une semaine déconnectée; un meilleur glasnost

This commit is contained in:
fpeters 2003-10-05 10:30:42 +00:00
parent 8469dd56a5
commit 347a8fdf1a
114 changed files with 4818 additions and 4512 deletions

View File

@ -13,3 +13,4 @@ tmp-system
tmp-tests
root-system
root-tests
talTranslations.py

View File

@ -129,6 +129,7 @@ archive: dist-clean
clean:
rm -rf tmp-system tmp-tests
rm -rf root-tests root-system
rm -f talTranslations.py
config: config.in
cat $^ | sed -e "s/^glasnost = .*/glasnost = $(GLASNOST)/g" \
@ -347,11 +348,15 @@ mo: po/glasnost-web/de.po \
msgfmt --statistics -c -v -o locale/fr/LC_MESSAGES/glasnost-web.mo po/glasnost-web/fr.po
msgfmt --statistics -c -v -o locale/sv/LC_MESSAGES/glasnost-web.mo po/glasnost-web/sv.po
talTranslations.py: templates/
./talGettext.py templates/ > talTranslations.py
po: glasnost-web/ \
shared/common/ \
shared/proxy/ \
shared/server/ \
shared/web/
shared/web/ \
talTranslations.py
cp po/glasnost-web/de.po po/glasnost-web/de.pox
cp po/glasnost-web/es.po po/glasnost-web/es.pox

View File

@ -27,27 +27,21 @@ plane - Plane
- Quality: ****
- Inspiration: default skin of Plane <http://www.plane.org>
lightbulb - Lightbulb
---------------------
- Colours: black on light blue; blues for decoration
- Navigation: one level, vertical, bottom-left
- Quality: ** (original but not for production use)
macfly - macfly
---------------
- Colours: black on orange; red/brown for misc elements
- Navigation: one level, vertical, right
- Quality: ****
- Inspiration: colour scheme from an example of CSS use (lost url)
- Inspiration: design idea and colour scheme from an example of CSS use
<http://www.projectseven.com/grafitti/jan2003/macfly/index.htm>
watercolor - Water Color
------------------------
- Colours: black on light blue; shades of blue
- Navigation: one level, vertical, top right
- Quality: ** (nice but lots of styles needed by Glasnost are not yet done)
- Quality: ****
- Inspiration: some watercolor metacity theme elements
@ -65,6 +59,7 @@ artus - artus (current version)
-------------------------------
- ARTUS (Code Lutin customer)
- Based on entrouvert2; should be removed
bxlug - BxLUG
-------------
@ -72,10 +67,25 @@ bxlug - BxLUG
- Bruxelles Linux User Group
- http://www.bxlug.be
codelutin.org - Code Lutin.org
------------------------------
- Code Lutin
- http://www.codelutin.org
crans - CRANS
-------------
- Cachan / Réseau @ Normale Sup'
- http://assoce.crans.org
- FIXME: /images/crans_banner.png missing
easter-eggs - Easter-eggs
-------------------------
- Proposal for http://www.easter-eggs.org
- Lacks several styles to be really used
- Bad coding style in CSS files
entrouvert.be - entrouvert.be
-----------------------------
@ -102,6 +112,7 @@ libre-entreprise - Libre-entreprise
-----------------------------------
- http://www.libre-entreprise.org and http://www.libre-entreprise.com
- TODO: add login button
rap - R.A.P. Belgique
---------------------
@ -110,28 +121,59 @@ rap - R.A.P. Belgique
- http://www.antipub.be
------
Others
------
lightbulb - Lightbulb
---------------------
- Colours: black on light blue; blues for decoration
- Navigation: one level, vertical, bottom-left
- hardcodes to many things
wretched - Wretched of the Earth
--------------------------------
- Colours: black on red
- lacks many styles
--------
Unsorted
--------
- chambon.raviart - Chambon.Raviart
[REMOVE]
- codelutin - Code Lutin
- codelutin.org - Code Lutin.org
- crans - CRANS
[REMOVE]
- cuisine - Cuisine (site pour les examples)
[REMOVE] [or modify to remove hardcoded strings]
- cyborg - Cyborg
- eclova - Eclova
[REMOVE] [or modify to be generic]
- entrouvert - entr'ouvert (first version)
[REMOVE]
- entrouvert2 - entr'ouvert (current version)
[hardcodes some strings]
- fsfeurope - FSF (~europe)
[REMOVE]
- glasnost - Glasnost
[REMOVE] [or modify to get in shape]
- glasnost2 - Glasnost 2
[default for now; should rename and remove background image]
- i3c - i3c
[nice one; should sort]
- in3activa - in3activa
[REMOVE]
- linuxdays - Luxembourg LinuxDays
[REMOVE] [despite nice colour scheme]
- pel-infini - infini (assoc brest)
[REMOVE]
- theridion - Theridion (new)
[REMOVE]
- upthings - upthings
[REMOVE]
- vecam - Vecam
- wretched - Wretched of the Earth
[REMOVE] [template now in metis]

View File

@ -27,7 +27,6 @@ WebDirectoryPath = %(webdir)s
[Mail]
# Email address to use when no admin has been defined in Glasnost
Admin = root@localhost
# website to show in emails sent to new people
Website = http://localhost
# Host name and port of the SMTP server

View File

@ -66,7 +66,7 @@ def monthTupleJS(year = 0, month = 0):
if (year, month, d) == today:
more = ' id="today"'
date = '%s-%02d-%02d' % (year, month, cal[i][j])
cal[i][j] = """<a href="#" onclick="selectDay('%s')"%s>%s</a>""" % \
cal[i][j] = '<a href="#" onclick="selectDay(\'%s\')"%s>%s</a>' % \
(date, more, cal[i][j])
return cal

View File

@ -160,7 +160,7 @@ class Application(applications.Application):
if session is not None:
getProxyForServerRole('sessions').setSession(session,
context.getVar('virtualHost').defaultDispatcherId)
except faults.MissingItem:
except (faults.MissingItem, faults.UnknownServerId):
if context.getVar('debug'):
raise
if req.caching:
@ -184,14 +184,9 @@ class Application(applications.Application):
req.cancel()
raise
t1 = context.getVar('t1')
open('/tmp/webbench', 'a+').write('%f %s\n' % (
time.time() - t1, req.unparsed_uri))
return result
def handler(self, req):
t1 = time.time()
# Use direct access to _req for speed.
try:
_req = req._req
@ -227,6 +222,7 @@ class Application(applications.Application):
dispatcherId = None,
fallbackTemplatesDirectoryPath = None,
function = None,
htmlHeaders = [],
httpHostName = None,
httpLocalPath = None,
# The HTTP path, without the httpScriptDirectoryPath prefix.
@ -249,7 +245,6 @@ class Application(applications.Application):
session = None,
sessionToken = None,
sessionTokenInCookie = 0, # Was the sessionToken stored in the url?
t1 = t1,
talEngine = None,
templateDirectoryName = None,
templatesDirectoryPath = None,
@ -353,12 +348,9 @@ class Application(applications.Application):
try:
virtualHost = virtualHostsWeb.getObjectByHostName(httpHostName)
except faults.MissingItem:
try:
virtualHost = virtualHostsWeb.getDefaultVirtualHost()
except faults.MissingItem:
if context.getVar('debug'):
raise
return HTTP_NOT_FOUND
if context.getVar('debug'):
raise
return HTTP_NOT_FOUND
except (faults.UnknownDispatcherInId, faults.UnknownServerId):
if context.getVar('debug'):
raise
@ -757,8 +749,6 @@ class Application(applications.Application):
data = zbuf.getvalue()
req.headers_out['Content-Encoding'] = 'gzip'
t1 = context.getVar('t1')
if not t1:
t1 = time.time()
if lastModTime:
req.headers_out['Last-Modified'] = time.strftime(
'%a, %d %b %Y %H:%M:%S GMT', lastModTime)
@ -770,9 +760,6 @@ class Application(applications.Application):
t = time.strptime(req.headers_in['If-Modified-Since'][:25],
'%a, %d %b %Y %H:%M:%S')
if lastModTime <= t:
open('/tmp/webbench', 'a+').write(
'%f %s (static, not mod)\n' % (
time.time() - t1, req.unparsed_uri))
return HTTP_NOT_MODIFIED
except KeyError:
pass
@ -785,8 +772,6 @@ class Application(applications.Application):
except IOError:
# the user probably cancelled the request
return OK
open('/tmp/webbench', 'a+').write('%f %s (static)\n' % (
time.time() - t1, req.unparsed_uri))
return OK
def parseHttpPath(self, remaining):
@ -857,12 +842,15 @@ class Application(applications.Application):
return None
if not 'pagenames' in context.getVar('knownRoles'):
return None
objectId = getWebForServerRole('pagenames').getIdByName(
remaining[0])
try:
objectId = getWebForServerRole('pagenames').getIdByName(
remaining[0])
except faults.UnknownServerId:
return None
if not objectId:
return None
context.setVar('dispatcherId',
commonTools.extractDispatcherId(objectId))
commonTools.extractDispatcherId(objectId))
context.setVar('serverRole', commonTools.extractRole(objectId))
context.setVar('objectId', objectId)
remaining = remaining[1:]
@ -1113,15 +1101,13 @@ class RequestCache:
context.getVar('varDirectoryPath'), 'webcache')
self.cacheFilePath = os.path.join(
self.cacheDirectoryPath,
self.getCacheFileName(self.unparsed_uri, language))
self.getCacheFileName(language))
self.cacheFilePathDepends = os.path.join(
self.cacheDirectoryPath,
self.getCacheFileName(self.unparsed_uri, language)
+ '.depends')
self.getCacheFileName(language) + '.depends')
self.cacheFilePathMimeType = os.path.join(
self.cacheDirectoryPath,
self.getCacheFileName(self.unparsed_uri, language)
+ '.mimetype')
self.getCacheFileName(language) + '.mimetype')
self.depends = []
def cancel(self):
@ -1189,8 +1175,13 @@ class RequestCache:
mimeType = 'text/html'
return cachePage, mimeType
def getCacheFileName(self, uri, language):
return binascii.hexlify(md5.new(uri + language).digest())
def getCacheFileName(self, language):
if self.headers_in.has_key('Host'):
hostName = self.headers_in['Host']
else:
hostName = ''
uri = self.unparsed_uri
return binascii.hexlify(md5.new(hostName + uri + language).digest())
def getExpires(self):
try:
@ -1240,13 +1231,14 @@ def handler(req):
# those are legitimate and should be raised to modpython handler
raise
except Exception, e:
if not commonTools.getConfig('Misc', 'SendTalkBackTo'):
raise
import traceback
import smtplib
f = cStringIO.StringIO()
traceback.print_exc(file = f)
message = """Subject: [%(host)s] Glasnost Talkback
f = f.getvalue()
if commonTools.getConfig('Misc', 'SendTalkBackTo'):
import smtplib
message = """Subject: [%(host)s] Glasnost Talkback
Version: %(version)s
Time: %(time)s
@ -1257,14 +1249,18 @@ Url: %(url)s
%(traceback)s
""" % { 'time': time.ctime(),
'host': socket.getfqdn(),
'traceback': f.getvalue(),
'traceback': f,
'version': glasnost.versionNumber,
'url': req.unparsed_uri}
server = smtplib.SMTP('localhost')
server.sendmail(
commonTools.getConfig('Misc', 'AdminEmailAddress'),
commonTools.getConfig('Misc', 'SendTalkBackTo'),
message)
server = smtplib.SMTP('localhost')
try:
server.sendmail(
commonTools.getConfig('Misc', 'AdminEmailAddress',
default = 'root@localhost'),
commonTools.getConfig('Misc', 'SendTalkBackTo'),
message)
except:
pass
raise
return result
@ -1279,6 +1275,7 @@ if webTools.getConfig('Profiling', 'false') == 'true':
globals(), locals())
except SystemExit:
pass
prof.dump_stats('/tmp/glasnost-web-%s.prof'%os.path.split(req.filename)[1])
prof.dump_stats('/tmp/glasnost-web-%s.prof' % \
os.path.split(req.filename)[1])
return result

View File

@ -9,6 +9,7 @@
font-weight: bold;
background-color: #ffffd1;
z-index: 1000;
margin: 2.5em 0 0 2em;
}
ul.tooltip {

View File

@ -141,14 +141,6 @@ table.spip th {
text-align: center;
}
.odd {
background-color: transparent;
}
.even {
background-color: #fafafa; /* very light grey */
}
table.rst td,
table.objects-table td,
table.spip td {
@ -252,7 +244,6 @@ p#powered-by-glasnost a {
}
.error-message {
text-align: center;
color: red;
display: block;
}

View File

@ -1,202 +1,100 @@
addEvent(window, "load", makeBalloonHelp);
var CURRENT_BALLOON_HELP;
var onLabels = 0;
document.getElementsByClassName = function ( class_name ) {
var all_obj, ret_obj = new Array(), j = 0, strict = 0;
if ( document.getElementsByClassName.arguments.length > 1 )
strict = ( document.getElementsByClassName.arguments[1] ? 1 : 0 );
if ( document.all )
all_obj = document.all;
else if ( document.getElementsByTagName && !document.all )
all_obj = document.getElementsByTagName ( "*" );
for ( i = 0; i < all_obj.length; i++ ) {
if ( ( ' ' + all_obj[i].getAttribute("class") + ' ').toLowerCase().match(
new RegExp ( ( strict ? '^ ' + class_name + ' $' :
'^.* ' + class_name + ' .*$' ).toLowerCase(),'g' ) ) ) {
ret_obj[j++] = all_obj[i];
}
}
return ret_obj;
}
var previousBalloon;
var currentBalloon;
var timeoutId;
var timeoutIdPrevious;
function makeBalloonHelp() {
if (!document.createElement) return;
var tagsHelp = new Array('tr', 'div');
for (var i=0; i<tagsHelp.length; i++) {
var tags = document.getElementsByTagName(tagsHelp[i]);
for (var tagi=0; tagi<tags.length; tagi++) {
tag = tags[tagi];
if (tag.className.indexOf('row') > -1) {
processElemForm(tag);
}
}
}
uls = document.getElementsByTagName("ul");
for (var uli=0; uli<uls.length; uli++) {
ul = uls[uli];
if (ul.nodeName == "UL" && ul.className == "appointment-details") {
processAppointment(ul);
}
var tags = document.getElementsByClassName('tooltip');
for (var i=0; i<tags.length; i++) {
tag = tags[i];
if (tag.id.substring(0, 3) != 'for' ) continue;
tag.style.display = 'none';
tag.style.visibility = 'visible';
parentTag = document.getElementById(tag.id.substring(4, tag.id.length));
if (! parentTag) continue;
if (parentTag.childNodes.length == 1 &&
parentTag.childNodes[0].nodeType != 3)
parentTag = parentTag.childNodes[0]
parentTag.balloonHelp = tag;
addEvent(parentTag, "mouseover", showBalloonHelp);
addEvent(parentTag, "focus", showBalloonHelp);
addEvent(parentTag, "mouseout", hideBalloonHelp);
addEvent(parentTag, "blur", hideBalloonHelp);
addEvent(parentTag, "keydown", hideBalloonHelp);
}
}
function prepareTag(elem, text) {
addEvent(elem, "mouseover", showBalloonHelp);
addEvent(elem, "mouseout", hideBalloonHelp);
addEvent(elem, "focus", showBalloonHelp);
addEvent(elem, "blur", hideBalloonHelp);
addEvent(elem, "keydown", hideBalloonHelp);
elem.setAttribute("balloon-help", text);
}
function processElemForm(elem) {
if (!elem.childNodes || elem.childNodes.length == 0) return;
var s = "";
for (var itemi=0;itemi<elem.childNodes.length;itemi++) {
var item = elem.childNodes[itemi];
if (item.nodeType == 3) continue;
if (item.className.indexOf("field-description") > -1) {
s = item.innerHTML;
if (onLabels == 1) {
t = 0;
while (elem.childNodes[t].nodeType == 3) t++;
item = elem.childNodes[t];
if (item.childNodes[0].nodeType != 3) {
item = item.childNodes[0];
}
prepareTag(item, s);
break;
}
continue;
}
if (item.className.indexOf("field-value") > -1 ||
item.className.indexOf("cell") > -1) {
if (s == "") continue;
var tagsArray = new Array('select', 'textarea', 'input');
for (var i=0; i<tagsArray.length; i++) {
tags = item.getElementsByTagName(tagsArray[i]);
for (var tagi=0; tagi<tags.length; tagi++) {
tag = tags[tagi];
prepareTag(tag, s);
}
if ( tags.length > 0 ) break;
}
}
}
}
function processAppointment(elem) {
if (!elem.childNodes || elem.childNodes.length == 0) return;
/* TODO */
}
/* Utility functions */
function addEvent(obj, evType, fn) {
/* adds an eventListener for browsers which support it
Written by Scott Andrew: nice one, Scott */
/* adds an eventListener for browsers which support it.
Derived from snippet by Scott Andrew */
if (obj.addEventListener) {
obj.addEventListener(evType, fn, true);
return true;
} else if (obj.attachEvent) {
var r = obj.attachEvent("on"+evType, fn);
return r;
} else {
return false;
}
if (obj.attachEvent)
return obj.attachEvent("on"+evType, fn);
return false;
}
function showBalloonHelp(e) {
if (!document.getElementsByTagName) return;
if (window.event && window.event.srcElement) {
el = window.event.srcElement
} else if (e && e.target) {
el = e.target
}
if (!el) return;
if (el.nodeType == 3) {
// lnk is a textnode -- ascend parents until we hit an input
el = getParent(el, "INPUT");
while (! el.balloonHelp ) {
el = el.parentNode;
}
if (!el) return;
balloonHelp = el.getAttribute("balloon-help");
tag = el.balloonHelp;
if (CURRENT_BALLOON_HELP) hideBalloonHelp(e);
var d = document.createElement("div");
d.className = "balloon-help";
tnt = document.createTextNode(balloonHelp);
pat = document.createElement("p");
pat.appendChild(tnt);
d.appendChild(pat);
STD_WIDTH = 300;
w = balloonHelp.length * 10;
if (w > STD_WIDTH) {
w = STD_WIDTH;
}
d.style.width = w + 'px';
if (currentBalloon && tag != currentBalloon)
hideBalloonHelp();
if (tag == previousBalloon)
return;
mx = findPosX(el);
my = findPosY(el);
d.style.left = (mx+15) + 'px';
d.style.top = (my+25) + 'px';
if (document.body && document.body.offsetWidth && ((mx+w) > document.body.offsetWidth)) {
d.style.left = (document.body.offsetWidth - w - 20) + "px";
}
document.getElementsByTagName("body")[0].appendChild(d);
CURRENT_BALLOON_HELP = d;
tag.style.display = 'block';
currentBalloon = tag;
clearTimeout(timeoutId);
timeoutId = setTimeout('hideBalloonHelp()', 3000);
}
function hideBalloonHelp(e) {
if (!document.getElementsByTagName) return;
if (CURRENT_BALLOON_HELP) {
document.getElementsByTagName("body")[0].removeChild(CURRENT_BALLOON_HELP);
CURRENT_BALLOON_HELP = null;
if (currentBalloon) {
currentBalloon.style.display = 'none';
previousBalloon = currentBalloon;
currentBalloon = null;
clearTimeout(timeoutIdPrevious);
timeoutIdPrevious = setTimeout('clearPrevious()', 5000);
}
}
// Add an eventListener to browsers that can do it somehow.
// Originally by the amazing Scott Andrew.
function addEvent(obj, evType, fn) {
if (obj.addEventListener) {
obj.addEventListener(evType, fn, true);
return true;
} else if (obj.attachEvent) {
var r = obj.attachEvent("on"+evType, fn);
return r;
} else {
return false;
}
}
function getParent(el, pTagName) {
if (el == null) return null;
if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase())
// Gecko bug, supposed to be uppercase
return el;
return getParent(el.parentNode, pTagName);
}
function findPosX(obj)
{
var curleft = 0;
if (obj.offsetParent) {
while (obj.offsetParent) {
curleft += obj.offsetLeft
obj = obj.offsetParent;
}
}
else if (obj.x)
curleft += obj.x;
return curleft;
}
function findPosY(obj)
{
var curtop = 0;
if (obj.offsetParent) {
while (obj.offsetParent) {
curtop += obj.offsetTop
obj = obj.offsetParent;
}
}
else if (obj.y)
curtop += obj.y;
return curtop;
function clearPrevious(e) {
previousBalloon = null;
}

View File

@ -84,22 +84,26 @@ def index():
import re
for article in articles.values():
if article.format == 'spip':
links = [x[10:].strip() for x in re.findall(r'->article +\d+', article.body)]
links = [x[10:].strip() for x in re.findall(r'->article +\d+',
article.body)]
for l in links:
id = '%s/articles/%s' % (dispatcherId, l)
d[id] = 1
links = [x[8:].strip() for x in re.findall(r'->alias +[\w\-_]+', article.body)]
links = [x[8:].strip() for x in re.findall(r'->alias +[\w\-_]+',
article.body)]
for l in links:
if not pagenames.has_key(l):
print 'Wrong pagename: %s' % l
continue
d[pagenames[l]] = 1
elif article.format == 'rst':
links = [x[10:].strip() for x in re.findall(r'<article +\d+', article.body)]
links = [x[10:].strip() for x in re.findall(r'<article +\d+',
article.body)]
for l in links:
id = '%s/articles/%s' % (dispatcherId, l)
d[id] = 1
links = [x[8:].strip() for x in re.findall(r'<alias +[\w\-_]+', article.body)]
links = [x[8:].strip() for x in re.findall(r'<alias +[\w\-_]+',
article.body)]
for l in links:
if not pagenames.has_key(l):
# print 'Wrong pagename: %s' % l

View File

@ -9,7 +9,7 @@ then
fi
echo "Installing glasnost://system environment in root-system/"
make config-system install \
rm config && make config config-system install \
GLASNOST=glasnost-system PORT=8500 \
PREFIX=`pwd`/root-system/usr/local \
VARPREFIX=`pwd`/root-system/var/lib/ \
@ -18,7 +18,16 @@ make config-system install \
SERVER_USER=`id -u` SERVER_GROUP=`id -u` \
WEB_USER=`id -u` WEB_GROUP=`id -u` &> /dev/null
$ROOT_SBIN/glasnost-system-ctl start
SERVERS="Dispatcher ArticlesServer AuthenticationServer \
AuthenticationLoginPasswordServer CardsServer DataflowsServer \
GroupsServer PeopleServer VirtualHostsServer UploadFilesServer \
PageNamesServer TranslationsServer"
echo "Starting Glasnost servers..."
for SERVER in $SERVERS
do
$ROOT_SBIN/glasnost-system-ctl start-one $SERVER
done
(cd tmp-system && ./generate-system.py) < /dev/null
$ROOT_SBIN/glasnost-system-ctl stop

View File

@ -8,7 +8,7 @@ fi
echo "Installing test environment in root-tests/"
rm -rf root-tests && mkdir root-tests 2> /dev/null
make config-tests install \
rm config && make config config-tests install \
GLASNOST=glasnost-tests PORT=8500 \
PREFIX=`pwd`/root-tests/usr/local \
VARPREFIX=`pwd`/root-tests/var/lib/ \
@ -17,7 +17,15 @@ make config-tests install \
SERVER_USER=`id -u` SERVER_GROUP=`id -u` \
WEB_USER=`id -u` WEB_GROUP=`id -u` &> /dev/null
root-tests/usr/local/sbin/glasnost-tests-ctl start
(cd tmp-tests && ./launch.py $1)
SERVERS="Dispatcher ArticlesServer AtomsServer AuthenticationServer \
AuthenticationLoginPasswordServer CardsServer DataflowsServer \
GroupsServer PeopleServer VirtualHostsServer"
echo "Starting Glasnost servers..."
for SERVER in $SERVERS
do
root-tests/usr/local/sbin/glasnost-tests-ctl start-one $SERVER
done
(cd tmp-tests && python ./tests.py)
root-tests/usr/local/sbin/glasnost-tests-ctl stop

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -174,6 +174,9 @@ class AppointmentsServer(AppointmentsCommonMixin, ObjectsServer):
def addObjectXmlRpc(self, objectImport):
objectId = ObjectsServer.addObjectXmlRpc(self, objectImport)
return objectId
# TODO: proper notification email
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
object = virtualServer.loadObjectCore(objectId)

View File

@ -74,7 +74,9 @@ class VcfParser(saxlib.XMLReader) :
if m :
vobjname = m.group(1)
if self._handle_namespaces:
self._cont_handler.startElementNS((EMPTY_NAMESPACE,vobjname),vobjname,AttributesNSImpl({},{}))
self._cont_handler.startElementNS(
(EMPTY_NAMESPACE, vobjname),
vobjname, AttributesNSImpl({}, {}))
else:
self._cont_handler.startElement(vobjname,AttributesImpl({}))
@ -83,7 +85,8 @@ class VcfParser(saxlib.XMLReader) :
if m :
vobjname = m.group(1)
if self._handle_namespaces:
self._cont_handler.endElementNS((EMPTY_NAMESPACE,vobjname),vobjname)
self._cont_handler.endElementNS(
(EMPTY_NAMESPACE, vobjname), vobjname)
else:
self._cont_handler.endElement(vobjname)
else :
@ -113,13 +116,15 @@ class VcfParser(saxlib.XMLReader) :
attrs[(EMPTY_NAMESPACE,'x-name')] = propname
propname = 'extension'
propvalue = unicode(to_xml_string(propvalue,'iso-8859-1'),'UTF-8')
# <=> to the above line, but doesn't work with python
# versions <2.0
#propvalue = unicode(propvalue,'iso-8859-1')
self._cont_handler.startElementNS((EMPTY_NAMESPACE,propname),propname,AttributesNSImpl(attrs,qnames))
propvalue = unicode(propvalue, 'iso-8859-1')
self._cont_handler.startElementNS(
(EMPTY_NAMESPACE, propname),
propname, AttributesNSImpl(attrs, qnames))
self._cont_handler.characters(propvalue)
self._cont_handler.endElementNS((EMPTY_NAMESPACE,propname),propname)
self._cont_handler.endElementNS(
(EMPTY_NAMESPACE, propname),
propname)
data = nextLine
file.close()
@ -128,20 +133,23 @@ class VcfParser(saxlib.XMLReader) :
return self._handle_namespaces
elif name == saxlib.feature_namespace_prefixes:
return 0
raise saxlib.SAXNotRecognizedException("Feature '%s' not recognized" % name)
raise saxlib.SAXNotRecognizedException(
"Feature '%s' not recognized" % name)
def setFeature(self, name, value):
if name == saxlib.feature_namespaces:
self._handle_namespaces = value
else:
raise saxlib.SAXNotRecognizedException("Feature '%s' not recognized" % name)
raise saxlib.SAXNotRecognizedException(
"Feature '%s' not recognized" % name)
def getProperty(self, name):
if name == saxlib.property_lexical_handler:
return self._lex_handler
elif name == saxlib.property_declaration_handler:
return self._decl_handler
raise saxlib.SAXNotRecognizedException("Property '%s' not recognized" % name)
raise saxlib.SAXNotRecognizedException(
"Property '%s' not recognized" % name)
def setProperty(self, name, value):
if name == saxlib.property_lexical_handler:
@ -149,73 +157,6 @@ class VcfParser(saxlib.XMLReader) :
elif name == saxlib.property_declaration_handler:
self._decl_handler = value
else:
raise saxlib.SAXNotRecognizedException("Property '%s' not recognized" % name)
raise saxlib.SAXNotRecognizedException(
"Property '%s' not recognized" % name)
xslt = '''<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" encoding="ISO-8859-1"/>
<xsl:strip-space elements='*'/>
<xsl:template match='/VCALENDAR'>BEGIN:VCALENDAR
<xsl:apply-templates/>END:VCALENDAR
</xsl:template>
<xsl:template match='VEVENT'>BEGIN:VEVENT
<xsl:apply-templates/>END:VEVENT
</xsl:template>
<xsl:template match='VTODO'>BEGIN:VTODO
<xsl:apply-templates/>END:VTODO
</xsl:template>
<xsl:template match='*[text()]'>
<xsl:choose>
<xsl:when test='name()="extension"'>
<xsl:value-of select='@x-name'/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select='name()'/>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates select='@*[name()!="x-name"]'/>:<xsl:value-of select='text()'/><xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match='@*'>;<xsl:value-of select='name()'/>=<xsl:value-of select='.'/></xsl:template>
</xsl:transform>'''
#---------------------------------------------------------------------
# VCalendar file to DOM
def load_vcal_to_dom(uri) :
parser=VcfParser()
reader = Sax2.Reader(0, 0, None, Sax2.XmlDomGenerator, parser)
return reader.fromUri(uri)
# DOM to VCalendar file
def write_dom_to_vcal(doc, uri):
new_api = 0
try:
from Ft.Xml.Xslt.Processor import Processor
try:
from Ft.Xml.InputSource import InputSourceFactory,InputSource
except:
new_api = 1
except:
from xml.xslt.Processor import Processor
processor = Processor()
if not new_api:
processor.appendStylesheetString(xslt)
result = processor.runNode(doc,1,{},None)
else:
self.inputsourcefactory = InputSourceFactory()
self.processor.appendStylesheet(self.inputsourcefactory.fromString(
xslt, 'dummy'))
dom = self.processor.execute(doc,InputSource(None,"dummy"), 1, {},
None)
file = open(uri, 'w')
file.write(result)
file.close()

View File

@ -163,7 +163,7 @@ class AuthenticationLoginPasswordVirtualServer(AdministrableVirtualServer):
del self.authentications
self.markCoreAsDirty()
return
raise faults.WrongLogin(partialAccount[0])
raise faults.WrongLogin(authenticationObject.login)
def emailAdminsForNewUser(self, object, authenticationObject):
virtualServerId = context.getVar('applicationId')
@ -209,12 +209,14 @@ For more information about this user, please see:
def emailPasswordToUser(self, object, authenticationObject):
emailAddress = getEmailForObject(object)
if not emailAddress:
print 'Not sending because no email address'
return
if not self.getServer().getAdminCore().stockPasswordsInClearText:
# TODO: mail user explaining we can generate a new password for
# him and provide him with an url with a token (so that others
# can't force password changes)
print 'Not sending because passwords are not in plain text'
return
toAddress = [emailAddress]
@ -290,14 +292,20 @@ The Glasnost administrator - %(fromAddress)s
result.append((userId, cleanedAuthObject.exportToXmlRpc()))
return result
def getAccountUserId(self, authenticationObject):
if not self.getServer().isAdmin():
raise faults.UserAccessDenied()
def getAccountUserIdPrivate(self, authenticationObject):
if self.authentications is not None:
for userId, authObject in self.authentications.items():
if authObject.login == authenticationObject.login:
return userId
raise faults.WrongLogin(authenticationObject.login)
return ''
def getAccountUserId(self, authenticationObject):
if not self.getServer().isAdmin():
raise faults.UserAccessDenied()
userId = self.getAccountUserIdPrivate(authenticationObject)
if not userId:
raise faults.WrongLogin(authenticationObject.login)
return userId
def getAdminEmailAddresses(self, stopAsap = 0):
virtualServerId = context.getVar('applicationId')
@ -370,7 +378,7 @@ class AuthenticationLoginPasswordServer(
authenticationObject = commonTools.importThing(authenticationDict)
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
userId = virtualServer.getAccountUserId(authenticationObject)
userId = virtualServer.getAccountUserIdPrivate(authenticationObject)
userObject = getObject(userId)
virtualServer.emailPasswordToUser(userObject, authenticationObject)

View File

@ -395,3 +395,4 @@ dispatcher = Dispatcher()
if __name__ == "__main__":
dispatcher.launch(applicationName, applicationRole)

View File

@ -115,8 +115,7 @@ class VirtualHost(ObjectServerMixin, VirtualHostCommon):
def modify(self, changes, givenSlotNames = None):
objectsByHostName = self.getServer().virtualServer.objectsByHostName
hostName = self.hostName
ObjectServerMixin.modify(
self, changes, givenSlotNames = givenSlotNames)
ObjectServerMixin.modify(self, changes, givenSlotNames = givenSlotNames)
if self.hostName != hostName:
if hostName is not None:
del objectsByHostName[hostName]
@ -229,13 +228,6 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
def exportVirtualServer(self, virtualServerId, exportDirectoryPath):
return None
def getDefaultVirtualHost(self):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
if not virtualServer.admin.defaultVirtualHostId:
raise faults.MissingItem('default virtual host')
return self.getObjectXmlRpc(self.admin.defaultVirtualHostId)
def getHostNameXmlRpc(self):
"""Return the url of the virtual server."""
@ -250,27 +242,37 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
raise faults.MissingItem(dispatcherId)
def getObjectByHostName(self, hostName):
"""Return the first virtual host with the given host name."""
"""Return the virtual host with the given host name."""
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
askedHostName = hostName
if not virtualServer.objectsByHostName:
# The is no virtual host defined. Create one with the requested
# There is no virtual host defined. Create one with the requested
# host name.
object = commonTools.newThing(
'object', 'virtualhosts.VirtualHost')
object = commonTools.newThing('object', 'virtualhosts.VirtualHost')
object.title = 'Glasnost'
object.hostName = hostName
object.defaultDispatcherId = 'glasnost://%s' % hostName
object.language = 'en'
self.addObjectXmlRpc(object.exportToXmlRpc())
if not virtualServer.objectsByHostName.has_key(hostName):
for k in virtualServer.objectsByHostName.keys():
if fnmatch(hostName, k):
# hostNames, without eventual www.
hostNames = virtualServer.objectsByHostName.keys()
hostNames.sort(lambda x,y: -cmp(len(x), len(y)))
for k in hostNames:
if fnmatch(hostName, '*.'+k):
hostName = k
break
else:
raise faults.MissingItem(hostName)
if not virtualServer.admin.defaultVirtualHostId:
raise faults.MissingItem(hostName)
try:
object = virtualServer.objects[
virtualServer.admin.defaultVirtualHostId]
except KeyError:
raise faults.MissingItem(hostName)
return object
object = virtualServer.objectsByHostName[hostName]
return object
@ -292,14 +294,18 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
return 0
def hasHostNameXmlRpc(self, hostName):
# note that this method may return false while getObjectByHostName
# returns something
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
hostName = iso8859_15(hostName)
if virtualServer.objectsByHostName.has_key(hostName):
return 1
for k in virtualServer.objectsByHostName.keys():
if fnmatch(hostName, k):
return 1
#hostNames = virtualServer.objectsByHostName.keys()
#hostNames.sort(lambda x,y: -cmp(len(x), len(y)))
#for k in hostNames:
# if fnmatch(hostName, '*.'+k):
# return 1
return 0
def importVirtualServer(self, virtualServerId, importDirectoryPath):
@ -317,8 +323,6 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
def registerPublicMethods(self):
ObjectsServer.registerPublicMethods(self)
self.registerPublicMethod('getHostName', self.getHostNameXmlRpc)
self.registerPublicMethod('getDefaultVirtualHost',
self.getDefaultVirtualHost)
self.registerPublicMethod('getObjectByHostName',
self.getObjectByHostNameXmlRpc)
self.registerPublicMethod('getObjectIdByHostName',
@ -375,7 +379,7 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
def updateApacheVHost(self, object):
"""Update the apache virtual host configuration.
Get the apache config template from the vistual host server data
Get the apache config template from the virtual host server data
directory.
Create the apache vhost files and fill them to add the given object as
a new virtual host.
@ -395,7 +399,7 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
created.
*IOError*:
The vhost file cannot be writen, or the templace config file cannot
The vhost file cannot be written, or the template config file cannot
be read.
"""

View File

@ -77,6 +77,7 @@ class AppointmentCommon(ObjectCommon):
creationTime_kindName = 'CreationTime'
end = None
end_kind_stateInViewMode = 'read-only/hidden-if-empty'
end_kindName = 'Time'
participantsSet = None
@ -112,34 +113,42 @@ class AppointmentCommon(ObjectCommon):
result = ''
return result
def getLabel(self):
def getLabel(self, withDate = 0, withHour = 0):
title = self.getTitle()
if title is None:
return ''
hourTime = self.getBeginningHourAndMinute()
if hourTime:
when = '%s %s' % (
time.strftime('%d/%m/%Y', time.localtime(self.start)),
hourTime)
else:
when = time.strftime('%d/%m/%Y', time.localtime(self.start))
dateTime = self.getDateTime(withDate, withHour)
if dateTime:
return '%s - %s' % (dateTime, title)
return title
return '%s - %s' % (when, title)
def getDateTime(self, withDate = 0, withHour = 0):
hourTime = ''
if withHour:
hourTime = self.getBeginningHourAndMinute()
date = ''
if withDate:
date = time.strftime('%d/%m/%Y', time.localtime(self.start))
if not date and not hourTime:
return ''
return ' '.join([date, hourTime])
def getTitle(self):
return self.title
def getBeginningHourAndMinute(self):
"""Returns a string with the start time of the appointment (or None
if no time set)"""
"""Returns a string with the start time of the appointment (or an empty
string if no time set)"""
hour = '%02d:%02d' % time.localtime(self.start)[3:5]
if hour == '00:00' and not self.end:
return None
return ''
if self.end:
hourEnd = '%02d:%02d' % time.localtime(self.end)[3:5]
if hour == '00:00' and self.end - self.start < 86400 and \
hourEnd == '23:59':
return None
return ''
return hour
def getEndHourAndMinute(self):

View File

@ -98,6 +98,7 @@ class VirtualHostCommon(ObjectCommon):
hostName_kind_isTranslatable = 0
hostName_kind_label = N_('Web Host Name')
hostName_kind_widget_size = 40
hostName_kind_widgetName = 'Url'
hostName_kindName = 'String'
modificationTime = None
@ -109,6 +110,9 @@ class VirtualHostCommon(ObjectCommon):
serverRole = 'virtualhosts'
# TODO: everything so that it is editable by user
showTooltips = 0 # FIXME: default should be true
templateDirectoryName = 'glasnost2'
templateDirectoryName_kind_balloonHelp = N_(
'Select the template (skin) to use for this host.')

View File

@ -138,6 +138,7 @@ class BaseThing:
thingCategory = 'other'
thingCategory_kind_importExport = 'private'
thingCategory_kind_isRequiredInEditMode = 1
thingCategory_kind_isTranslatable = 0
thingCategory_kind_label = N_('Internal Category')
thingCategory_kind_stateInEditMode = 'hidden'
thingCategory_kind_stateInViewMode = 'hidden'
@ -146,6 +147,7 @@ class BaseThing:
thingName = None
thingName_kind_importExport = 'private'
thingName_kind_isRequiredInEditMode = 1
thingName_kind_isTranslatable = 0
thingName_kind_label = N_('Internal Name')
thingName_kind_stateInEditMode = 'hidden'
thingName_kind_stateInViewMode = 'hidden'

View File

@ -455,6 +455,19 @@ class aliasUrl(rootUrl):
action = ''
return '%s%s%s' % (path, self.alias, action)
class fileUrl(rootUrl):
filename = None
def __init__(self, filename):
rootUrl.__init__(self)
self.filename = filename
def getPath(self, **keywords):
path = rootUrl.getPath(self, **keywords)
if path[-1] == '/' and self.filename[0] == '/':
path = path[:-1]
return path +