annotate libervia/web/server/constants.py @ 1598:86c7a3a625d5

server: always start a new session on connection: The session was kept when a user was connecting from service profile (but not from other profiles), this was leading to session fixation vulnerability (an attacker on the same machine could get service profile session cookie, and use it when a victim would log-in). This patch fixes it by always starting a new session on connection. fix 443
author Goffi <goffi@goffi.org>
date Fri, 23 Feb 2024 13:35:24 +0100
parents 7941444c1671
children 5d9889f14012
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1239
f511f8fbbf8a fixed shebangs
Goffi <goffi@goffi.org>
parents: 1237
diff changeset
1 #!/usr/bin/env python3
f511f8fbbf8a fixed shebangs
Goffi <goffi@goffi.org>
parents: 1237
diff changeset
2
1595
7941444c1671 pages: set `own_local_jid` to avoid confusion with `own_jid`:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
3 # Libervia web frontend
7941444c1671 pages: set `own_local_jid` to avoid confusion with `own_jid`:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
4 # Copyright (C) 2009-2023 Jérôme Poisson (goffi@goffi.org)
317
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
5
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
6 # This program is free software: you can redistribute it and/or modify
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
7 # it under the terms of the GNU Affero General Public License as published by
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
8 # the Free Software Foundation, either version 3 of the License, or
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
9 # (at your option) any later version.
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
10
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
11 # This program is distributed in the hope that it will be useful,
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
14 # GNU Affero General Public License for more details.
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
15
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
16 # You should have received a copy of the GNU Affero General Public License
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
18
860
05cd9dc775e6 server: use of relative import instead of try/except block in server/constants
Goffi <goffi@goffi.org>
parents: 856
diff changeset
19 from ..common import constants
317
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
20
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
21
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
22 class Const(constants.Const):
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
23
1397
ed037818d6de core (constants): renaming following global project renaming
Goffi <goffi@goffi.org>
parents: 1396
diff changeset
24 APP_NAME = "Libervia Web"
ed037818d6de core (constants): renaming following global project renaming
Goffi <goffi@goffi.org>
parents: 1396
diff changeset
25 APP_COMPONENT = "web"
ed037818d6de core (constants): renaming following global project renaming
Goffi <goffi@goffi.org>
parents: 1396
diff changeset
26 APP_NAME_ALT = APP_NAME
ed037818d6de core (constants): renaming following global project renaming
Goffi <goffi@goffi.org>
parents: 1396
diff changeset
27 APP_NAME_FILE = "libervia_web"
1402
388558a30cf8 core (config): use component (i.e. "web") as config section
Goffi <goffi@goffi.org>
parents: 1397
diff changeset
28 CONFIG_SECTION = APP_COMPONENT.lower()
1479
095e94ca6728 pages: disable CSRF token check when service profile is used:
Goffi <goffi@goffi.org>
parents: 1435
diff changeset
29 # the Libervia profile that is used for public operations (when nobody is connected)
095e94ca6728 pages: disable CSRF token check when service profile is used:
Goffi <goffi@goffi.org>
parents: 1435
diff changeset
30 SERVICE_PROFILE = "libervia"
317
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
31
993
641664553a41 server: changed session timeout from 5 min to 2h, avoiding undesired disconnection on Libervia pages.
Goffi <goffi@goffi.org>
parents: 990
diff changeset
32 SESSION_TIMEOUT = 7200 # Session's timeout, after that the user will be disconnected
449
981ed669d3b3 /!\ reorganize all the file hierarchy, move the code and launching script to src:
souliane <souliane@mailoo.org>
parents: 445
diff changeset
33 HTML_DIR = "html/"
703
1a19ee7d8d8a server_side: add default theme
souliane <souliane@mailoo.org>
parents: 685
diff changeset
34 THEMES_DIR = "themes/"
823
027139763511 server (blog): cleaning & improvments:
Goffi <goffi@goffi.org>
parents: 818
diff changeset
35 THEMES_URL = "themes"
317
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
36 MEDIA_DIR = "media/"
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
37 CARDS_DIR = "games/cards/tarot"
1216
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
38 PAGES_DIR = "pages"
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
39 TASKS_DIR = "tasks"
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
40 LIBERVIA_CACHE = "libervia"
1246
aaf28d45ae67 pages: browser code, first draft:
Goffi <goffi@goffi.org>
parents: 1239
diff changeset
41 SITE_NAME_DEFAULT = "default"
1257
1ec41ac1e7cf server: seperation between production build dir and dev build dir:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
42 # generated files will be accessible there
1216
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
43 BUILD_DIR = "__b"
1246
aaf28d45ae67 pages: browser code, first draft:
Goffi <goffi@goffi.org>
parents: 1239
diff changeset
44 BUILD_DIR_DYN = "dyn"
1257
1ec41ac1e7cf server: seperation between production build dir and dev build dir:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
45 # directory where build files are served to the client
1ec41ac1e7cf server: seperation between production build dir and dev build dir:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
46 PRODUCTION_BUILD_DIR = "sites"
1ec41ac1e7cf server: seperation between production build dir and dev build dir:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
47 # directory used for files needed temporarily (e.g. for compiling other files)
1ec41ac1e7cf server: seperation between production build dir and dev build dir:
Goffi <goffi@goffi.org>
parents: 1253
diff changeset
48 DEV_BUILD_DIR = "dev_build"
317
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
49
1216
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
50 TPL_RESOURCE = '_t'
1127
9234f29053b0 server, pages: update to handle multi sites themes, first draft:
Goffi <goffi@goffi.org>
parents: 1124
diff changeset
51
317
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
52 ERRNUM_BRIDGE_ERRBACK = 0 # FIXME
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
53 ERRNUM_LIBERVIA = 0 # FIXME
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
54
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
55 # Security limit for Libervia (get/set params)
338
80016abf3ad3 server_side: raised default security_limit to 5
Goffi <goffi@goffi.org>
parents: 317
diff changeset
56 SECURITY_LIMIT = 5
317
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
57
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
58 # Security limit for Libervia server_side
bbadd490e63c misc: gather the constants in a single file, as it is done for other frontends
souliane <souliane@mailoo.org>
parents:
diff changeset
59 SERVER_SECURITY_LIMIT = constants.Const.NO_SECURITY_LIMIT
605
917e271975d9 server + browser side: implementation of new getEntitiesData bridge method + added a security check: only a white list of entities can be gotten
Goffi <goffi@goffi.org>
parents: 555
diff changeset
60
917e271975d9 server + browser side: implementation of new getEntitiesData bridge method + added a security check: only a white list of entities can be gotten
Goffi <goffi@goffi.org>
parents: 555
diff changeset
61 # keys for cache values we can get from browser
1113
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
62 ALLOWED_ENTITY_DATA = {"avatar", "nick"}
823
027139763511 server (blog): cleaning & improvments:
Goffi <goffi@goffi.org>
parents: 818
diff changeset
63
027139763511 server (blog): cleaning & improvments:
Goffi <goffi@goffi.org>
parents: 818
diff changeset
64 STATIC_RSM_MAX_LIMIT = 100
027139763511 server (blog): cleaning & improvments:
Goffi <goffi@goffi.org>
parents: 818
diff changeset
65 STATIC_RSM_MAX_DEFAULT = 10
027139763511 server (blog): cleaning & improvments:
Goffi <goffi@goffi.org>
parents: 818
diff changeset
66 STATIC_RSM_MAX_COMMENTS_DEFAULT = 10
917
86563d6c83b0 server: Libervia pages:
Goffi <goffi@goffi.org>
parents: 861
diff changeset
67
86563d6c83b0 server: Libervia pages:
Goffi <goffi@goffi.org>
parents: 861
diff changeset
68 ## Libervia pages ##
1216
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
69 PAGES_META_FILE = "page_meta.py"
1246
aaf28d45ae67 pages: browser code, first draft:
Goffi <goffi@goffi.org>
parents: 1239
diff changeset
70 PAGES_BROWSER_DIR = "_browser"
1253
6d49fae517ba pages: browser metadata + root `_browser`:
Goffi <goffi@goffi.org>
parents: 1248
diff changeset
71 PAGES_BROWSER_META_FILE = "browser_meta.json"
1113
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
72 PAGES_ACCESS_NONE = (
1216
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
73 "none"
1113
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
74 ) #  no access to this page (using its path will return a 404 error)
1216
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
75 PAGES_ACCESS_PUBLIC = "public"
1113
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
76 PAGES_ACCESS_PROFILE = (
1216
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
77 "profile"
1113
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
78 ) # a session with an existing profile must be started
1216
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
79 PAGES_ACCESS_ADMIN = "admin" #  only profiles set in admins_list can access the page
1113
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
80 PAGES_ACCESS_ALL = (
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
81 PAGES_ACCESS_NONE,
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
82 PAGES_ACCESS_PUBLIC,
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
83 PAGES_ACCESS_PROFILE,
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
84 PAGES_ACCESS_ADMIN,
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
85 )
990
6daa59d44ee2 pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents: 985
diff changeset
86 # names of the page to use for menu
1113
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
87 DEFAULT_MENU = [
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
88 "login",
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
89 "chat",
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
90 "blog",
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
91 "forums",
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
92 "photos",
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
93 "files",
1508
ec3ad9abf9f9 pages (calendar): calendar page, first draft
Goffi <goffi@goffi.org>
parents: 1479
diff changeset
94 "calendar",
1113
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
95 "events",
1378
e3e303a30a74 pages (tickets): renamed "tickets" to "lists":
Goffi <goffi@goffi.org>
parents: 1296
diff changeset
96 "lists",
1113
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
97 "merge-requests",
1517
b8ed9726525b browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents: 1508
diff changeset
98 "calls"
1248
9b865f2604a9 server (constants): temporarily removed `app` from menu
Goffi <goffi@goffi.org>
parents: 1246
diff changeset
99 # XXX: app is not available anymore since removal of pyjamas code with Python 3
9b865f2604a9 server (constants): temporarily removed `app` from menu
Goffi <goffi@goffi.org>
parents: 1246
diff changeset
100 # port. It should come back at a later point with an alternative (Brython
9b865f2604a9 server (constants): temporarily removed `app` from menu
Goffi <goffi@goffi.org>
parents: 1246
diff changeset
101 # probably).
1113
cdd389ef97bc server: code style reformatting using black
Goffi <goffi@goffi.org>
parents: 1111
diff changeset
102 ]
922
16d1084d1371 server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents: 917
diff changeset
103
957
67bf14c91d5c server (pages): added a confirm flag on successful post:
Goffi <goffi@goffi.org>
parents: 956
diff changeset
104 ## Session flags ##
1216
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
105 FLAG_CONFIRM = "CONFIRM"
962
c7fba7709d05 Pages: various improvments:
Goffi <goffi@goffi.org>
parents: 957
diff changeset
106
c7fba7709d05 Pages: various improvments:
Goffi <goffi@goffi.org>
parents: 957
diff changeset
107 ## Data post ##
1216
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
108 POST_NO_CONFIRM = "POST_NO_CONFIRM"
957
67bf14c91d5c server (pages): added a confirm flag on successful post:
Goffi <goffi@goffi.org>
parents: 956
diff changeset
109
931
8a393ae90f8c server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents: 922
diff changeset
110 ## HTTP methods ##
1216
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
111 HTTP_METHOD_GET = b"GET"
b2d067339de3 python 3 port:
Goffi <goffi@goffi.org>
parents: 1173
diff changeset
112 HTTP_METHOD_POST = b"POST"
931
8a393ae90f8c server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents: 922
diff changeset
113
922
16d1084d1371 server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents: 917
diff changeset
114 ## HTTP codes ##
956
dabecab10faa server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents: 934
diff changeset
115 HTTP_SEE_OTHER = 303
1019
34240d08f682 pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents: 1005
diff changeset
116 HTTP_NOT_MODIFIED = 304
922
16d1084d1371 server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents: 917
diff changeset
117 HTTP_BAD_REQUEST = 400
16d1084d1371 server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents: 917
diff changeset
118 HTTP_UNAUTHORIZED = 401
1173
0f37b65fe7c2 server: replaced wrong usage of C.HTTP_UNAUTHORIZED by C.HTTP_FORBIDDEN
Goffi <goffi@goffi.org>
parents: 1146
diff changeset
119 HTTP_FORBIDDEN = 403
922
16d1084d1371 server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents: 917
diff changeset
120 HTTP_NOT_FOUND = 404
934
a21fee7e30ee server (constants): added HTTP_INTERNAL_ERROR and HTTP_SERVICE_UNAVAILABLE
Goffi <goffi@goffi.org>
parents: 931
diff changeset
121 HTTP_INTERNAL_ERROR = 500
1296
b1215347b5c3 pages (bridge): better handling of errors:
Goffi <goffi@goffi.org>
parents: 1275
diff changeset
122 HTTP_PROXY_ERROR = 502
934
a21fee7e30ee server (constants): added HTTP_INTERNAL_ERROR and HTTP_SERVICE_UNAVAILABLE
Goffi <goffi@goffi.org>
parents: 931
diff changeset
123 HTTP_SERVICE_UNAVAILABLE = 503
985
64826e69f365 pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents: 964
diff changeset
124
1435
396d5606477f server (proxy): add "Forwarded" and "X-Forwarded-xxx" headers to reverse proxy
Goffi <goffi@goffi.org>
parents: 1402
diff changeset
125 ## HTTP HEADERS ##
396d5606477f server (proxy): add "Forwarded" and "X-Forwarded-xxx" headers to reverse proxy
Goffi <goffi@goffi.org>
parents: 1402
diff changeset
126 H_FORWARDED = "Forwarded"
396d5606477f server (proxy): add "Forwarded" and "X-Forwarded-xxx" headers to reverse proxy
Goffi <goffi@goffi.org>
parents: 1402
diff changeset
127 H_X_FORWARDED_FOR = "X-Forwarded-For"
396d5606477f server (proxy): add "Forwarded" and "X-Forwarded-xxx" headers to reverse proxy
Goffi <goffi@goffi.org>
parents: 1402
diff changeset
128 H_X_FORWARDED_HOST = "X-Forwarded-Host"
396d5606477f server (proxy): add "Forwarded" and "X-Forwarded-xxx" headers to reverse proxy
Goffi <goffi@goffi.org>
parents: 1402
diff changeset
129 H_X_FORWARDED_PROTO = "X-Forwarded-Proto"
396d5606477f server (proxy): add "Forwarded" and "X-Forwarded-xxx" headers to reverse proxy
Goffi <goffi@goffi.org>
parents: 1402
diff changeset
130
396d5606477f server (proxy): add "Forwarded" and "X-Forwarded-xxx" headers to reverse proxy
Goffi <goffi@goffi.org>
parents: 1402
diff changeset
131
985
64826e69f365 pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents: 964
diff changeset
132 ## Cache ##
64826e69f365 pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents: 964
diff changeset
133 CACHE_PUBSUB = 0
1019
34240d08f682 pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents: 1005
diff changeset
134
34240d08f682 pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents: 1005
diff changeset
135 ## Date/Time ##
34240d08f682 pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents: 1005
diff changeset
136 HTTP_DAYS = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
1127
9234f29053b0 server, pages: update to handle multi sites themes, first draft:
Goffi <goffi@goffi.org>
parents: 1124
diff changeset
137 HTTP_MONTH = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
9234f29053b0 server, pages: update to handle multi sites themes, first draft:
Goffi <goffi@goffi.org>
parents: 1124
diff changeset
138 "Nov", "Dec")