| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- from direct.task import Task
- from direct.http import WebRequest
- from direct.directnotify import DirectNotifyGlobal
- import random, string
- class webNotifyDebug:
- def __init__(self, portNumber = 8888, username = None, password = None):
- self.portNumber = portNumber
- self.username = username
- self.password = password
- self.passwordProtect = False
- self.pageToHit = 'debug'
- self.authTokens = []
- self.web = WebRequest.WebRequestDispatcher()
- self.web.listenOnPort(int(self.portNumber))
- # 'debug' will be the name of the page we have to hit
- # If both a username and password should be specified, then
- # we will need to present a username and password prompt to the user
- if self.username and self.password:
- # set self.passwordProtect to True
- self.passwordProtect = True
- # Register 'debug' with the password prompt
- self.web.registerGETHandler('debug', self.passwordPrompt)
- self.web.registerGETHandler('authDebug', self.authDebug)
- self.pageToHit = 'authDebug'
- else:
- self.web.registerGETHandler('debug', self.debug)
- self.startCheckingIncomingHTTP()
- def passwordPrompt(self, replyTo, **kw):
- # This should get called if we need to prompt the user for
- # a username and password.
- try:
- username = kw['username']
- password = kw['password']
- except KeyError:
- # the user is probably making their initial connection to the
- # password protected site. Present them with the login page
- replyTo.respond('<HTML>\n<HEAD><TITLE>Direct Notify Web Interface - Username and Password Required</TITLE></HEAD>\n<BODY>\n<FONT SIZE=4>Username/Password authentication has been enabled. You must provide the following before gaining access to the system:<P><FORM action="debug" method="get">\nUsername: <INPUT type="text" name="username"><BR>\nPassword: <INPUT type="password" name="password"><BR>\n<input type=submit name="Submit" text="Login"></form>\n</BODY></HTML>')
- return
- # If the username and password are correct, we need to generate an
- # auth token and place it in self.authTokens. If the username and
- # password are incorrect. Return an error message indicating such.
- if username == self.username and password == self.password:
- # Username and Password match
- # Generate auth token
- authToken = self.genToken()
- # Place the authToken in the list of valid auth tokens
- self.authTokens.append(authToken)
-
- replyTo.respond('<HTML><HEAD><TITLE>Username and Password Good</TITLE></HEAD><BODY>Username and Password are good, please remember to logout when done. <A HREF=authDebug?authToken=%s>Click here to continue</a></BODY></HTML>' % (authToken))
- return
- else:
- replyTo.respond('Username and/or password are incorrect')
- return
- def listAllCategories(self, replyTo, optionalMessage = None, authToken = None):
- # Return a web page with a list of all registered notify categories
- # along with an HTML widget to chage their debug state
- completeList = DirectNotifyGlobal.directNotify.getCategories()
- # Define the static head of the response
- if not optionalMessage:
- head = '<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<title>DirectNotify - List All Categories</title>\n</head>\n<body>\n<h1 style="text-align: center;">DirectNotify - Listing All Categories</h1>\n<CENTER><table style="text-align: left;" border="1" cellpadding="2" cellspacing="2">\n<tbody>\n<tr><th>Category</th><th>Debug Status</th></tr>\n'
- else:
- head = '<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<title>DirectNotify - List All Categories</title>\n</head>\n<body>\n<h1 style="text-align: center;">DirectNotify - Listing All Categories</h1>\n<CENTER><HR>%s<HR><BR><table style="text-align: left;" border="1" cellpadding="2" cellspacing="2">\n<tbody>\n<tr><th>Category</th><th>Debug Status</th></tr>\n' % (optionalMessage)
- # define the static foot
- if authToken:
- foot = '</tbody></table></CENTER><BR><A HREF="%s?authToken=%s">Main Menu</a></body></html>' % (self.pageToHit, authToken)
- else:
- foot = '</tbody></table></CENTER><BR><A HREF="%s">Main Menu</a></body></html>' % self.pageToHit
- # Sort our catagory list into alpha order
- completeList.sort()
- # Now generate the body of the page response
- body = ''
- for item in completeList:
- select = '<tr><td>%s</td><td style="text-align: center;">' % (item)
- tempCategory = DirectNotifyGlobal.directNotify.getCategory(item)
- debugStatus = tempCategory.getDebug()
- if debugStatus == 0:
- if authToken:
- body = '%s%s<A HREF="%s?command=on&item=%s&authToken=%s">Off</a></td></tr>' % (body, select, self.pageToHit, item, authToken)
- else:
- body = '%s%s<A HREF="%s?command=on&item=%s">Off</a></td></tr>' % (body, select, self.pageToHit, item)
- else:
- if authToken:
- body = '%s%s<A HREF="%s?command=off&item=%s&authToken=%s">On</a></td></tr>' % (body, select, self.pageToHit, item, authToken)
- else:
- body = '%s%s<A HREF="%s?command=off&item=%s">On</a></td></tr>' % (body, select, self.pageToHit, item)
- replyTo.respond('%s\n%s\n%s\n' % (head, body, foot))
- def turnCatOn(self, item, replyTo, sString = None, authToken = None):
- # Used to turn a catagory (item), to the on state
- try:
- notifyItem = DirectNotifyGlobal.directNotify.getCategory(item)
- notifyItem.setDebug(1)
- updateMessage = 'Category <b>%s</b>, has been turned on' % (item)
- if not sString:
- self.listAllCategories(replyTo, updateMessage, authToken)
- else:
- self.searchForCat(sString, replyTo, updateMessage, authToken)
- except AttributeError:
- replyTo.respond('Invalid Category Passed')
- def turnCatOff(self, item, replyTo, sString = None, authToken = None):
- # Used to turn a catagory (item), to the off state
- try:
- notifyItem = DirectNotifyGlobal.directNotify.getCategory(item)
- notifyItem.setDebug(0)
- updateMessage = 'Category <b>%s</b>, has been turned off' % (item)
- if not sString:
- self.listAllCategories(replyTo, updateMessage, authToken)
- else:
- self.searchForCat(sString, replyTo, updateMessage, authToken)
- except AttributeError:
- replyTo.respond('Invalid Category Passed')
- def searchForCat(self, searchString, replyTo, toggle = None, authToken = None):
- # Used to execute a substring search for a category
- completeList = DirectNotifyGlobal.directNotify.getCategories()
- resultList = []
- while completeList:
- item = completeList.pop()
- if item.find(searchString) != -1:
- resultList.append(item)
- # Now that we have the results, present them
- # First, sort the list
- resultList.sort()
- if not toggle:
- head = '<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<title>DirectNotify - Search Results</title>\n</head>\n<body>\n<h1 style="text-align: center;">DirectNotify - Listing All Categories</h1>\n<CENTER><table style="text-align: left;" border="1" cellpadding="2" cellspacing="2">\n<tbody>\n<tr><th>Category</th><th>Debug Status</th></tr>\n'
- else:
- head = '<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<title>DirectNotify - Search Results</title>\n</head>\n<body>\n<h1 style="text-align: center;">DirectNotify - Listing All Categories</h1>\n<CENTER><HR>%s<HR><br><table style="text-align: left;" border="1" cellpadding="2" cellspacing="2">\n<tbody>\n<tr><th>Category</th><th>Debug Status</th></tr>\n' % (toggle)
- if authToken:
- foot = '</tbody></table></CENTER><BR><A HREF="authDebug?authToken=%s">Main Menu</a></body></html>' % (authToken)
- else:
- foot = '</tbody></table></CENTER><BR><A HREF="debug">Main Menu</a></body></html>'
- body = ''
- for item in resultList:
- select = '<tr><td>%s</td><td style="text-align: center;">' % (item)
- tempCategory = DirectNotifyGlobal.directNotify.getCategory(item)
- debugStatus = tempCategory.getDebug()
- if debugStatus == 0:
- if authToken:
- body = '%s%s<A HREF="%s?command=on&item=%s&sString=%s&authToken=%s">Off</a></td></tr>' % (body, select, self.pageToHit, item, searchString, authToken)
- else:
- body = '%s%s<A HREF="%s?command=on&item=%s&sString=%s">Off</a></td></tr>' % (body, select, self.pageToHit, item, searchString)
- else:
- if authToken:
- body = '%s%s<A HREF="%s?command=off&item=%s&sString=%s&authToken=%s">On</a></td></tr>' % (body, select, self.pageToHit, item, searchString, authToken)
- else:
- body = '%s%s<A HREF="%s?command=off&item=%s&sString=%s">On</a></td></tr>' % (body, select, self.pageToHit, item, searchString)
- replyTo.respond('%s\n%s\n%s\n' % (head, body, foot))
- def debug(self, replyTo, **kw):
- try:
- authToken = kw['authToken']
- except KeyError:
- authToken = None
- try:
- command = kw['command']
- if command == 'listAll':
- if self.passwordProtect:
- self.listAllCategories(replyTo, None, authToken)
- else:
- self.listAllCategories(replyTo)
- elif command == 'on':
- item = kw['item']
- try:
- sString = kw['sString']
- if self.passwordProtect:
- self.turnCatOn(item, replyTo, sString, authToken)
- else:
- self.turnCatOn(item, replyTo, sString)
- except KeyError:
- if self.passwordProtect:
- self.turnCatOn(item, replyTo, None, authToken)
- else:
- self.turnCatOn(item, replyTo)
- elif command == 'off':
- item = kw['item']
- try:
- sString = kw['sString']
- if self.passwordProtect:
- self.turnCatOff(item, replyTo, sString, authToken)
- else:
- self.turnCatOff(item, replyTo, sString)
- except KeyError:
- if self.passwordProtect:
- self.turnCatOff(item, replyTo, None, authToken)
- else:
- self.turnCatOff(item, replyTo)
- elif command == 'search':
- searchString = kw['searchString']
- if self.passwordProtect:
- self.searchForCat(searchString, replyTo, None, authToken)
- else:
- self.searchForCat(searchString, replyTo)
- elif command == 'logOff' and authToken:
- self.logOut(replyTo, authToken)
- else:
- replyTo.respond('Error: Invalid args')
- return
- except KeyError:
- pass
- # Basic Index Page
- if not authToken:
- replyTo.respond('<html><head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<title>DirectNotify Web Interface</title>\n</head>\n<body>\n<div style="text-align: center;">\n<h1>DirectNotify Web Interface</h1>\n</div>\n<hr style="height: 2px;">\n<form method="get" action="debug" name="searchfom"><INPUT TYPE=HIDDEN NAME="command" VALUE="search">Search for a DirectNotify Category: <input name="searchString"> <input type=submit name="Submit"></button><br>\n</form>\n<br>\n<A HREF="%s?command=listAll">Display all DirectNotify Categories</a>\n</body>\n</html>' % (self.pageToHit))
- else:
- replyTo.respond('<html><head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<title>DirectNotify Web Interface</title>\n</head>\n<body>\n<div style="text-align: center;">\n<h1>DirectNotify Web Interface</h1>\n</div>\n<hr style="height: 2px;">\n<form method="get" action="authDebug" name="searchfom"><INPUT TYPE=HIDDEN NAME="command" VALUE="search"><INPUT TYPE=HIDDEN NAME="authToken" VALUE="%s">Search for a DirectNotify Category: <input name="searchString"> <input type=submit name="Submit"></button><br>\n</form>\n<br>\n<A HREF="%s?command=listAll&authToken=%s">Display all DirectNotify Categories</a><BR>\n<A HREF="authDebug?command=logOff&authToken=%s">Log Off</a></body>\n</html>' % (authToken, self.pageToHit, authToken, authToken))
- def logOut(self, replyTo, authToken):
- # Delete token from auth list
- self.authTokens.remove(authToken)
- replyTo.respond('<HTML><HEAD><TITLE>Logout Sucessful</TITLE></HEAD>\n<BODY>Logout complete. You will need to login again to use the system</BODY>\n</HTML>')
- def authDebug(self, replyTo, **kw):
- try:
- authToken = kw['authToken']
- try:
- pos = self.authTokens.index(authToken)
- except ValueError:
- # authToken passed is not in the list
- replyTo.respond('Error: Client not authorized')
- return
- except (ValueError, KeyError):
- # authToken not passed in GET. Return an error
- replyTo.respond('Error: No auth token passed from client')
- return
- # If we've gotten this far, we have determined that an auth token was
- # passed in the HTTP GET and it is on the list of auth tokens.
- # Now we can pass this to the normal debug URI
- kw['authToken'] = authToken
- self.debug(replyTo, **kw)
- def startCheckingIncomingHTTP(self):
- taskMgr.remove('pollDirectDebugHTTPTask')
- taskMgr.doMethodLater(0.3,self.pollDirectDebugHTTPTask,'pollDirectDebugHTTPTask')
- def stopCheckingIncomingHTTP(self):
- taskMgr.remove('pollDirectDebugHTTPTask')
- def pollDirectDebugHTTPTask(self,task):
- self.web.poll()
- return Task.again
- def genToken(self):
- alpha = string.letters.upper()
- num = string.digits
- ranNumber = ''
- ranAlpha = ''
- for i in range(3):
- ranNumberOne = ranNumber + random.choice(num)
- for i in range(3):
- ranAlphaOne = ranAlpha + random.choice(alpha)
- for i in range(3):
- ranNumberTwo = ranNumber + random.choice(num)
- for i in range(3):
- ranAlphaTwo = ranAlpha + random.choice(alpha)
- token = "%s%s%s%s" % (ranAlphaOne, ranNumberOne, ranAlphaTwo, ranNumberTwo)
- return token
|