📄 web.py
字号:
#! python
#
# $Workfile: Web.py $ $Revision: 18 $
# $Date: 10/07/01 1:50p $ $Author: Sholden $
#
import os, base64
import cgi
import mx.DateTime as mxdt
import mx.DateTime.ARPA as arpa
import Cookie
import Params
from dtuple import TupleDescriptor, DatabaseTuple
from dbsource import dbsource
import pyforms
from cachequery import CacheQuery
from Error import Error
try:
pageformat = open("index.htm", "r").read()
except:
import sys
sys.exit("Cannot read 'index.htm'")
conn = dbsource().conn
cursor = conn.cursor()
StdNames = ["StdEmail", "StdFirstName", "StdLastName", "StdPhone",
"StdPasswd", "StdAddress", "StdCity", "StdState", "StdPostCode"]
qStud = CacheQuery("Student", StdNames, ("StdEmail", ), conn)
class Page:
"""Implement common page behavior, with basic look-and-feel.
This is the ultimate ancestor class for all pages."""
def __init__(self, op, path, query, session, headers,
oHeaders=None, Realm=None, Initpath=""):
"""Build the page to prepare for content generation."""
self.op = op
self.path = path
self.query = query
self.session = session
self.headers = headers
self.oheaders = oHeaders or []
self.realm = Realm
self.initpath = Initpath or []
self.message = "OK Content Follows"
self.returncode = 200
self.mimetype = "text/html"
def Generate(self, Input=None):
self.input = Input
try:
self.Authenticate()
return self.HTTP(self.Content())
except Error, error:
self.returncode, self.message, self.realm, \
self.oheaders, self.errmsg, self.errcontent = error()
self.mimetype = "text/html"
return self.HTTP(self.Content())
def Authenticate(self):
realm = self.Realm()
if not realm: # no authentication required
return
else: # verify authentication
try:
passwd = self.session._auth[realm]["password"]
# Already authenticated for the realm
return
except KeyError:
# Check authentication credentials in HTTP headers
auth = self.headers.getheader("authorization")
if auth:
auth = auth.split()
if auth[0].lower() == "basic": # username:password
auth = base64.decodestring(auth[1]).split(":")
self.session._auth[realm] = {"email": auth[0].lower()}
# Retrieve authentication data from realm table
a = Params.RealmAuth.get(realm, None)
if a: # Always fail if no data for the realm
stmt ="SELECT %s FROM %s WHERE %s = ?" % (a[2], a[0], a[1])
cursor.execute(stmt, (auth[0].lower(), ))
pw = cursor.fetchall()
if pw and pw[0][0].lower() == auth[1].lower():
self.session._auth[realm]["password"] = pw[0][0]
# This realm is authenticated for the first time
if realm == "PythonTeach":
self.session._udata = qStud(auth[0])[0]
return
# No credential is present for this realm, so we require
# authentication. If the browser stops trying, the content
# we return instead of the page offers the password via
# email. Email is only sent to users in the database!
raise Error(401, "Authentication required", realm,
oheaders=['WWW-Authenticate: Basic realm="%s"' % realm],
errmsg="""Authentication Required<BR><BR>
Would you like an <BR>
<A HREF="/MailPass/%s/"> email password reminder</A>?<BR><BR>
Or do you want to <BR>
<A HREF="/NewAccount/%s/">open a new account</A>?
""" % (realm, realm))
def Content(self):
"""Return content when authentication not required or known good.
If error occurred, generate standard or abbreviated page depending
on whether the error overrode the errcontent argument."""
if self.returncode == 200:
return pageformat % (self.Title(), self.session._id, self.NavBar(), self.Body())
elif self.errcontent is None:
return pageformat % (self.Title(), self.session._id, self.NavBar(), self.ErrMsg())
else:
return self.errcontent
def HTTP(self, content):
return \
"""HTTP/1.0 %d %s
Content-Type: %s
Content-Length: %d
Date: %s
%s
%s
%s""" % (self.ReturnCode(), self.Message(), self.MIMEtype(), len(content),
arpa.str(mxdt.now()), self.Cookie(), self.Headers(), content)
def ErrMsg(self):
return """<FONT SIZE="+1" COLOR="RED"><B>Error Response<BR></FONT>
<FONT SIZE="+1" COLOR="RED">%d <I>%s</I></B></FONT>""" % \
(self.ReturnCode(), self.errmsg)
def Body(self):
return "Error: Web.Page subclass %s requires Body() method" % str(self.__class__)
def Cookie(self):
cookie = Cookie.SimpleCookie()
cookie["session"] = "%s:%d" % (self.session._id, id(self.session))
cookie["session"]["path"] = "/"
#cookie["session"]["expires"] = "31 Dec 2002" # Seems to make it permanent
return str(cookie)
def Message(self):
return self.message
def MIMEtype(self):
return self.mimetype
def NavBar(self, Home=0):
try:
name = "%s %s<BR>" % (self.session._udata.StdFirstName,
self.session._udata.StdLastName)
except AttributeError:
name = ""
if self.session._bookings:
checkout = """<A HREF="/CourseViewCart/">Shopping Cart</A><BR>"""
else:
checkout = ""
return """
<table border="0" cellpadding="0" cellspacing="0" width="158">
<tr>
<td width="10" valign="top">
<img src="/images/spacer.gif" width="10" height="5" border="0"></td>
<td class="navtext" width="148">
<img src="/images/spacer.gif" width="5" height="5" border="0"><br>
<b>%s%s</b></td>
</tr>
</table>
%s
%s
%s
%s
""" % (name, checkout, self.NavSection("/", "home"),
self.NavSection("/DeptStart/", "departments", self.DeptNav()),
self.NavSection("/CourseStart/", "courses", self.CourseNav()),
self.NavSection("/Auth/Usrs/", "PythonTeach", self.PTNav()))
def NavLink(self, p):
return """
<a href="%s">%s</a><br>
<img alt="" src="/images/spacer.gif" width="5" height="2" border="0"><br>""" % p
def NavSection(self, link, graphic, extra=""):
return """
<a href="%s"><img src="/images/%s.gif" width="158" height="22" border="0"></a><br>
<table border="0" cellpadding="0" cellspacing="0" width="158">
<tr>
<td width="10" valign="top">
<img src="/images/spacer.gif" width="10" height="10" border="0"></td>
<td class="navtext" width="148">
%s<img src="/images/spacer.gif" width="5" height="5" border="0"><br>
</td>
</tr>
</table>
""" % (link, graphic, extra)
def DeptNav(self):
return ""
def CourseNav(self):
return ""
def PTNav(self):
return ""
def Headers(self):
if self.oheaders:
return "\n".join(self.oheaders)+"\n"
else:
return "\n"
def Realm(self):
"""Return the authentication realm, if any."""
return self.realm
def ReturnCode(self):
return self.returncode
def Title(self):
return "Error: Web.Page subclass %s requires Title() method" % str(self.__class__)
def ChkReqd(self, FD, udata):
"""Return list of errors concerning required fields."""
errors = []
# Verify that required fields are present
for field in FD:
field = DatabaseTuple(pyforms.Descriptor(), field)
if "R" in field.Options:
if not udata[field.FieldName]:
errors.append("%s is required" % field.Description)
# Verify that passwords in the form agree
if udata.StdPasswd != self.input["StdPasswd+"]:
errors.append("Passwords did not agree")
return errors
def getValidForm(self):
try:
FD = self.session._fd
if not FD:
raise AttributeError # session timeout?
if self.session._secureform:
# raise AttributeError if FD is not same as form._Flist_
if str(id(FD)) != self.input["_Flist_"]:
# print "Form ID mismatch!!!!!"
raise AttributeError
self.session._fd = None # can only ask this question once!
except (AttributeError, KeyError):
raise Error(400, "Bad Request",
errmsg="""Non-matching form ID<BR>
<FONT SIZE="-1">
Form identity not recognized.
</FONT><BR>We log all potential
abuse to safeguard member privacy.
""")
return FD
def test():
import rfc822, StringIO, Session
h = rfc822.Message(StringIO.StringIO(""))
s = Session.Session(1)
p = Page("GET", ["one", "two"], {}, s, h, Realm="staff")
print ":::::401 Error:::::\n", p.Generate(), "=================================="
p = Page("GET", ["one", "two"], {}, s, h, Realm=None)
print ":::::200 Page:::::\n", p.Generate(), "=================================="
ha = rfc822.Message(StringIO.StringIO("Authorization: Basic c3RldmU6ZGFwcGxl\n\n"))
p = Page("GET", ["one", "two"], {}, s, ha, Realm="Staff")
print ":::::Good authentication:::::\n", p.Generate(), "=================================="
if __name__ == "__main__":
import rfc822, StringIO, Session
h = rfc822.Message(StringIO.StringIO(""))
s = Session.Session(1)
p = Page("GET", ["one", "two"], {}, s, h, Realm="staff")
print p.NavBar()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -