Hello everybody,
I've tried for the last 4 hours to have my web.py application working
with sessions in apache+mod_wsgi, but could not make it.
I've looked in docs, tutorials, searched on google, but could not find
anything...
I'm using web.py 0.3, with python 2.5 and mod_wsgi 2.3
I'm creating a simple document management interface for an association
I'm member of, and I need to use sessions for login states.
Using the web.py integrated server, I've got everything working, with
both a datastore file or db based (the db was sqlite, if it counts).
Now, I've switched to apache as the web server, and nothing works
anymore.
First, my code:
class config:
def __init__(self):
self.curPath = os.path.dirname(__file__)
self.basePath=os.path.join(self.curPath,'..')
self.storePath = os.path.join(self.basePath, 'files')
self.tplPath=os.path.join(self.basePath,'tpl/')
self.sessPath=os.path.join(self.basePath,'sess/')
self.dbPath=os.path.join(self.basePath,'sqlite')
self.dbFile='arcenciel.sqlite3'
self.finalDb=os.path.join(self.dbPath, self.dbFile)
self.debugMode=False
self.frmHome = form.Form(
form.Password('pwd', description='Veuillez donner votre nouveau
mot de passe'),
form.Password('pwd2', description='Veullez retaper votre nouveau
mot de passe'),
form.Button("submit", type="submit", description="Changer de mot
de passe"),
)
self.frmLogin = form.Form(
form.Textbox('username', description="Utilisateur"),
form.Password('pwd', description='Mot de passe'),
form.Button("submit", type="submit",
description="S'authentifier"),
)
self.frmNewFolder=form.Form(
form.Textbox('folderName', description='Donnez le nom du dossier
à créer'),
form.Button("submit", type="submit", description="Créer le
dossier"),
)
self.frmUp=form.Form(
form.File('newFile', description='Fichier à transmettre' ),
form.Button("submit", type="submit", description="Créer le
dossier"),
)
cfg=config()
web.config.debug = cfg.debugMode
app = web.application(urls, globals())
db=web.database(dbn='sqlite', db=cfg.finalDb)
sessVals={'logged': False,
'msg':'',
'user':'',
'uid':False,
}
store = web.session.DBStore(db, 'sessions')
#store = web.session.DiskStore(cfg.curPath+'/sess')
session = web.session.Session(app, store, initializer=sessVals)
The path have all been checked, and they are correct, with permissions
relaxed enough for apache to open/read the files.
the cfg.finalDb resolves to "/var/www/arc_en_ciel/htdocs/../sqlite/
arcenciel.sqlite3", which is an sqlite3 database I created using the
sqlite cli tools.
cfg.debugMode is False, just as a security.
When I enter my first page, I've declared
web.debug(session)
to see the session content.
From an web.py server, the result is:
<Storage {'msg': u'Erreur de connection.', 'ip': u'127.0.0.1',
'logged': False, 'session_id':
'3f63b62e016a10b8db33a7ef98bc35b712fd0f40'}>
From apache, the result is
<Storage {}>, referer:
http://aec.dev/base.py/
Of course, the same file is used each time.
Has anyone ever faced this situation ?
I'm just "that" close to throw web.py away and redo this with django,
but I love web.py simplicity sooooo much more that it would really
hurt.
The complete code is:
#!/bin/python
# -*- coding: utf-8 -*-
import web, os, os.path, stat
import mimetypes
from web import form
urls = (
'/' , 'login',
'/login/' , 'login',
'/upload/(.*)$' , 'upload',
'/newFolder/(.*)' , 'newFolder',
'/del/(.*)' , 'delete',
'/search/(.*)$' , 'search',
'/browse/(.*)$' , 'browse',
'/download/(.*)$' , 'download',
'/my(.*)' , 'home',
'/sess' , 'sess',
)
#DONE: login
#DONE: navigation dans le repository
#DONE: ajouter une page de changement des infos persos
#DONE: download des fichiers
#DONE: upload des fichiers
#TODO: indexage des fichiers uploadés
def walktree (top = ".", depthfirst = True):
names = os.listdir(unicode(top))
if not depthfirst:
yield top, names
for name in names:
if name.startswith('.')==False:
try:
st = os.lstat(os.path.join(top, name))
except os.error:
continue
if depthfirst:
yield top, names
def getMsg():
ret=''
if session.get('msg','')!='':
ret=session.msg
session.msg=''
return ret
def parentPath(opath):
aryTmp=opath.split(os.path.sep)
path=''
for i in aryTmp[:-1]:
path=os.path.join(path, i)
return path
def cleanPath(path):
return path.replace('//','/')
class config:
def __init__(self):
self.curPath = os.path.dirname(__file__)
self.basePath=os.path.join(self.curPath,'..')
self.storePath = os.path.join(self.basePath, 'files')
self.tplPath=os.path.join(self.basePath,'tpl/')
self.sessPath=os.path.join(self.basePath,'sess/')
self.dbPath=os.path.join(self.basePath,'sqlite')
self.dbFile='arcenciel.sqlite3'
self.finalDb=os.path.join(self.dbPath, self.dbFile)
self.debugMode=False
self.frmHome = form.Form(
form.Password('pwd', description='Veuillez donner votre nouveau
mot de passe'),
form.Password('pwd2', description='Veullez retaper votre nouveau
mot de passe'),
form.Button("submit", type="submit", description="Changer de mot
de passe"),
)
self.frmLogin = form.Form(
form.Textbox('username', description="Utilisateur"),
form.Password('pwd', description='Mot de passe'),
form.Button("submit", type="submit",
description="S'authentifier"),
)
self.frmNewFolder=form.Form(
form.Textbox('folderName', description='Donnez le nom du dossier
à créer'),
form.Button("submit", type="submit", description="Créer le
dossier"),
)
self.frmUp=form.Form(
form.File('newFile', description='Fichier à transmettre' ),
form.Button("submit", type="submit", description="Créer le
dossier"),
)
cfg=config()
web.config.debug = cfg.debugMode
app = web.application(urls, globals())
db=web.database(dbn='sqlite', db=cfg.finalDb)
sessVals={'logged': False,
'msg':'',
'user':'',
'uid':False,
}
store = web.session.DBStore(db, 'sessions')
#store = web.session.DiskStore(cfg.curPath+'/sess')
session = web.session.Session(app, store, initializer=sessVals)
#===============================================================================
# if web.config.get('_session') is None:
# session = web.session.Session(app, store, sessVals)
# web.config._session = session
# else:
# session = web.config._session
#===============================================================================
session.logged=False
cfg.app=app
rdr = web.template.render(cfg.tplPath)
application = web.application(urls, globals()).wsgifunc()
class dbg:
def GET(self):
return rdr.debug(cfg.curPath, cfg.basePath, cfg.storePath,
cfg.finalDb, os.path.join(cfg.curPath, 'sess'))
class login:
'''
Let the users login
'''
def GET(self):
web.debug(session)
web.debug(db)
session.logged=False
msg=getMsg()
if session.logged==False:
return rdr.welcome(cfg.frmLogin, msg)
else:
web.redirect('/browse/')
def POST(self):
i=web.input()
ret=False
if i.username!='' and i.pwd!='':
ret=db.select('users',where='lower(username)=\'%s\' and password=
\'%s\''%(i.username, i.pwd))
cpt=0
for row in ret:
cpt+=1
uid=row.userid
if cpt==1:
session.logged=True
session.user=i.username
session.id=uid
web.redirect('/browse/')
else:
session.msg='Erreur de connection.'.decode('utf-8')
web.redirect('/')
else:
session.msg='Pas de mot de passe spécifié'.decode('utf-8')
web.redirect('/')
class newFolder:
def GET(self, path):
return rdr.newFolder(cleanPath(path), cfg.frmNewFolder, '')
def POST(self, path):
path=cleanPath(path)
i=web.input()
msg=''
try:
os.mkdir(os.path.join(cfg.storePath, path, i.folderName))
except OSError, err:
msg='Erreur lors de la création du dossier %s: %s'.decode
('utf-8')%(i.folderName, err)
finally:
if msg=='':
web.redirect('/browse/%s'%(path))
else:
return rdr.newFolder(path, cfg.frmNewFolder, msg)
class delete:
def GET(self, opath):
opath=cleanPath(opath.encode('utf-8'))
finPath=os.path.join(cfg.storePath, opath)
path=parentPath(opath)
try:
if os.path.isdir(finPath):
trg='dossier'
os.rmdir(finPath)
else:
trg='fichier'
os.unlink(finPath)
except OSError, err:
session.msg='Erreur lors de la supression du %s %s: %s'.decode
('utf-8')%(trg, opath, err)
finally:
web.redirect('/browse/%s'%(path))
class upload:
'''
Upload a file in a given directory.
'''
def GET(self, path):
path=cleanPath(path)
msg=getMsg()
return rdr.upload(cfg.frmUp, path, msg)
def POST(self, path):
path=cleanPath(path.encode('utf-8'))
x = web.input(newFile={})
finPath=os.path.join(unicode(cfg.storePath), unicode(path), x
['newFile'].filename.decode('utf-8'))
web.debug(finPath)
web.debug(len(x['newFile'].value))
try:
h=open(finPath.encode('utf-8'),'wb+')
h.write(x['newFile'].value)
h.close()
raise web.seeother('/browse/%s'%(path))
except UnicodeEncodeError, err:
session.msg=err
return web.redirect('/upload/%s'%(path))
class browse:
'''
Browse the filesystem
'''
def GET(self, path=None):
if session.logged!=True:
web.redirect('/login/')
else:
#present a view of the fs files uploaded
if path==None or path=='':
path=cfg.storePath
path=cleanPath(path)
aryTmp=path.replace(cfg.storePath,'').split(os.path.sep)
#check if we are at the top level
top=''
for x in aryTmp[:-1]:
top=os.path.join(top, x)
if top=='' and aryTmp[0]=='':
top=False
aryDirs=[]
aryFiles=[]
#get list of files and dir in the current directory.
for (basepath, children) in walktree(os.path.join
(cfg.storePath,path.encode('utf-8')),False):
for child in children:
if child.startswith('.')==False:
fullPath=os.path.join(unicode(basepath), child.decode
('utf-8'))
parent=parentPath(fullPath.replace(cfg.storePath,''))
o={'name':child, 'base':basepath, 'full':fullPath,
'parent':parent, 'short':fullPath.replace(cfg.storePath+'/','')}
if os.path.isdir(fullPath.encode('utf-8')):
#print 'adding %s to dirs'%child
aryDirs.append(o)
else:
#print 'adding %s to files'%child
aryFiles.append(o)
#end if
#end for
#end for
if path!=cfg.storePath:
loc=path+'/'
else:
loc=''
loc=cleanPath(loc)
msg=getMsg()
return rdr.browse(aryDirs, aryFiles, top, loc, msg, 'browse')
pass
def POST(self):
pass
class home:
def GET(self, jnk):
if session.msg!='':
msg=session.msg
session.msg=''
else:
msg=''
return rdr.home(session, cfg.frmHome, msg)
def POST(self, jnk):
i=web.input()
ret=False
if i.pwd!=i.pwd2:
#pwd mismatch
session.msg="Les mots de passes ne sont pas identiques.<br/
>Veuillez ré-essayer."
web.redirect('/my/')
else:
#update pwd
q="update users set password='%s' where userid='%d'"%(i.pwd,
session.id)
db.update('users',where="userid='%d'"%
session.id,
password=i.pwd)
msg='Votre mot de passe à été mis à jour'
return rdr.home(session, cfg.frmHome, msg)
class download:
def GET(self, path):
path=cleanPath(path.encode('utf-8'))
finPath=os.path.join(cfg.storePath,path)
mimetypes.init()
mime=mimetypes.guess_type(path, True)[0]
web.header('Content-Type', mime)
h=open(finPath)
x=h.read()
h.close()
return x
class search:
'''
Search the indexed files for a given string
'''
def GET(self):
pass
def POST(self):
pass
if __name__ == "__main__":
app.run()