Remove unused direct.http package
This commit is contained in:
parent
32367fcbdc
commit
77bf02742b
|
|
@ -1,19 +0,0 @@
|
|||
import xml.etree.ElementTree as ET
|
||||
|
||||
class HTMLTree(ET.ElementTree):
|
||||
def __init__(self, title):
|
||||
root = ET.Element('HTML')
|
||||
ET.ElementTree.__init__(self, root)
|
||||
|
||||
head = ET.SubElement(root, 'HEAD')
|
||||
titleTag = ET.SubElement(head, 'TITLE')
|
||||
titleTag.text = title
|
||||
|
||||
body = ET.SubElement(root, 'BODY')
|
||||
|
||||
def getBody(self):
|
||||
return self.find('BODY')
|
||||
|
||||
def getHead(self):
|
||||
return self.find('HEAD')
|
||||
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
import os
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
from pandac.PandaModules import VirtualFileSystem
|
||||
from pandac.PandaModules import Filename
|
||||
from pandac.PandaModules import DSearchPath
|
||||
import xml.etree.ElementTree as ET
|
||||
import LandingPageHTML
|
||||
from StringIO import StringIO
|
||||
|
||||
class LandingPage:
|
||||
notify = directNotify.newCategory("LandingPage")
|
||||
def __init__(self):
|
||||
self.headerTemplate = LandingPageHTML.header
|
||||
self.footerTemplate = LandingPageHTML.footer
|
||||
|
||||
self.menu = {}
|
||||
|
||||
self.uriToTitle = {}
|
||||
|
||||
self.quickStats = [[],{}]
|
||||
|
||||
self.addQuickStat("Pages Served", 0, 0)
|
||||
|
||||
self.favicon = self.readFavIcon()
|
||||
|
||||
|
||||
def readFavIcon(self):
|
||||
vfs = VirtualFileSystem.getGlobalPtr()
|
||||
filename = Filename('favicon.ico')
|
||||
|
||||
searchPath = DSearchPath()
|
||||
searchPath.appendDirectory(Filename('.'))
|
||||
searchPath.appendDirectory(Filename('etc'))
|
||||
searchPath.appendDirectory(Filename.fromOsSpecific(os.path.expandvars('$DIRECT/src/http')))
|
||||
searchPath.appendDirectory(Filename.fromOsSpecific(os.path.expandvars('direct/src/http')))
|
||||
searchPath.appendDirectory(Filename.fromOsSpecific(os.path.expandvars('direct/http')))
|
||||
found = vfs.resolveFilename(filename,searchPath)
|
||||
if not found:
|
||||
raise "Couldn't find direct/http/favicon.ico"
|
||||
|
||||
return vfs.readFile(filename, 1)
|
||||
|
||||
|
||||
def addTab(self, title, uri):
|
||||
self.menu[title] = uri
|
||||
self.uriToTitle[uri] = title
|
||||
|
||||
def getMenu(self, activeTab):
|
||||
return LandingPageHTML.getTabs(self.menu,activeTab)
|
||||
|
||||
def getMenuTags(self, activeTab):
|
||||
return LandingPageHTML.getTabTags(self.menu, activeTab)
|
||||
|
||||
def getHeader(self, activeTab = "Main", headTag=None, bodyTag=None):
|
||||
if headTag is None:
|
||||
headTag = ET.Element('head')
|
||||
if bodyTag is None:
|
||||
bodyTag = ET.Element('body')
|
||||
|
||||
# make sure each component has elements to make formatting consistent
|
||||
headTag.append(ET.Comment(''))
|
||||
bodyTag.append(ET.Comment(''))
|
||||
|
||||
fileStr = StringIO()
|
||||
ET.ElementTree(headTag).write(fileStr, encoding='utf-8')
|
||||
headTagStr = unicodeUtf8(fileStr.getvalue())
|
||||
# remove the tag closer
|
||||
# </head>
|
||||
headTagStr = headTagStr[:headTagStr.rindex('<')]
|
||||
|
||||
# fill in the prefab body tag content
|
||||
titleStr = LandingPageHTML.title
|
||||
landing = ET.Element('body')
|
||||
LandingPageHTML.addBodyHeaderAndContent(landing, titleStr, self.getMenuTags(activeTab))
|
||||
|
||||
fileStr = StringIO()
|
||||
ET.ElementTree(landing).write(fileStr, encoding='utf-8')
|
||||
landingStr = unicodeUtf8(fileStr.getvalue())
|
||||
# remove <body>
|
||||
landingStr = landingStr[landingStr.index('>')+1:]
|
||||
# remove tag closers
|
||||
for i in xrange(3):
|
||||
# </body>
|
||||
# contents </div>
|
||||
# </center>
|
||||
landingStr = landingStr[:landingStr.rindex('<')]
|
||||
|
||||
fileStr = StringIO()
|
||||
ET.ElementTree(bodyTag).write(fileStr, encoding='utf-8')
|
||||
bodyTagStr = unicodeUtf8(fileStr.getvalue())
|
||||
# extract <body>
|
||||
bodyStr = bodyTagStr[bodyTagStr.index('>')+1:]
|
||||
bodyTagStr = bodyTagStr[:bodyTagStr.index('>')+1]
|
||||
|
||||
bodyStr = bodyTagStr + '\n' + landingStr + '\n' + bodyStr
|
||||
|
||||
s = self.headerTemplate % {'titlestring': titleStr,
|
||||
'headTag' : headTagStr,
|
||||
'bodyTag': bodyStr,
|
||||
}
|
||||
return s
|
||||
|
||||
def getFooter(self):
|
||||
return self.footerTemplate % {'contact' : LandingPageHTML.contactInfo}
|
||||
|
||||
def getServicesPage(self, uriToHandler):
|
||||
output = ""
|
||||
|
||||
uriList = uriToHandler.keys()
|
||||
|
||||
uriList.sort()
|
||||
|
||||
autoList = []
|
||||
|
||||
if "/" in uriList:
|
||||
uriList.remove("/")
|
||||
autoList.append("/")
|
||||
if "/services" in uriList:
|
||||
uriList.remove("/services")
|
||||
autoList.append("/services")
|
||||
if "/default.css" in uriList:
|
||||
uriList.remove("/default.css")
|
||||
autoList.append("/default.css")
|
||||
if "/favicon.ico" in uriList:
|
||||
uriList.remove("/favicon.ico")
|
||||
autoList.append("/favicon.ico")
|
||||
|
||||
output += LandingPageHTML.getURITable(title="Application",uriList=uriList,uriToHandler=uriToHandler)
|
||||
|
||||
output += LandingPageHTML.getURITable(title="Admin",uriList=autoList,uriToHandler=uriToHandler)
|
||||
|
||||
return output
|
||||
|
||||
def populateMainPage(self, body):
|
||||
LandingPageHTML.mainPageBody = body
|
||||
|
||||
def setTitle(self, title):
|
||||
if LandingPageHTML.title == LandingPageHTML.defaultTitle:
|
||||
LandingPageHTML.title = title
|
||||
else:
|
||||
LandingPageHTML.title = LandingPageHTML.title + " + " + title
|
||||
|
||||
def setDescription(self,desc):
|
||||
if LandingPageHTML.description == LandingPageHTML.defaultDesc:
|
||||
LandingPageHTML.description = desc
|
||||
else:
|
||||
LandingPageHTML.description = LandingPageHTML.description + "</P>\n<P>" + desc
|
||||
|
||||
def setContactInfo(self,info):
|
||||
LandingPageHTML.contactInfo = info
|
||||
|
||||
def getDescription(self):
|
||||
return LandingPageHTML.description
|
||||
|
||||
def getQuickStatsTable(self):
|
||||
return LandingPageHTML.getQuickStatsTable(self.quickStats)
|
||||
|
||||
def getMainPage(self):
|
||||
return LandingPageHTML.mainPageBody % {"description" : self.getDescription(),
|
||||
"quickstats" : self.getQuickStatsTable()}
|
||||
|
||||
def getStyleSheet(self):
|
||||
return LandingPageHTML.stylesheet
|
||||
|
||||
def getFavIcon(self):
|
||||
return self.favicon
|
||||
|
||||
def skin(self, body, uri, headTag=None, bodyTag=None):
|
||||
title = self.uriToTitle.get(uri,"Services")
|
||||
return self.getHeader(title, headTag, bodyTag) + body + self.getFooter()
|
||||
|
||||
def addQuickStat(self,item,value,position):
|
||||
if item in self.quickStats[1]:
|
||||
assert self.notify.warning("Ignoring duplicate addition of quickstat %s." % item)
|
||||
return
|
||||
|
||||
self.quickStats[0].insert(position,item)
|
||||
self.quickStats[1][item] = value
|
||||
|
||||
def updateQuickStat(self,item,value):
|
||||
assert item in self.quickStats[1]
|
||||
|
||||
self.quickStats[1][item] = value
|
||||
|
||||
def incrementQuickStat(self,item):
|
||||
assert item in self.quickStats[1]
|
||||
|
||||
self.quickStats[1][item] += 1
|
||||
|
|
@ -1,476 +0,0 @@
|
|||
# -- Text content for the landing page. You should change these for yours! --
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
title = "Landing Page"
|
||||
defaultTitle = title
|
||||
|
||||
description = "To set this description, call WebRequestDispatcher.setDescription!<BR><BR>You can also add stats to the table below by calling WebRequestDispatcher.addQuickStat(Name,Value,PositionInTable)."
|
||||
defaultDesc = description
|
||||
|
||||
contactInfo = "M. Ian Graham - ian.graham@dig.com"
|
||||
|
||||
|
||||
# -- Begin fancy layout stuff, change at your own risk --
|
||||
|
||||
stylesheet = '''
|
||||
body
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 90%;
|
||||
font-family: Verdana, sans-serif;
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
p
|
||||
{
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
h2
|
||||
{
|
||||
font-size: 140%;
|
||||
color: #666;
|
||||
background-color: #fff;
|
||||
width: 22em;
|
||||
margin-left: 150px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
h3
|
||||
{
|
||||
padding-top: 10px;
|
||||
margin-top: 0px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
pre
|
||||
{
|
||||
margin-left: 20px;
|
||||
margin-bottom: 0px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
a
|
||||
{
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
a:hover
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#header
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#footer
|
||||
{
|
||||
margin: 0;
|
||||
padding: 3px;
|
||||
text-align: right;
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #778;
|
||||
font: 10px Verdana, sans-serif;
|
||||
}
|
||||
|
||||
#contents
|
||||
{
|
||||
margin: 0;
|
||||
padding: 25;
|
||||
background-color: #eee;
|
||||
min-height:600px;
|
||||
height:auto !important;
|
||||
height:600px;
|
||||
}
|
||||
|
||||
<!-- Tab menu -->
|
||||
|
||||
#navcontainer
|
||||
{
|
||||
margin:0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#navlist
|
||||
{
|
||||
padding: 3px 0;
|
||||
margin-left: 0;
|
||||
margin: 0;
|
||||
border-bottom: 1px solid #778;
|
||||
font: bold 12px Verdana, sans-serif;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#navlist li
|
||||
{
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#navlist li a
|
||||
{
|
||||
padding: 3px 0.5em;
|
||||
margin-left: 3px;
|
||||
border: 1px solid #778;
|
||||
border-bottom: none;
|
||||
background: #DDE;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#navlist li a:link { color: #448; }
|
||||
#navlist li a:visited { color: #667; }
|
||||
|
||||
#navlist li a:hover
|
||||
{
|
||||
color: #000;
|
||||
background: #AAE;
|
||||
border-color: #227;
|
||||
}
|
||||
|
||||
#navlist li a#current
|
||||
{
|
||||
background: #eee;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#navlist li.first
|
||||
{
|
||||
margin-left: 150px;
|
||||
}
|
||||
|
||||
<!-- Table formatting -->
|
||||
|
||||
table
|
||||
{
|
||||
border-spacing:1px;
|
||||
background:#E7E7E7;
|
||||
color:#333;
|
||||
}
|
||||
|
||||
caption
|
||||
{
|
||||
border: #666666;
|
||||
border-bottom: 2px solid #666666;
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
padding: 10px;
|
||||
background: #cfcfdf;
|
||||
font: 15px 'Verdana', Arial, Helvetica, sans-serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
td, th
|
||||
{
|
||||
font:13px 'Courier New',monospace;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
thead th
|
||||
{
|
||||
text-align: center;
|
||||
background: #dde;
|
||||
color: #666666;
|
||||
border: 1px solid #ffffff;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
tbody th
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
tbody tr
|
||||
{
|
||||
background: #efeffc;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
tbody tr.odd
|
||||
{
|
||||
background: #ffffff;
|
||||
border-top: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
tbody th a:hover
|
||||
{
|
||||
color: #009900;
|
||||
}
|
||||
|
||||
tbody tr td
|
||||
{
|
||||
text-align: left
|
||||
height: 30px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #ffffff;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
tbody tr.odd td
|
||||
{
|
||||
background: #efeffc;
|
||||
border-top: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
tbody tr[altColoring="1"] td
|
||||
{
|
||||
background: LightCyan;
|
||||
border-top: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
tbody tr[altColoring="1"].odd td
|
||||
{
|
||||
background: PaleTurquoise;
|
||||
border-top: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
tbody tr[altColoring="2"] td
|
||||
{
|
||||
background: LightSalmon;
|
||||
border-top: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
tbody tr[altColoring="2"].odd td
|
||||
{
|
||||
background: SandyBrown;
|
||||
border-top: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
tbody tr.dead td
|
||||
{
|
||||
background:#ff0000;
|
||||
border-top: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
table td a:link, table td a:visited
|
||||
{
|
||||
display: block;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
width: 100%;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
html>body #navcontainer li a { width: auto; }
|
||||
|
||||
table td a:hover
|
||||
{
|
||||
color: #000000;
|
||||
background: #aae;
|
||||
}
|
||||
|
||||
tfoot th, tfoot td
|
||||
{
|
||||
background: #dfdfdf;
|
||||
padding: 3px;
|
||||
text-align: center;
|
||||
font: 14px 'Verdana', Arial, Helvetica, sans-serif;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #cccccc;
|
||||
border-top: 1px solid #DFDFDF;
|
||||
}
|
||||
\r\n'''
|
||||
|
||||
header = '''
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<html>
|
||||
%(headTag)s
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>%(titlestring)s</title>
|
||||
<link rel="stylesheet" type="text/css" href="/default.css">
|
||||
</head>
|
||||
|
||||
%(bodyTag)s
|
||||
'''
|
||||
|
||||
# this portion of the body is now added dynamically in order to support changes to the body tag
|
||||
# attributes
|
||||
'''
|
||||
<!-- HEADER -->
|
||||
|
||||
<div id="header">
|
||||
<h2>%(titlestring)s</h2>
|
||||
<div id="navcontainer">
|
||||
<ul id="navlist">
|
||||
%(menustring)s</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CONTENT -->
|
||||
|
||||
<div id="contents">
|
||||
<center>
|
||||
|
||||
'''
|
||||
|
||||
# caller must remove '</div>' from end of output string derived from what is returned
|
||||
def addBodyHeaderAndContent(bodyTag, titleString, menuTags):
|
||||
SE = ET.SubElement
|
||||
bodyTag.append(ET.Comment('HEADER'))
|
||||
header = SE(bodyTag, 'div', id='header')
|
||||
h2 = SE(header, 'h2')
|
||||
h2.text = titleString
|
||||
navContainer = SE(header, 'div', id='navcontainer')
|
||||
navList = SE(navContainer, 'ul', id='navlist')
|
||||
for menuTag in menuTags:
|
||||
navList.append(menuTag)
|
||||
bodyTag.append(ET.Comment('CONTENT'))
|
||||
contents = SE(bodyTag, 'div', id='contents')
|
||||
center = SE(contents, 'center')
|
||||
# for ease of removal of center tag closer
|
||||
center.append(ET.Comment(''))
|
||||
|
||||
mainPageBody = '''
|
||||
<P>%(description)s</P>
|
||||
|
||||
<P>%(quickstats)s</P>
|
||||
'''
|
||||
|
||||
footer = '''
|
||||
</center>
|
||||
</div>
|
||||
|
||||
<!-- FOOTER -->
|
||||
|
||||
<div id="footer">
|
||||
Contact: %(contact)s
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
\r\n'''
|
||||
|
||||
|
||||
def getRowClassString(rowNum):
|
||||
if rowNum % 2 == 0:
|
||||
return ""
|
||||
else:
|
||||
return " class=\"odd\""
|
||||
|
||||
def getURITable(title,uriList,uriToHandler):
|
||||
output = "\n<P>\n<table>\n<caption>%s</caption><thead><tr><th scope=col>URI</th><th scope=col>Handler</th></tr></thead>\n" % title
|
||||
output += "<tbody>\n"
|
||||
|
||||
rowNum = 0
|
||||
for uri in uriList:
|
||||
handlerFunc = str(uriToHandler[uri][0]).split(" ")[2]
|
||||
|
||||
output += "<tr%s><td><a href=%s>%s</a></td><td>%s</td></tr>\n" % \
|
||||
(getRowClassString(rowNum),
|
||||
uri,
|
||||
uri,
|
||||
handlerFunc)
|
||||
rowNum += 1
|
||||
|
||||
output += "</tbody>\n</table>\n</P>\n"
|
||||
|
||||
return output
|
||||
|
||||
def getTabs(menu,activeTab):
|
||||
tabList = menu.keys()
|
||||
if "Main" in tabList:
|
||||
tabList.remove("Main")
|
||||
if "Services" in tabList:
|
||||
tabList.remove("Services")
|
||||
|
||||
tabList.sort()
|
||||
|
||||
if "Main" in menu.keys():
|
||||
tabList.insert(0, "Main")
|
||||
if "Services" in menu.keys():
|
||||
tabList.insert(1, "Services")
|
||||
|
||||
s = ""
|
||||
tabNum = 0
|
||||
|
||||
for tab in tabList:
|
||||
if tabNum == 0:
|
||||
if tab == activeTab:
|
||||
s += "<li id=\"active\" class=\"first\"><a href=\"%s\" id=\"current\">%s</a></li>\n" % \
|
||||
(menu[tab], tab)
|
||||
else:
|
||||
s += "<li class=\"first\"><a href=\"%s\">%s</a></li>\n" % \
|
||||
(menu[tab], tab)
|
||||
else:
|
||||
if tab == activeTab:
|
||||
s += "<li id=\"active\"><a href=\"%s\" id=\"current\">%s</a></li>\n" % \
|
||||
(menu[tab], tab)
|
||||
else:
|
||||
s += "<li><a href=\"%s\">%s</a></li>\n" % \
|
||||
(menu[tab], tab)
|
||||
tabNum += 1
|
||||
|
||||
return s
|
||||
|
||||
def getTabTags(menu,activeTab):
|
||||
tabList = menu.keys()
|
||||
if "Main" in tabList:
|
||||
tabList.remove("Main")
|
||||
if "Services" in tabList:
|
||||
tabList.remove("Services")
|
||||
|
||||
tabList.sort()
|
||||
|
||||
if "Main" in menu.keys():
|
||||
tabList.insert(0, "Main")
|
||||
if "Services" in menu.keys():
|
||||
tabList.insert(1, "Services")
|
||||
|
||||
tabNum = 0
|
||||
|
||||
tags = []
|
||||
|
||||
for tab in tabList:
|
||||
if tabNum == 0:
|
||||
if tab == activeTab:
|
||||
li = ET.Element('li', id='active')
|
||||
li.set('class', 'first')
|
||||
a = ET.SubElement(li, 'a', href=menu[tab], id='current')
|
||||
a.text = tab
|
||||
tags.append(li)
|
||||
else:
|
||||
li = ET.Element('li')
|
||||
li.set('class', 'first')
|
||||
a = ET.SubElement(li, 'a', href=menu[tab])
|
||||
a.text = tab
|
||||
tags.append(li)
|
||||
else:
|
||||
if tab == activeTab:
|
||||
li = ET.Element('li', id='active')
|
||||
a = ET.SubElement(li, 'a', href=menu[tab], id='current')
|
||||
a.text = tab
|
||||
tags.append(li)
|
||||
else:
|
||||
li = ET.Element('li')
|
||||
a = ET.SubElement(li, 'a', href=menu[tab])
|
||||
a.text = tab
|
||||
tags.append(li)
|
||||
tabNum += 1
|
||||
|
||||
return tags
|
||||
|
||||
def getQuickStatsTable(quickStats):
|
||||
output = "\n<table>\n<caption>Quick Stats</caption>\n<thead><tr><th scope=col>Item</th><th scope=col>Value</th></tr></thead>\n"
|
||||
output += "<tbody>\n"
|
||||
|
||||
rowNum = 0
|
||||
for item in quickStats[0]:
|
||||
output += "<tr%s><td>%s</td><td>%s</td></tr>\n" % \
|
||||
(getRowClassString(rowNum),
|
||||
item,
|
||||
quickStats[1][item])
|
||||
rowNum += 1
|
||||
|
||||
output += "</tbody>\n</table>\n"
|
||||
|
||||
return output
|
||||
|
|
@ -1,295 +0,0 @@
|
|||
import direct
|
||||
from pandac.PandaModules import HttpRequest
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from direct.task import Task
|
||||
from LandingPage import LandingPage
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
notify = directNotify.newCategory('WebRequestDispatcher')
|
||||
|
||||
class WebRequest(object):
|
||||
"""
|
||||
Pointer to a single web request (maps to an open HTTP socket).
|
||||
An instance of this class maps to a single client waiting for a response.
|
||||
|
||||
connection is an instance of libdirect.HttpRequest
|
||||
"""
|
||||
def __init__(self,connection):
|
||||
self.connection = connection
|
||||
|
||||
def getURI(self):
|
||||
return self.connection.GetRequestURL()
|
||||
|
||||
def getRequestType(self):
|
||||
return self.connection.GetRequestType()
|
||||
|
||||
def dictFromGET(self):
|
||||
result = {}
|
||||
for pair in self.connection.GetRequestOptionString().split('&'):
|
||||
arg = pair.split('=',1)
|
||||
if len(arg) > 1:
|
||||
result[arg[0]] = arg[1]
|
||||
return result
|
||||
|
||||
def respondHTTP(self,status,body):
|
||||
status = str(status)
|
||||
msg = u"HTTP/1.0 %s\r\nContent-Type: text/html\r\n\r\n%s" % (status,body)
|
||||
self.connection.SendThisResponse(encodedUtf8(msg))
|
||||
|
||||
def respond(self,body):
|
||||
self.respondHTTP("200 OK",body)
|
||||
|
||||
def respondXML(self,body):
|
||||
msg = u"HTTP/1.0 200 OK\r\nContent-Type: text/xml\r\n\r\n%s" % body
|
||||
self.connection.SendThisResponse(encodedUtf8(msg))
|
||||
|
||||
def respondCustom(self,contentType,body):
|
||||
msg = "HTTP/1.0 200 OK\r\nContent-Type: %s" % contentType
|
||||
|
||||
if contentType in ["text/css",]:
|
||||
msg += "\nCache-Control: max-age=313977290\nExpires: Tue, 02 May 2017 04:08:44 GMT\n"
|
||||
|
||||
msg += "\r\n\r\n%s" % (body)
|
||||
self.connection.SendThisResponse(msg)
|
||||
|
||||
def timeout(self):
|
||||
resp = "<html><body>Error 504: Request timed out</body></html>\r\n"
|
||||
self.respondHTTP("504 Gateway Timeout",resp)
|
||||
|
||||
def getSourceAddress(self):
|
||||
return self.connection.GetSourceAddress()
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------
|
||||
|
||||
class SkinningReplyTo:
|
||||
def __init__(self, replyTo, dispatcher, uri, doSkin):
|
||||
self._replyTo = replyTo
|
||||
self._dispatcher = dispatcher
|
||||
self._uri = uri
|
||||
self._doSkin = doSkin
|
||||
self._headTag = ET.Element('head')
|
||||
self._bodyTag = ET.Element('body')
|
||||
|
||||
def respondHTTP(self,status,body):
|
||||
if self._doSkin:
|
||||
body = self._dispatcher.landingPage.skin(
|
||||
body, self._uri, headTag=self._headTag, bodyTag=self._bodyTag)
|
||||
self._replyTo.respondHTTP(status, body)
|
||||
|
||||
def respond(self, response):
|
||||
self.respondHTTP("200 OK", response)
|
||||
|
||||
# provides access to head and body tags of landing page
|
||||
def getHeadTag(self):
|
||||
return self._headTag
|
||||
def getBodyTag(self):
|
||||
return self._bodyTag
|
||||
|
||||
def __getattr__(self, attrName):
|
||||
if attrName in self.__dict__:
|
||||
return self.__dict__[attrName]
|
||||
if hasattr(self.__class__, attrName):
|
||||
return getattr(self.__class__, attrName)
|
||||
# pass-through to replyTo object which this object is a proxy to
|
||||
return getattr(self._replyTo, attrName)
|
||||
|
||||
class WebRequestDispatcher(object):
|
||||
"""
|
||||
Request dispatcher for HTTP requests.
|
||||
Contains registration and dispatching functionality.
|
||||
|
||||
Single-state class--multiple instances share all data.
|
||||
This is because we're wrapping a singleton webserver.
|
||||
|
||||
How to use:
|
||||
|
||||
w = WebRequestDispatcher()
|
||||
w.listenOnPort(8888)
|
||||
def test(replyTo,**kw):
|
||||
print 'test got called with these options: %s' % str(kw)
|
||||
replyTo.respond('<html><body>Thank you for the yummy arguments: %s' % str(kw))
|
||||
w.registerGETHandler('test',test)
|
||||
while 1:
|
||||
w.poll()
|
||||
|
||||
Browse to http://localhost:8888/test?foo=bar and see the result!
|
||||
"""
|
||||
|
||||
_shared_state = {}
|
||||
|
||||
listenPort = None
|
||||
|
||||
uriToHandler = {}
|
||||
|
||||
requestTimeout = 10.0
|
||||
|
||||
notify = notify
|
||||
|
||||
def __new__(self, *a, **kw):
|
||||
obj = object.__new__(self, *a, **kw)
|
||||
obj.__dict__ = self._shared_state
|
||||
return obj
|
||||
|
||||
def __init__(self, wantLandingPage = True):
|
||||
self.enableLandingPage(wantLandingPage)
|
||||
|
||||
def listenOnPort(self,listenPort):
|
||||
"""
|
||||
Start the web server listening if it isn't already.
|
||||
Singleton server, so ignore multiple listen requests.
|
||||
"""
|
||||
if self.listenPort is None:
|
||||
self.listenPort = listenPort
|
||||
HttpRequest.HttpManagerInitialize(listenPort)
|
||||
self.notify.info("Listening on port %d" % listenPort)
|
||||
else:
|
||||
self.notify.warning("Already listening on port %d. Ignoring request to listen on port %d." % (self.listenPort,listenPort))
|
||||
|
||||
def invalidURI(self,replyTo,**kw):
|
||||
resp = "<html><body>Error 404</body></html>\r\n"
|
||||
replyTo.respondHTTP("404 Not Found",resp)
|
||||
self.notify.warning("%s - %s - 404" % (replyTo.getSourceAddress(),replyTo.getURI()))
|
||||
|
||||
# access to head and body tags of landing page
|
||||
# only for 'returnsResponse' mode
|
||||
def getHeadTag(self):
|
||||
return self._headTag
|
||||
def getBodyTag(self):
|
||||
return self._bodyTag
|
||||
|
||||
def handleGET(self,req):
|
||||
"""
|
||||
Parse and dispatch a single GET request.
|
||||
Expects to receive a WebRequest object.
|
||||
"""
|
||||
assert req.getRequestType() == "GET"
|
||||
|
||||
self.landingPage.incrementQuickStat("Pages Served")
|
||||
|
||||
uri = req.getURI()
|
||||
args = req.dictFromGET()
|
||||
|
||||
callable,returnsResponse,autoSkin = self.uriToHandler.get(uri, [self.invalidURI,False,False])
|
||||
|
||||
if callable != self.invalidURI:
|
||||
self.notify.info("%s - %s - %s - 200" % (req.getSourceAddress(), uri, args))
|
||||
|
||||
if returnsResponse:
|
||||
result = apply(callable,(),args)
|
||||
if autoSkin:
|
||||
self._headTag = ET.Element('head')
|
||||
self._bodyTag = ET.Element('body')
|
||||
req.respond(self.landingPage.skin(result,uri, headTag=self._headTag, bodyTag=self._bodyTag))
|
||||
del self._bodyTag
|
||||
del self._headTag
|
||||
else:
|
||||
req.respond(result)
|
||||
else:
|
||||
args["replyTo"] = SkinningReplyTo(req, self, uri, autoSkin)
|
||||
apply(callable,(),args)
|
||||
|
||||
def poll(self):
|
||||
"""
|
||||
Pump the web server, handle any incoming requests.
|
||||
This function should be called regularly, about 2-4
|
||||
calls/sec for current applications is a good number.
|
||||
"""
|
||||
request = HttpRequest.HttpManagerGetARequest()
|
||||
while request is not None:
|
||||
wreq = WebRequest(request)
|
||||
if wreq.getRequestType() == "GET":
|
||||
self.handleGET(wreq)
|
||||
else:
|
||||
self.notify.warning("Ignoring a non-GET request from %s: %s" % (request.GetSourceAddress(),request.GetRawRequest()))
|
||||
self.invalidURI(wreq)
|
||||
|
||||
request = HttpRequest.HttpManagerGetARequest()
|
||||
|
||||
|
||||
def registerGETHandler(self,uri,handler,returnsResponse=False, autoSkin=False):
|
||||
"""
|
||||
Call this function to register a handler function to
|
||||
be called in response to a query to the given URI.
|
||||
|
||||
GET options are translated into **kw arguments.
|
||||
Handler function should accept **kw in order to handle
|
||||
arbitrary queries.
|
||||
|
||||
If returnsResponse is False, the request is left open after
|
||||
handler returns--handler or tasks it creates are responsible
|
||||
for fulfilling the query now or in the future. Argument
|
||||
replyTo (a WebRequest) is guaranteed to be passed to the
|
||||
handler, and replyTo.respond must be called with an HTML
|
||||
response string to fulfill the query and close the socket.
|
||||
|
||||
If returnsResponse is True, WebRequestDispatcher expects the
|
||||
handler to return its response string, and we will route the
|
||||
response and close the socket ourselves. No replyTo argument
|
||||
is provided to the handler in this case.
|
||||
"""
|
||||
if uri[0] != "/":
|
||||
uri = "/" + uri
|
||||
|
||||
if self.uriToHandler.get(uri,None) is None:
|
||||
self.notify.info("Registered handler %s for URI %s." % (handler,uri))
|
||||
self.uriToHandler[uri] = [handler, returnsResponse, autoSkin]
|
||||
else:
|
||||
self.notify.warning("Attempting to register a duplicate handler for URI %s. Ignoring." % uri)
|
||||
|
||||
def unregisterGETHandler(self,uri):
|
||||
if uri[0] != "/":
|
||||
uri = "/" + uri
|
||||
self.uriToHandler.pop(uri,None)
|
||||
|
||||
|
||||
# -- Poll task wrappers --
|
||||
|
||||
def pollHTTPTask(self,task):
|
||||
self.poll()
|
||||
return Task.again
|
||||
|
||||
def startCheckingIncomingHTTP(self, interval=0.3):
|
||||
taskMgr.remove('pollHTTPTask')
|
||||
taskMgr.doMethodLater(interval,self.pollHTTPTask,'pollHTTPTask')
|
||||
|
||||
def stopCheckingIncomingHTTP(self):
|
||||
taskMgr.remove('pollHTTPTask')
|
||||
|
||||
|
||||
# -- Landing page convenience functions --
|
||||
|
||||
def enableLandingPage(self, enable):
|
||||
if enable:
|
||||
if "landingPage" not in self.__dict__:
|
||||
self.landingPage = LandingPage()
|
||||
self.registerGETHandler("/", self._main, returnsResponse = True, autoSkin = True)
|
||||
self.registerGETHandler("/services", self._services, returnsResponse = True, autoSkin = True)
|
||||
self.registerGETHandler("/default.css", self._stylesheet)
|
||||
self.registerGETHandler("/favicon.ico", self._favicon)
|
||||
self.landingPage.addTab("Main", "/")
|
||||
self.landingPage.addTab("Services", "/services")
|
||||
else:
|
||||
self.landingPage = None
|
||||
self.unregisterGETHandler("/")
|
||||
self.unregisterGETHandler("/services")
|
||||
|
||||
|
||||
def _main(self):
|
||||
return self.landingPage.getMainPage()
|
||||
|
||||
def _services(self):
|
||||
return self.landingPage.getServicesPage(self.uriToHandler)
|
||||
|
||||
def _stylesheet(self,**kw):
|
||||
replyTo = kw.get("replyTo",None)
|
||||
assert replyTo is not None
|
||||
body = self.landingPage.getStyleSheet()
|
||||
replyTo.respondCustom("text/css",body)
|
||||
|
||||
def _favicon(self,**kw):
|
||||
replyTo = kw.get("replyTo",None)
|
||||
assert replyTo is not None
|
||||
body = self.landingPage.getFavIcon()
|
||||
replyTo.respondCustom("image/x-icon",body)
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#define LOGINFO printf
|
||||
#define LOGWARNING printf
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
#ifndef __BASEINCOMINGSET_H__
|
||||
#define __BASEINCOMINGSET_H__
|
||||
|
||||
#include <list>
|
||||
#include "socket_base.h"
|
||||
|
||||
enum CloseState
|
||||
{
|
||||
ConnectionDoNotClose,
|
||||
ConnectionDoClose
|
||||
};
|
||||
// RHH
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Template :BaseIncomingSet
|
||||
//
|
||||
// Description : A base structre for a listening socket and a
|
||||
// set of connection that have been received with there read functions..
|
||||
//
|
||||
// Think of this like a web server with 1 listening socket and 0-n open reacting conections..
|
||||
//
|
||||
// The general operation if get connection..
|
||||
// do you have a message
|
||||
// process message
|
||||
// go back to do you have a message or close connection
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template < class _INCLASS1,class _IN_LISTEN, class MESSAGE_READER_BUF, class MESSAGE_READER_UPPASS> class BaseIncomingSet : public std::list<_INCLASS1 *>
|
||||
{
|
||||
typedef std::list<_INCLASS1 *> BaseClass;
|
||||
typedef TYPENAME BaseClass::iterator iterator;
|
||||
_IN_LISTEN _Listener;
|
||||
|
||||
inline void AddFromListener(void);
|
||||
inline int PumpReader(Time_Clock ¤tTime);
|
||||
inline void AddAConection(_INCLASS1 * newt);
|
||||
|
||||
public:
|
||||
|
||||
// typedef typename BaseIncomingSet<_INCLASS1, _IN_LISTEN, MESSAGE_READER_BUF, MESSAGE_READER_UPPASS>::LinkNode LinkNode;
|
||||
|
||||
// typedef SentDblLinkListNode_Gm SentDblLinkListNode_Gm;
|
||||
inline BaseIncomingSet(void);
|
||||
inline BaseIncomingSet(BaseIncomingSet &in);
|
||||
virtual ~BaseIncomingSet();
|
||||
|
||||
inline _IN_LISTEN & GetListener(void);
|
||||
inline bool init(Socket_Address &WhereFrom);
|
||||
inline void PumpAll(Time_Clock ¤tTime);
|
||||
virtual CloseState ProcessNewConnection(SOCKET socket);
|
||||
inline void AddToFDSet(Socket_fdset &set);
|
||||
|
||||
// inline LinkNode * GetRoot(void) { return &this->sentenal; };
|
||||
BaseIncomingSet &operator=( BaseIncomingSet &inval);
|
||||
void Reset();
|
||||
};
|
||||
|
||||
#include "baseincomingset.i"
|
||||
|
||||
#endif //__BASEINCOMINGSET_H__
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,202 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddFromListener
|
||||
// Description : Read incoming connections off the listener
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddFromListener(void)
|
||||
{
|
||||
Socket_Address Addr1;
|
||||
SOCKET newsck;
|
||||
|
||||
|
||||
while(_Listener.GetIncomingConnection(newsck,Addr1) == true)
|
||||
{
|
||||
CloseState cl= ProcessNewConnection(newsck);
|
||||
if(cl == ConnectionDoNotClose)
|
||||
{
|
||||
_INCLASS1 * newt = new _INCLASS1(newsck,Addr1);
|
||||
AddAConection(newt);
|
||||
}
|
||||
else
|
||||
DO_CLOSE(newsck);
|
||||
}
|
||||
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::PumpReader
|
||||
// Description : Tries to read a record off the incoming socket
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : Time_Clock currentTime
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline int BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::PumpReader(Time_Clock ¤tTime)
|
||||
{
|
||||
MESSAGE_READER_BUF message;
|
||||
|
||||
iterator lpNext, lp;
|
||||
for (lpNext = lp = BaseClass::begin(); lp != BaseClass::end() ; lp = lpNext)
|
||||
{
|
||||
lpNext++;
|
||||
|
||||
int ans = (*lp)->ReadIt(message, sizeof(message),currentTime);
|
||||
if(ans < 0)
|
||||
{
|
||||
delete *lp;
|
||||
this->erase(lp);
|
||||
}
|
||||
if(ans > 0)
|
||||
{
|
||||
CloseState cs = (*lp)->ProcessMessage(message,currentTime);
|
||||
if( cs == ConnectionDoClose)
|
||||
{
|
||||
delete *lp;
|
||||
this->erase(lp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddAConection
|
||||
// Description : Adds a member to the base container
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : _INCLASS1 * newt
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddAConection(_INCLASS1 * newt)
|
||||
{
|
||||
this->push_back(newt);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::BaseIncomingSet
|
||||
// Description : core constructor
|
||||
//
|
||||
// Return type : inline
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::BaseIncomingSet(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::BaseIncomingSet(BaseIncomingSet &in)
|
||||
{
|
||||
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::~BaseIncomingSet
|
||||
// Description : The Destructot .. will delete all members.. ??
|
||||
//
|
||||
// Return type :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::~BaseIncomingSet()
|
||||
{
|
||||
for(iterator ii = BaseClass::begin(); ii != BaseClass::end(); ii++)
|
||||
delete *ii;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : & BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::GetListener
|
||||
// Description : Retyurns a pointer to the listener in this class
|
||||
//
|
||||
// Return type : inline _IN_LISTEN
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline _IN_LISTEN & BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::GetListener(void)
|
||||
{
|
||||
return this->Listener;
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::init
|
||||
// Description : the second part of the 2 phase power up.. Opends the listener
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : Socket_Address &WhereFrom
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline bool BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::init(Socket_Address &WhereFrom)
|
||||
{
|
||||
if(_Listener.OpenForListen(WhereFrom,true) != true)
|
||||
return false;
|
||||
_Listener.SetNonBlocking();
|
||||
return true;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::PumpAll
|
||||
// Description : THis is the polled interface to this class
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : Time_Clock ¤tTime
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::PumpAll(Time_Clock ¤tTime)
|
||||
{
|
||||
PumpReader(currentTime); // I MOVED ORDER TO FINE TUNE THE READ OPERATIONS
|
||||
AddFromListener();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::ProcessNewConnection
|
||||
// Description : this is the vertual function call when a new connection is created
|
||||
// manly here for loging if needed...
|
||||
//
|
||||
// Return type : CloseState
|
||||
// Argument : SOCKET socket
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
CloseState BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::ProcessNewConnection(SOCKET socket)
|
||||
{
|
||||
return ConnectionDoNotClose;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddToFDSet
|
||||
// Description : Add LIstener and Client to the FD set for polled reading
|
||||
//
|
||||
// Return type : inline
|
||||
// Argument : Socket_Selector &set
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddToFDSet(Socket_fdset &set1)
|
||||
{
|
||||
if(_Listener.Active())
|
||||
set1.setForSocket(_Listener);
|
||||
iterator lp;
|
||||
|
||||
for (lp = BaseClass::begin(); lp != BaseClass::end(); lp = lp++)
|
||||
set1.setForSocket((*lp)->val);
|
||||
}
|
||||
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS> &BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::operator=
|
||||
(BaseIncomingSet &inval)
|
||||
{
|
||||
if (&inval == this) return *this;
|
||||
_Listener = inval._Listener;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::Reset()
|
||||
{
|
||||
_Listener.Close();
|
||||
iterator lpNext, lp;
|
||||
for (lpNext = lp = BaseClass::begin(); lp != BaseClass::end() ; lp = lpNext)
|
||||
{
|
||||
lpNext++;
|
||||
(*lp)->Reset();
|
||||
delete *lp;
|
||||
this->erase(lp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
#ifndef __BufferedWriter_Growable_H__
|
||||
#define __BufferedWriter_Growable_H__
|
||||
///////////////////////////////////////////////////////
|
||||
// this class is for the usage of growable output...
|
||||
// it is slower than buffered writer but more robust..
|
||||
// it also allows for writes to take more time to the out putt..
|
||||
// ie.. Write buffering.. Not just one write..
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
class BufferedWriter_Growable : public std::string
|
||||
{
|
||||
int _write_offset;
|
||||
public:
|
||||
|
||||
BufferedWriter_Growable(void);
|
||||
~BufferedWriter_Growable(void);
|
||||
int AmountBuffered(void);
|
||||
void AppendData(const char * buf, int len);
|
||||
void Reset() { clear(); _write_offset = 0; };
|
||||
const char * GetMessageHead(void);
|
||||
int Flush(Socket_TCP &sck) ; // this is the ugly part
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : BufferedWriter_Growable::BufferedWriter_Growable
|
||||
// Description :
|
||||
// Return type : inline
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline BufferedWriter_Growable::BufferedWriter_Growable(void)
|
||||
{
|
||||
_write_offset = 0;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : ~BufferedWriter_Growable::BufferedWriter_Growable
|
||||
// Description :
|
||||
// Return type : inline
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline BufferedWriter_Growable::~BufferedWriter_Growable(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : BufferedWriter_Growable::AmountBuffered
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int BufferedWriter_Growable::AmountBuffered(void)
|
||||
{
|
||||
return (int) (size() - _write_offset);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : BufferedWriter_Growable::AppendData
|
||||
// Description :
|
||||
// Return type : inline void
|
||||
// Argument : const char * buf
|
||||
// Argument : int len
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void BufferedWriter_Growable::AppendData(const char * buf, int len)
|
||||
{
|
||||
append(buf, len);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : char * BufferedWriter_Growable::GetMessageHead
|
||||
// Description :
|
||||
// Return type : inline const
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline const char * BufferedWriter_Growable::GetMessageHead(void)
|
||||
{
|
||||
return data() + _write_offset;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : BufferedWriter_Growable::Flush
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
// Argument : SocketTCP_Gm &sck
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int BufferedWriter_Growable::Flush(Socket_TCP &sck) // this is the ugly part
|
||||
{
|
||||
int answer = 0;
|
||||
int Writesize = AmountBuffered();
|
||||
|
||||
if(Writesize > 0)
|
||||
{
|
||||
const char * out1 = GetMessageHead();
|
||||
int Writen = sck.SendData(out1,Writesize);
|
||||
if(Writen > 0)
|
||||
{
|
||||
_write_offset += Writen;
|
||||
answer = 1;
|
||||
}
|
||||
else if(Writen < 0)
|
||||
{
|
||||
if(GETERROR() != LOCAL_BLOCKING_ERROR)
|
||||
answer = -1;
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
#endif //__BufferedWriter_Growable_H__
|
||||
|
||||
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
// Filename: config_http.cxx
|
||||
// Created by: drose (15Mar09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_http.h"
|
||||
#include "http_connection.h"
|
||||
#include "http_request.h"
|
||||
#include "dconfig.h"
|
||||
|
||||
Configure(config_http);
|
||||
NotifyCategoryDef(http, "");
|
||||
|
||||
ConfigureFn(config_http) {
|
||||
init_libhttp();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: init_libhttp
|
||||
// Description: Initializes the library. This must be called at
|
||||
// least once before any of the functions or classes in
|
||||
// this library can be used. Normally it will be
|
||||
// called by the static initializers and need not be
|
||||
// called explicitly, but special cases exist.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
init_libhttp() {
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
HttpConnection::init_type();
|
||||
Http_Request::init_type();
|
||||
}
|
||||
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
// Filename: config_http.h
|
||||
// Created by: drose (15Mar09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONFIG_HTTP_H
|
||||
#define CONFIG_HTTP_H
|
||||
|
||||
#include "directbase.h"
|
||||
#include "notifyCategoryProxy.h"
|
||||
|
||||
NotifyCategoryDecl(http, EXPCL_DIRECT, EXPTP_DIRECT);
|
||||
|
||||
extern EXPCL_DIRECT void init_libhttp();
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.6 KiB |
|
|
@ -1,96 +0,0 @@
|
|||
#ifndef __WEBBUFFEREDREADER_GM_H__
|
||||
#define __WEBBUFFEREDREADER_GM_H__
|
||||
// RHH
|
||||
|
||||
#include <string>
|
||||
#include "strtargetbuffer.h"
|
||||
#include "ringbuffer_slide.h"
|
||||
#include "application_log.h"
|
||||
|
||||
|
||||
class Http_BufferedReader : protected RingBuffer_Slide
|
||||
{
|
||||
inline bool GetTermedString(char * outdata, size_t maxlen,char termchar1, char termchar2);
|
||||
inline bool GetDoubleTermedString(char * outdata, int maxlen,char termchar1, char termchar2);
|
||||
inline bool GetTermedStringInPLace(char ** outdata,char termchars);
|
||||
inline bool GetTermedString(char * outdata, int maxlen,char * termchars);
|
||||
inline bool GetSizeString(StrTargetBuffer & outdata);
|
||||
public:
|
||||
inline Http_BufferedReader(int in_size = 8192) ;
|
||||
//
|
||||
// The Read Message Interface
|
||||
//
|
||||
inline void ReSet(void);
|
||||
inline int PumpCRRead(char * data, int maxdata, Socket_TCP &sck);
|
||||
inline int PumpHTTPHeaderRead(char * data, int maxdata, Socket_TCP &sck);
|
||||
inline int PumpSizeRead(StrTargetBuffer & outdata,Socket_TCP &sck);
|
||||
inline int PumpEofRead(StrTargetBuffer & outdata,Socket_TCP &sck);
|
||||
//inline int PumpMessageReader(CoreMessage &inmsg, Socket_TCP &sck);
|
||||
|
||||
|
||||
template < class SOCK_TYPE>
|
||||
inline int ReadPump(SOCK_TYPE &sck)
|
||||
{
|
||||
int answer = 0;
|
||||
size_t readsize = BufferAvailabe();
|
||||
|
||||
if(readsize < 1)
|
||||
{
|
||||
FullCompress();
|
||||
readsize = BufferAvailabe();
|
||||
}
|
||||
|
||||
|
||||
if(readsize > 0)
|
||||
{
|
||||
char * ff = GetBufferOpen();
|
||||
int gotbytes = sck.RecvData(ff,(int)readsize);
|
||||
|
||||
|
||||
if(gotbytes < 0) // some error
|
||||
{
|
||||
int er = GETERROR();
|
||||
// if(err != LOCAL_BLOCKING_ERROR )
|
||||
if(!sck.ErrorIs_WouldBlocking(gotbytes) )
|
||||
{
|
||||
answer = -3;
|
||||
LOGINFO("Http_BufferedReader::ReadPump->Socket Level Read Error %d %d %d %s",er,gotbytes,errno,sck.GetPeerName().get_ip_port().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
answer = 0; // try again nothing to read
|
||||
}
|
||||
}
|
||||
else if(gotbytes > 0) // ok got some lets process it
|
||||
{
|
||||
|
||||
_EndPos += gotbytes;
|
||||
answer = 1;
|
||||
}
|
||||
else // 0 mean other end disconect arggggg
|
||||
{
|
||||
answer = -1;
|
||||
LOGWARNING("Http_BufferedReader::ReadPump->Other End Closed Normal [%s]",sck.GetPeerName().get_ip_port().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string addstr = sck.GetPeerName().get_ip_port();
|
||||
LOGWARNING("Http_BufferedReader::ReadPump->** Very Important** No Internal buffer left for read[%s] BufferSIze=[%d][%d]",
|
||||
addstr.c_str(),
|
||||
AmountBuffered(),
|
||||
BufferAvailabe()
|
||||
);
|
||||
|
||||
answer = -2;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#include "http_bufferedreader.i"
|
||||
|
||||
#endif //__BUFFEREDREADER_GM_H__
|
||||
|
||||
|
||||
|
|
@ -1,296 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::GetTermedString
|
||||
// Description : a function that will peal a terminated string from the buffer
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char * outdata
|
||||
// Argument : int maxlen
|
||||
// Argument : char termchar1
|
||||
// Argument : char termchar2
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Http_BufferedReader::GetTermedString(char * outdata, size_t maxlen,char termchar1, char termchar2)
|
||||
{
|
||||
bool answer = false;
|
||||
size_t DataAvail = FastAmountBeffered();
|
||||
size_t MaxRead = maxlen;
|
||||
if(MaxRead > DataAvail)
|
||||
MaxRead = DataAvail;
|
||||
|
||||
char * wrk = FastGetMessageHead();
|
||||
for(size_t x=0; x< MaxRead; x++)
|
||||
{
|
||||
if(wrk[x] == termchar1 || wrk[x] == termchar2)
|
||||
{
|
||||
memcpy(outdata,wrk,x);
|
||||
outdata[x] = '\0';
|
||||
_StartPos += x+1;
|
||||
Compress();
|
||||
answer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::GetDoubleTermedString
|
||||
// Description : a function that will peal a terminated string from the buffer
|
||||
//
|
||||
// This is the interface for a web request....
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char * outdata
|
||||
// Argument : int maxlen
|
||||
// Argument : char termchar1
|
||||
// Argument : char termchar2
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Http_BufferedReader::GetDoubleTermedString(char * outdata, int maxlen,char termchar1, char termchar2)
|
||||
{
|
||||
bool answer = false;
|
||||
size_t DataAvail = FastAmountBeffered();
|
||||
size_t MaxRead = maxlen;
|
||||
if(MaxRead > DataAvail)
|
||||
MaxRead = DataAvail;
|
||||
|
||||
char * wrk = FastGetMessageHead();
|
||||
for(size_t x=1; x< MaxRead; x++)
|
||||
{
|
||||
if(
|
||||
(wrk[x] == termchar1 && wrk[x-1] == termchar1) ||
|
||||
(wrk[x] == termchar2 && wrk[x-1] == termchar2) ||
|
||||
( x >= 3 && wrk[x] == termchar1 && wrk[x-2] == termchar1 && wrk[x-1] == termchar2 && wrk[x-3] == termchar2 ) ||
|
||||
( x >= 3 && wrk[x] == termchar2 && wrk[x-2] == termchar2 && wrk[x-1] == termchar1 && wrk[x-3] == termchar1 )
|
||||
)
|
||||
{
|
||||
memcpy(outdata,wrk,x);
|
||||
outdata[x] = '\0';
|
||||
_StartPos += x+1;
|
||||
Compress();
|
||||
answer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::GetTermedStringInPLace
|
||||
// Description : Will peal a string inplace for reading
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char ** outdata
|
||||
// Argument : char termchars
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Http_BufferedReader::GetTermedStringInPLace(char ** outdata,char termchars)
|
||||
{
|
||||
bool answer = false;
|
||||
Compress();
|
||||
size_t MaxRead = FastAmountBeffered();
|
||||
char * wrk = FastGetMessageHead();
|
||||
for(size_t x=0; x< MaxRead; x++)
|
||||
{
|
||||
if(wrk[x] == termchars)
|
||||
{
|
||||
*outdata = wrk;
|
||||
wrk[x] = '\0';
|
||||
_StartPos += x+1;
|
||||
answer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::GetTermedString
|
||||
// Description : do a read of a termed string not in place
|
||||
//
|
||||
// Return type : bool
|
||||
// Argument : char * outdata
|
||||
// Argument : int maxlen
|
||||
// Argument : char * termchars
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Http_BufferedReader::GetTermedString(char * outdata, int maxlen,char * termchars)
|
||||
{
|
||||
bool answer = false;
|
||||
size_t DataAvail = FastAmountBeffered();
|
||||
size_t MaxRead = maxlen;
|
||||
if(MaxRead > DataAvail)
|
||||
MaxRead = DataAvail;
|
||||
int tstrsize = (int)strlen(termchars);
|
||||
|
||||
char * wrk = FastGetMessageHead();
|
||||
for(size_t x=0; x< MaxRead; x++)
|
||||
{
|
||||
if(memcmp(&wrk[x],termchars,tstrsize) == 0)
|
||||
{
|
||||
memcpy(outdata,wrk,x);
|
||||
outdata[x] = '\0';
|
||||
_StartPos += x+tstrsize;
|
||||
Compress();
|
||||
answer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::Http_BufferedReader
|
||||
// Description : constructore .. passes size up to ring buffer
|
||||
//
|
||||
// Return type : inline
|
||||
// Argument : int in_size
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline Http_BufferedReader::Http_BufferedReader(int in_size) : RingBuffer_Slide(in_size)
|
||||
{
|
||||
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::ReSet
|
||||
// Description : Reaset all read content.. IE zero's out buffer...
|
||||
//
|
||||
// If you lose framing this will not help
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void Http_BufferedReader::ReSet(void)
|
||||
{
|
||||
ResetContent();
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::PumpCRRead
|
||||
// Description : a upcall function to read a CR object off buffer
|
||||
//
|
||||
// Return type : inline int
|
||||
// Argument : char * data
|
||||
// Argument : int maxdata
|
||||
// Argument : Socket_TCP &sck
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Http_BufferedReader::PumpCRRead(char * data, int maxdata, Socket_TCP &sck)
|
||||
{
|
||||
if(GetTermedString(data,maxdata,'\r','\n') == true)
|
||||
return 1;
|
||||
|
||||
int rp = ReadPump(sck);
|
||||
if(rp == 0)
|
||||
return 0;
|
||||
|
||||
if(rp < 1)
|
||||
return -1;
|
||||
|
||||
if(GetTermedString(data,maxdata,'\r','\n') == true)
|
||||
return 1;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::PumpHTTPHeaderRead
|
||||
// Description : Will read a HTTP head ,, GET ..... or response from web server
|
||||
//
|
||||
// Return type : inline int
|
||||
// Argument : char * data
|
||||
// Argument : int maxdata
|
||||
// Argument : Socket_TCP &sck
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Http_BufferedReader::PumpHTTPHeaderRead(char * data, int maxdata, Socket_TCP &sck)
|
||||
{
|
||||
|
||||
if(GetDoubleTermedString(data,maxdata,'\r','\n') == true)
|
||||
return 1;
|
||||
|
||||
|
||||
int rp = ReadPump(sck);
|
||||
if(rp == 0)
|
||||
return 0;
|
||||
|
||||
if(rp < 1)
|
||||
return -1;
|
||||
|
||||
if(GetDoubleTermedString(data,maxdata,'\r','\n') == true)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int Http_BufferedReader::PumpSizeRead(StrTargetBuffer & outdata,Socket_TCP &sck)
|
||||
{
|
||||
if(GetSizeString(outdata) == true)
|
||||
return 1;
|
||||
|
||||
int rp = ReadPump(sck);
|
||||
if(rp == 0)
|
||||
return 0;
|
||||
|
||||
if(rp < 1)
|
||||
return -1;
|
||||
|
||||
if(GetSizeString(outdata) == true)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int Http_BufferedReader::PumpEofRead(StrTargetBuffer & outdata,Socket_TCP &sck)
|
||||
{
|
||||
// do a quick read
|
||||
{
|
||||
size_t MaxRead = FastAmountBeffered();
|
||||
if(MaxRead > 0)
|
||||
{
|
||||
char *ff = FastGetMessageHead();
|
||||
outdata.append(ff,MaxRead);
|
||||
_StartPos += MaxRead;
|
||||
Compress();
|
||||
}
|
||||
}
|
||||
|
||||
// pump the reader
|
||||
int rp = ReadPump(sck);
|
||||
if(rp == 0)
|
||||
return 0;
|
||||
|
||||
if(rp== -1) // eof
|
||||
{
|
||||
// if eof clean the mess
|
||||
size_t MaxRead = FastAmountBeffered();
|
||||
if(MaxRead > 0)
|
||||
{
|
||||
char *ff = FastGetMessageHead();
|
||||
outdata.append(ff,MaxRead);
|
||||
_StartPos += MaxRead;
|
||||
Compress();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if(rp < 1)
|
||||
return -1;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
inline bool Http_BufferedReader::GetSizeString(StrTargetBuffer & outdata)
|
||||
{
|
||||
size_t DataAvail = FastAmountBeffered();
|
||||
size_t MaxRead = outdata.left_to_fill();
|
||||
if(MaxRead > DataAvail)
|
||||
MaxRead = DataAvail;
|
||||
|
||||
char * wrk = FastGetMessageHead();
|
||||
if(MaxRead > 0)
|
||||
{
|
||||
|
||||
char *ff = FastGetMessageHead();
|
||||
outdata.append(ff,MaxRead);
|
||||
_StartPos += MaxRead;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
#include "http_connection.h"
|
||||
|
||||
TypeHandle HttpConnection::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
HttpConnection::HttpConnection(SOCKET sck,Socket_Address &inaddr) :
|
||||
_Timer(Time_Span(10,0)) ,
|
||||
_MyAddress(inaddr),
|
||||
_state(READING_HEADER)
|
||||
{
|
||||
SetSocket(sck);
|
||||
SetNonBlocking();
|
||||
SetReuseAddress();
|
||||
|
||||
_writer.reserve(102400);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
HttpConnection::~HttpConnection(void)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const Socket_Address & HttpConnection::GetMyAddress(void)
|
||||
{
|
||||
return _MyAddress;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int HttpConnection::DoReadHeader(char * message, int buffersize,Time_Clock ¤tTime)
|
||||
{
|
||||
int ans = _Reader.PumpHTTPHeaderRead(message,buffersize,*this);
|
||||
|
||||
if(ans != 0)
|
||||
{
|
||||
if(ans > 0)
|
||||
_headerDetail.assign(message,buffersize);
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
if(_Timer.Expired(currentTime) == true)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int HttpConnection::DoReadBody(char * message1, int buffersize,Time_Clock ¤tTime)
|
||||
{
|
||||
int ans = _Reader.PumpSizeRead(_bodyDetail,*this);
|
||||
|
||||
if(ans != 0)
|
||||
{
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
if(_Timer.Expired(currentTime) == true)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ok lets process this thing..
|
||||
_state = WAITING_TO_FINALIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int HttpConnection::ReadIt(char * message, int buffersize,Time_Clock ¤tTime)
|
||||
{
|
||||
switch (_state)
|
||||
{
|
||||
case(READING_HEADER):
|
||||
return DoReadHeader(message, buffersize,currentTime);
|
||||
break;
|
||||
|
||||
case(READING_POST):
|
||||
return DoReadBody(message, buffersize,currentTime);
|
||||
break;
|
||||
|
||||
case(WAITING_TO_FINALIZE):
|
||||
return TryAndFinalize();
|
||||
break;
|
||||
|
||||
case(WRITING_DATA):
|
||||
return CloseStateWriter(currentTime);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
};
|
||||
return ConnectionDoClose;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
CloseState HttpConnection::ProcessMessage(char * message,Time_Clock ¤tTime)
|
||||
{
|
||||
if(_state == READING_POST )
|
||||
{
|
||||
_state = WAITING_TO_FINALIZE;
|
||||
return ConnectionDoClose;
|
||||
}
|
||||
|
||||
|
||||
if(_parser.ParseThis(message) != true)
|
||||
{
|
||||
Reset();
|
||||
return ConnectionDoClose;
|
||||
}
|
||||
// if it is a post go into read details mode and
|
||||
// wait to get the post data..
|
||||
// we do not support any other methoid today
|
||||
if(_parser.GetRequestType() == "POST")
|
||||
{
|
||||
int context_length = _parser.getContentLength();
|
||||
if(context_length > 0)
|
||||
{
|
||||
//_DoingExtraRead = true;
|
||||
_state = READING_POST;
|
||||
_bodyDetail.SetDataSize(context_length);
|
||||
return ConnectionDoNotClose;
|
||||
}
|
||||
}
|
||||
|
||||
_state = WAITING_TO_FINALIZE;
|
||||
|
||||
_parser.SetBodyText(_bodyDetail);
|
||||
_Timer.ResetTime(currentTime);
|
||||
|
||||
if(BuildPage(_writer,_parser) != true)
|
||||
return ConnectionDoClose;
|
||||
|
||||
if(_state == WRITING_DATA)
|
||||
{
|
||||
if(CloseStateWriter(currentTime) <0)
|
||||
return ConnectionDoClose;
|
||||
}
|
||||
|
||||
return ConnectionDoNotClose;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int HttpConnection::CloseStateWriter(Time_Clock ¤tTime)
|
||||
{
|
||||
int fans = _writer.Flush(*this); // write error
|
||||
if(fans < 0)
|
||||
return -1;
|
||||
|
||||
if(_writer.AmountBuffered() <= 0) // all done
|
||||
return -1;
|
||||
|
||||
if(_Timer.Expired(currentTime) == true) // too long
|
||||
return -1;
|
||||
|
||||
return 0; // keep trying
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void HttpConnection::Reset()
|
||||
{
|
||||
_state = ABORTING;
|
||||
Close();
|
||||
_Timer.ForceToExpired();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
#ifndef HttpConnection_H
|
||||
#define HttpConnection_H
|
||||
////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#include "parsedhttprequest.h"
|
||||
#include "baseincomingset.h"
|
||||
|
||||
#include "bufferedwriter_growable.h"
|
||||
#include "http_bufferedreader.h"
|
||||
|
||||
|
||||
class HttpConnection : public Socket_TCP
|
||||
{
|
||||
protected:
|
||||
Http_BufferedReader _Reader;
|
||||
BufferedWriter_Growable _writer;
|
||||
Socket_Address _MyAddress;
|
||||
|
||||
Time_Out _Timer;
|
||||
|
||||
enum STATE_CONNECTIONS {
|
||||
READING_HEADER =1,
|
||||
READING_POST =2,
|
||||
WAITING_TO_FINALIZE =3,
|
||||
WRITING_DATA =4,
|
||||
ABORTING = 5,
|
||||
};
|
||||
|
||||
|
||||
STATE_CONNECTIONS _state;
|
||||
|
||||
|
||||
ParsedHttpRequest _parser;
|
||||
|
||||
StrTargetBuffer _bodyDetail;
|
||||
std::string _headerDetail;
|
||||
|
||||
int CloseStateWriter(Time_Clock ¤tTime);
|
||||
|
||||
public:
|
||||
virtual ~HttpConnection(void);
|
||||
const Socket_Address & GetMyAddress(void);
|
||||
virtual bool BuildPage( BufferedWriter_Growable &_writer, ParsedHttpRequest &parser) = 0;
|
||||
HttpConnection(SOCKET sck,Socket_Address &inaddr) ;
|
||||
|
||||
CloseState ProcessMessage(char * message,Time_Clock ¤tTime);
|
||||
int DoReadHeader(char * message, int buffersize,Time_Clock ¤tTime);
|
||||
int DoReadBody(char * message, int buffersize,Time_Clock ¤tTime);
|
||||
int ReadIt(char * message, int buffersize,Time_Clock ¤tTime);
|
||||
void Reset();
|
||||
|
||||
virtual CloseState TryAndFinalize() { _state = WRITING_DATA; ;return ConnectionDoNotClose; };
|
||||
|
||||
std::string GetFullmessage() { return _headerDetail + _bodyDetail; };
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
Socket_TCP::init_type();
|
||||
register_type(_type_handle, "HttpConnection",
|
||||
Socket_TCP::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
|
||||
#endif // HttpConnection_H
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
#include "socket_base.h"
|
||||
|
||||
|
||||
#include "http_connection.h"
|
||||
#include "baseincomingset.h"
|
||||
#include "socket_base.h"
|
||||
|
||||
|
||||
#include "http_request.h"
|
||||
|
||||
TypeHandle Http_Request::_type_handle;
|
||||
|
||||
typedef BaseIncomingSet< Http_Request , Socket_TCP_Listen , char [10240], char *> Http_Source_BaseIncomingSet;
|
||||
std::set< Http_Request * > Global_WebRequests_pendingNotify;
|
||||
static Http_Source_BaseIncomingSet Global_HttpManager;
|
||||
|
||||
bool Http_Request::HttpManager_Initialize( unsigned short port)
|
||||
{
|
||||
init_network();
|
||||
Socket_Address address;
|
||||
address.set_port(port);
|
||||
return Global_HttpManager.init(address);
|
||||
}
|
||||
|
||||
Http_Request * Http_Request::HttpManager_GetARequest()
|
||||
{
|
||||
Time_Clock Know;
|
||||
Global_HttpManager.PumpAll(Know);
|
||||
Http_Request * answer = NULL;
|
||||
std::set< Http_Request * >::iterator ii = Global_WebRequests_pendingNotify.begin();
|
||||
if(ii != Global_WebRequests_pendingNotify.end())
|
||||
{
|
||||
answer = *ii;
|
||||
Global_WebRequests_pendingNotify.erase(ii);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
#ifndef Http_Request_H_
|
||||
#define Http_Request_H_
|
||||
|
||||
class Http_Request;
|
||||
extern std::set< Http_Request * > Global_WebRequests_pendingNotify;
|
||||
|
||||
class Http_Request : public HttpConnection
|
||||
{
|
||||
public:
|
||||
Http_Request(SOCKET sck,Socket_Address &inaddr) : HttpConnection(sck,inaddr)
|
||||
{
|
||||
};
|
||||
|
||||
~Http_Request()
|
||||
{
|
||||
Global_WebRequests_pendingNotify.erase(this);
|
||||
};
|
||||
bool BuildPage( BufferedWriter_Growable &_writer, ParsedHttpRequest &parser)
|
||||
{
|
||||
Global_WebRequests_pendingNotify.insert((Http_Request *)this);
|
||||
|
||||
_state = WAITING_TO_FINALIZE;
|
||||
_Timer.ResetAll(Time_Clock::GetCurrentTime(),Time_Span(9999999,0));
|
||||
return true;
|
||||
};
|
||||
|
||||
CloseState TryAndFinalize()
|
||||
{
|
||||
return ConnectionDoNotClose;
|
||||
};
|
||||
|
||||
PUBLISHED:
|
||||
|
||||
std::string GetRequestType()
|
||||
{
|
||||
return _parser.GetRequestType();
|
||||
}
|
||||
|
||||
std::string GetRawRequest()
|
||||
{
|
||||
return _parser.GetRawRequest();
|
||||
}
|
||||
|
||||
std::string GetRequestURL()
|
||||
{
|
||||
return _parser.GetRequestURL();
|
||||
}
|
||||
|
||||
std::string GetSourceAddress()
|
||||
{
|
||||
return _MyAddress.get_ip_port();
|
||||
}
|
||||
|
||||
void AppendToResponse(const std::string &in)
|
||||
{
|
||||
_writer+=in;
|
||||
}
|
||||
|
||||
|
||||
void SendThisResponse(const std::string &in)
|
||||
{
|
||||
_writer+=in;
|
||||
Finish();
|
||||
}
|
||||
|
||||
void Finish()
|
||||
{
|
||||
_Timer.ResetAll(Time_Clock::GetCurrentTime(),Time_Span(10,0));
|
||||
_state = WRITING_DATA;
|
||||
};
|
||||
void Abort()
|
||||
{
|
||||
_state = ABORTING;
|
||||
};
|
||||
|
||||
|
||||
bool HasOption(std::string in)
|
||||
{
|
||||
const std::string * answer = _parser.GetOption(in);
|
||||
if(answer != NULL)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const char * GetOption(std::string in)
|
||||
{
|
||||
const std::string * answer = _parser.GetOption(in);
|
||||
if(answer != NULL)
|
||||
return answer->c_str();
|
||||
return "";
|
||||
}
|
||||
std::string GetRequestOptionString()
|
||||
{
|
||||
return _parser.GetRequestOptionString();
|
||||
}
|
||||
|
||||
static bool HttpManager_Initialize( unsigned short port);
|
||||
static Http_Request * HttpManager_GetARequest();
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
HttpConnection::init_type();
|
||||
register_type(_type_handle, "Http_Request",
|
||||
HttpConnection::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // Http_Request_H_
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
import sys
|
||||
|
||||
"""
|
||||
Class to extract system information from a Linux Box via /proc
|
||||
|
||||
The following variables are accessable:
|
||||
|
||||
os
|
||||
cpu
|
||||
totalRAM
|
||||
availableRAM
|
||||
totalVM
|
||||
availableVM
|
||||
loadAvg
|
||||
|
||||
Example:
|
||||
|
||||
s = SystemInformation()
|
||||
print s.os
|
||||
|
||||
s.refresh() # If you need to refresh the dynamic data
|
||||
|
||||
"""
|
||||
|
||||
class SystemInformation:
|
||||
def __init__(self):
|
||||
|
||||
# Just in case sombody called this class by accident, we should
|
||||
# check to make sure the OS is Linux before continuing
|
||||
|
||||
assert sys.platform == 'linux2', "Not a Linux based system. This class should not be called"
|
||||
|
||||
self.os = self.__getOS()
|
||||
self.cpu = self.__getCPU()
|
||||
self.totalRAM, self.availableRAM, self.totalVM, self.availableVM = self.__getMemory()
|
||||
self.loadAvg = self.__getLoadAvg()
|
||||
|
||||
def refresh(self):
|
||||
self.totalRAM, self.availableRAM, self.totalVM, self.availableVM = self.__getMemory()
|
||||
self.loadAvg = self.__getLoadAvg()
|
||||
|
||||
def __getloadAvg(self):
|
||||
loadAvg = open('/proc/loadavg')
|
||||
procloadAvg = loadAvg.read()
|
||||
loadAvg.close()
|
||||
# Lets remove the \n from the raw string
|
||||
procloadAvg = procloadAvg.replace('\n','')
|
||||
return procloadAvg
|
||||
|
||||
def __getOS(self):
|
||||
procOS = open('/proc/version')
|
||||
procOSRaw = procOS.read()
|
||||
procOS.close()
|
||||
# Lets remove the \n before returning the version string
|
||||
procOSRaw = procOSRaw.replace('\n', '')
|
||||
return procOSRaw
|
||||
|
||||
def __getCPU(self):
|
||||
procCPU = open('/proc/cpuinfo')
|
||||
procCPURaw = procCPU.read()
|
||||
procCPU.close()
|
||||
del procCPU
|
||||
procCPURaw = procCPURaw.split('\n')
|
||||
# Lets first figure out how many CPUs are in the system
|
||||
cpuCount = 0
|
||||
modelName = ''
|
||||
cpuMHz = ''
|
||||
for element in procCPURaw:
|
||||
if element.find('processor') != -1:
|
||||
cpuCount += 1
|
||||
# cpuCount now has the total number of CPUs
|
||||
|
||||
# Next, on to the Model of the Processor
|
||||
for element in procCPURaw:
|
||||
if element.find('model name') != -1:
|
||||
modelName = element[element.find(':')+2:]
|
||||
break
|
||||
|
||||
# Next, on to the clock speed
|
||||
for element in procCPURaw:
|
||||
if element.find('cpu MHz') != -1:
|
||||
cpuMHz = element[element.find(':')+2:]
|
||||
break
|
||||
# Now that we have the info, time to return a string
|
||||
|
||||
return "%s\t%d @ %s MHz" % (modelName, cpuCount, cpuMHz)
|
||||
|
||||
|
||||
def __getMemory(self):
|
||||
procMemory = open('/proc/meminfo')
|
||||
procMemoryRaw = procMemory.read()
|
||||
procMemory.close()
|
||||
del procMemory
|
||||
procMemoryRaw = procMemoryRaw.split('\n')
|
||||
# We are looking for the following:
|
||||
# MemTotal, MemFree, SwapTotal, SwapFree
|
||||
|
||||
# Lets start with MemTotal first
|
||||
|
||||
memTotal = ''
|
||||
for element in procMemoryRaw:
|
||||
if element.find('MemTotal:') != -1:
|
||||
memTotal = element.split(':')[1].replace(' ','')
|
||||
break
|
||||
# Next MemFree:
|
||||
|
||||
memFree = ''
|
||||
for element in procMemoryRaw:
|
||||
if element.find('MemFree:') != -1:
|
||||
memFree = element.split(':')[1].replace(' ','')
|
||||
break
|
||||
|
||||
# SwapTotal:
|
||||
|
||||
swapTotal = ''
|
||||
for element in procMemoryRaw:
|
||||
if element.find('SwapTotal:') != -1:
|
||||
memFree = element.split(':')[1].replace(' ','')
|
||||
break
|
||||
|
||||
# SwapFree:
|
||||
|
||||
swapFree = ''
|
||||
for element in procMemoryRaw:
|
||||
if element.find('SwapFree:') != -1:
|
||||
memFree = element.split(':')[1].replace(' ','')
|
||||
break
|
||||
return memTotal, memFree, swapTotal, swapFree
|
||||
|
||||
if __name__ == "__main__":
|
||||
s = SystemInformation()
|
||||
print s.cpu
|
||||
print s.totalRAM
|
||||
print s.os
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
#include "config_http.cxx"
|
||||
#include "http_connection.cxx"
|
||||
#include "parsedhttprequest.cxx"
|
||||
#include "http_request.cxx"
|
||||
|
||||
|
|
@ -1,214 +0,0 @@
|
|||
#pragma warning(disable : 4789)
|
||||
#pragma warning(disable : 4786)
|
||||
|
||||
#include "parsedhttprequest.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline std::string & trimleft_inplace(std::string & s)
|
||||
{
|
||||
s.erase(0, s.find_first_not_of(" \t\n\r"));
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline std::string & trimright_inplace(std::string & s)
|
||||
{
|
||||
size_t idx = s.find_last_not_of(" \t\n\r");
|
||||
|
||||
if (std::string::npos == idx)
|
||||
{
|
||||
s.erase();
|
||||
}
|
||||
else
|
||||
{
|
||||
char c = s.at(idx);
|
||||
s.erase(idx, std::string::npos);
|
||||
s.append(1, c);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline std::string & trim_inplace(std::string & s)
|
||||
{
|
||||
trimleft_inplace(s);
|
||||
trimright_inplace(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::string trim_tonew(const std::string &in)
|
||||
{
|
||||
std::string ss = in;
|
||||
return trim_inplace(ss);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::string ParsedHttpRequest::deCanonicalize(std::string &inval)
|
||||
{
|
||||
std::string work("");
|
||||
unsigned int x=0;
|
||||
while (x < inval.size())
|
||||
{
|
||||
switch(inval[x])
|
||||
{
|
||||
case('+'):
|
||||
work+=' ';
|
||||
x++;
|
||||
break;
|
||||
|
||||
case('%'):
|
||||
if(x+2 < inval.size())
|
||||
{
|
||||
x++;
|
||||
char aa[5];
|
||||
char * end;
|
||||
aa[0] = inval[x++];
|
||||
aa[1] = inval[x++];
|
||||
aa[2] = '\0';
|
||||
char c = ( char ) strtoul(aa,&end,16);
|
||||
work+=c;
|
||||
}
|
||||
else
|
||||
x+=3;
|
||||
break;
|
||||
|
||||
default:
|
||||
work+=inval[x++];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return work;
|
||||
}
|
||||
|
||||
size_t ParsedHttpRequest::PullCR(std::string &src, std::string &dst)
|
||||
{
|
||||
size_t offset = src.find(' ');
|
||||
if(offset >= 0 )
|
||||
{
|
||||
dst = src.substr(0,offset);
|
||||
src = src.substr(offset+1);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
void ParsedHttpRequest::clear(void)
|
||||
{
|
||||
_RequestType = "";
|
||||
_parameters.clear();
|
||||
}
|
||||
|
||||
const std::string * ParsedHttpRequest::GetOption(const std::string & query)
|
||||
{
|
||||
std::map<std::string,std::string>::iterator ii;
|
||||
ii = _parameters.find(query);
|
||||
if(ii == _parameters.end())
|
||||
return NULL;
|
||||
|
||||
return &ii->second;
|
||||
}
|
||||
|
||||
|
||||
bool ParsedHttpRequest::GetOption(const std::string & query, std::string & out_value)
|
||||
{
|
||||
std::map<std::string,std::string>::iterator ii;
|
||||
ii = _parameters.find(query);
|
||||
if(ii == _parameters.end())
|
||||
{
|
||||
out_value = "";
|
||||
return false;
|
||||
}
|
||||
out_value = ii->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParsedHttpRequest::ParseThis(char * request)
|
||||
{
|
||||
_Raw_Text = request;
|
||||
// printf("%s\n\n",request);
|
||||
|
||||
|
||||
std::string work1(_Raw_Text);
|
||||
for(size_t pos = work1.find_first_of("\n\r\0") ; pos != std::string::npos ; pos = work1.find_first_of("\n\r\0") )
|
||||
{
|
||||
std::string line1 = work1.substr(0,pos);
|
||||
work1 = work1.substr(pos+1);
|
||||
if(line1.size() > 2)
|
||||
{
|
||||
// printf(" Line[%s]\n",line1.c_str());
|
||||
size_t i_pos = line1.find(':');
|
||||
if(i_pos != std::string::npos && i_pos > 1)
|
||||
{
|
||||
std::string noune = trim_tonew(line1.substr(0,i_pos));
|
||||
std::string verb = trim_tonew(line1.substr(i_pos+1));
|
||||
|
||||
//printf(" Noune [%s][%s]\n",noune.c_str(),verb.c_str());
|
||||
_header_Lines[noune] = verb;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get the url for the request ..
|
||||
//
|
||||
std::string work(request);
|
||||
std::string line1 = work.substr(0,work.find_first_of("\n\r\0"));
|
||||
if(line1.size() < 4)
|
||||
return false;
|
||||
|
||||
if(PullCR(line1,_RequestType) < 3)
|
||||
return false;
|
||||
|
||||
if(PullCR(line1,_RequestText) < 1)
|
||||
return false;
|
||||
|
||||
size_t loc = (int)_RequestText.find('?');
|
||||
if(loc != std::string::npos)
|
||||
{
|
||||
_Requestoptions = _RequestText.substr(loc+1);
|
||||
_RequestText = _RequestText.substr(0,loc);
|
||||
}
|
||||
|
||||
return ProcessOptionString(_Requestoptions);
|
||||
}
|
||||
|
||||
std::string & ParsedHttpRequest::GetRequestURL(void)
|
||||
{
|
||||
return _RequestText;
|
||||
};
|
||||
|
||||
bool ParsedHttpRequest::ProcessOptionString(std::string str)
|
||||
{
|
||||
size_t loc;
|
||||
for(loc = str.find('&'); loc != std::string::npos; loc = str.find('&'))
|
||||
{
|
||||
std::string valset = str.substr(0,loc);
|
||||
str = str.substr(loc+1);
|
||||
if(ProcessParamSet(valset) != true)
|
||||
return false;
|
||||
}
|
||||
return ProcessParamSet(str);
|
||||
};
|
||||
|
||||
bool ParsedHttpRequest::ProcessParamSet(std::string &str)
|
||||
{
|
||||
std::string val("");
|
||||
size_t loc = str.find('=');
|
||||
|
||||
if(loc != std::string::npos)
|
||||
{
|
||||
val = str.substr(loc+1);
|
||||
str = str.substr(0,loc);
|
||||
|
||||
std::string ind1 = deCanonicalize(str);
|
||||
_parameters[ind1] = deCanonicalize(val);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
#ifndef __PARSEDHTTPREQUEST_GM_H__
|
||||
#define __PARSEDHTTPREQUEST_GM_H__
|
||||
|
||||
#include "string"
|
||||
#include "map"
|
||||
#include "stdlib.h"
|
||||
|
||||
|
||||
class ParsedHttpRequest
|
||||
{
|
||||
protected:
|
||||
std::string _Raw_Text;
|
||||
std::string _RequestType;
|
||||
std::string _RequestText;
|
||||
std::string _Requestoptions;
|
||||
std::string _BodyText;
|
||||
|
||||
|
||||
std::map<std::string,std::string> _parameters;
|
||||
std::map<std::string,std::string> _header_Lines;
|
||||
|
||||
std::string deCanonicalize(std::string &inval);
|
||||
size_t PullCR(std::string &src, std::string &dst);
|
||||
|
||||
public:
|
||||
void clear(void);
|
||||
const std::string GetRequestOptionString() { return _Requestoptions; };
|
||||
const std::string * GetOption(const std::string & query);
|
||||
bool GetOption(const std::string & query, std::string & out_value);
|
||||
bool ParseThis(char * request);
|
||||
std::string & GetRequestURL(void);
|
||||
const std::string & GetRawRequest(void) const { return _Raw_Text; };
|
||||
const std::string & GetRequestType(void) const { return _RequestType; };
|
||||
bool ProcessOptionString(std::string str);
|
||||
bool ProcessParamSet(std::string &str);
|
||||
|
||||
|
||||
void SetBodyText(const std::string & text)
|
||||
{
|
||||
_BodyText = text;
|
||||
}
|
||||
|
||||
const std::string & getBodyText() { return _BodyText; };
|
||||
|
||||
int getContentLength()
|
||||
{
|
||||
int answer = 0;
|
||||
std::map<std::string,std::string>::iterator ii = _header_Lines.find("Content-Length");
|
||||
if(ii != _header_Lines.end())
|
||||
answer = atol(ii->second.c_str());
|
||||
|
||||
return answer;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
class ParsedHttpResponse
|
||||
{
|
||||
std::string _Raw_Text;
|
||||
std::string _response_header;
|
||||
|
||||
std::map<std::string,std::string> _header_Lines;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
std::string GetresponseCode()
|
||||
{
|
||||
std::string answer;
|
||||
|
||||
size_t pos = _response_header.find_first_of(" ");
|
||||
if(pos != std::string::npos)
|
||||
answer = support::trim_tonew(_response_header.substr(pos,100));
|
||||
|
||||
|
||||
pos = answer.find_first_of(" \t\n\r\0");
|
||||
if(pos != std::string::npos)
|
||||
answer = support::trim_tonew(answer.substr(0,pos));
|
||||
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
bool ParseThis(const std::string &response)
|
||||
{
|
||||
_Raw_Text = response;
|
||||
|
||||
int line_number = 0;
|
||||
std::string work1(_Raw_Text);
|
||||
for(size_t pos = work1.find_first_of("\n\r\0") ; pos != std::string::npos ; pos = work1.find_first_of("\n\r\0") )
|
||||
{
|
||||
std::string line1 = work1.substr(0,pos);
|
||||
work1 = work1.substr(pos+1);
|
||||
if(line1.size() > 2)
|
||||
{
|
||||
|
||||
if(line_number == 0 && line1.substr(0,4) == "HTTP")
|
||||
{
|
||||
// the first line...
|
||||
_response_header = line1;
|
||||
// printf("[%s]\n",line1.c_str());
|
||||
}
|
||||
|
||||
size_t i_pos = line1.find(':');
|
||||
if(i_pos != std::string::npos && i_pos > 1)
|
||||
{
|
||||
std::string noune = support::trim_tonew(line1.substr(0,i_pos));
|
||||
std::string verb = support::trim_tonew(line1.substr(i_pos+1));
|
||||
_header_Lines[noune] = verb;
|
||||
}
|
||||
line_number++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return !_response_header.empty();
|
||||
}
|
||||
|
||||
size_t PullCR(std::string &src, std::string &dst)
|
||||
{
|
||||
size_t offset = src.find(' ');
|
||||
if(offset >= 0 )
|
||||
{
|
||||
dst = src.substr(0,offset);
|
||||
src = src.substr(offset+1);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
int getContentLength()
|
||||
{
|
||||
int answer = 0;
|
||||
std::map<std::string,std::string>::iterator ii = _header_Lines.find("Content-Length");
|
||||
if(ii != _header_Lines.end())
|
||||
answer = atol(ii->second.c_str());
|
||||
|
||||
return answer;
|
||||
};
|
||||
|
||||
};
|
||||
*/
|
||||
|
||||
#endif //__PARSEDHTTPREQUEST_GM_H__
|
||||
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
# copied from recaptcha-client-1.0.5
|
||||
# http://pypi.python.org/pypi/recaptcha-client
|
||||
# http://recaptcha.net/resources.html
|
||||
|
||||
import urllib2, urllib
|
||||
|
||||
API_SSL_SERVER="https://api-secure.recaptcha.net"
|
||||
API_SERVER="http://api.recaptcha.net"
|
||||
VERIFY_SERVER="api-verify.recaptcha.net"
|
||||
|
||||
class RecaptchaResponse(object):
|
||||
def __init__(self, is_valid, error_code=None):
|
||||
self.is_valid = is_valid
|
||||
self.error_code = error_code
|
||||
|
||||
def displayhtml (public_key,
|
||||
use_ssl = False,
|
||||
error = None):
|
||||
"""Gets the HTML to display for reCAPTCHA
|
||||
|
||||
public_key -- The public api key
|
||||
use_ssl -- Should the request be sent over ssl?
|
||||
error -- An error message to display (from RecaptchaResponse.error_code)"""
|
||||
|
||||
error_param = ''
|
||||
if error:
|
||||
error_param = '&error=%s' % error
|
||||
|
||||
if use_ssl:
|
||||
server = API_SSL_SERVER
|
||||
else:
|
||||
server = API_SERVER
|
||||
|
||||
return """<script type="text/javascript" src="%(ApiServer)s/challenge?k=%(PublicKey)s%(ErrorParam)s"></script>
|
||||
|
||||
<noscript>
|
||||
<iframe src="%(ApiServer)s/noscript?k=%(PublicKey)s%(ErrorParam)s" height="300" width="500" frameborder="0"></iframe><br />
|
||||
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
|
||||
<input type='hidden' name='recaptcha_response_field' value='manual_challenge' />
|
||||
</noscript>
|
||||
""" % {
|
||||
'ApiServer' : server,
|
||||
'PublicKey' : public_key,
|
||||
'ErrorParam' : error_param,
|
||||
}
|
||||
|
||||
|
||||
def submit (recaptcha_challenge_field,
|
||||
recaptcha_response_field,
|
||||
private_key,
|
||||
remoteip):
|
||||
"""
|
||||
Submits a reCAPTCHA request for verification. Returns RecaptchaResponse
|
||||
for the request
|
||||
|
||||
recaptcha_challenge_field -- The value of recaptcha_challenge_field from the form
|
||||
recaptcha_response_field -- The value of recaptcha_response_field from the form
|
||||
private_key -- your reCAPTCHA private key
|
||||
remoteip -- the user's ip address
|
||||
"""
|
||||
|
||||
if not (recaptcha_response_field and recaptcha_challenge_field and
|
||||
len (recaptcha_response_field) and len (recaptcha_challenge_field)):
|
||||
return RecaptchaResponse (is_valid = False, error_code = 'incorrect-captcha-sol')
|
||||
|
||||
|
||||
def encode_if_necessary(s):
|
||||
if isinstance(s, unicode):
|
||||
return s.encode('utf-8')
|
||||
return s
|
||||
|
||||
params = urllib.urlencode ({
|
||||
'privatekey': encode_if_necessary(private_key),
|
||||
'remoteip' : encode_if_necessary(remoteip),
|
||||
'challenge': encode_if_necessary(recaptcha_challenge_field),
|
||||
'response' : encode_if_necessary(recaptcha_response_field),
|
||||
})
|
||||
|
||||
request = urllib2.Request (
|
||||
url = "http://%s/verify" % VERIFY_SERVER,
|
||||
data = params,
|
||||
headers = {
|
||||
"Content-type": "application/x-www-form-urlencoded",
|
||||
"User-agent": "reCAPTCHA Python"
|
||||
}
|
||||
)
|
||||
|
||||
httpresp = urllib2.urlopen (request)
|
||||
|
||||
return_values = httpresp.read ().splitlines ();
|
||||
# DCR: prevent garbage leak (really)
|
||||
httpresp.fp._sock.recv = None
|
||||
httpresp.close();
|
||||
|
||||
return_code = return_values [0]
|
||||
|
||||
if (return_code == "true"):
|
||||
return RecaptchaResponse (is_valid=True)
|
||||
else:
|
||||
return RecaptchaResponse (is_valid=False, error_code = return_values [1])
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
#ifndef __RINGBUFFER_GM_H__
|
||||
#define __RINGBUFFER_GM_H__
|
||||
////////////////////////////////////////////
|
||||
|
||||
// RHH
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GmRingBuffer
|
||||
// Description : This is an implemention of the membuffer with ring
|
||||
// buffer interface on it....
|
||||
//
|
||||
// Main target right know is base class for network
|
||||
// stream buffering both input and output
|
||||
//
|
||||
// see BufferedReader_Gm
|
||||
// BufferedWriter_Gm
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#include "membuffer.h"
|
||||
class RingBuffer_Slide : protected MemBuffer
|
||||
{
|
||||
protected:
|
||||
size_t _StartPos;
|
||||
size_t _EndPos;
|
||||
inline char * GetMessageHead(void);
|
||||
inline char * GetBufferOpen(void);
|
||||
inline void ForceWindowSlide(void);
|
||||
#define FastGetMessageHead() (_Buffer+_StartPos)
|
||||
#define FastAmountBeffered() (_EndPos - _StartPos)
|
||||
|
||||
inline bool PutFast(const char * data, size_t len);
|
||||
|
||||
public:
|
||||
inline size_t AmountBuffered(void);
|
||||
inline size_t BufferAvailabe(void);
|
||||
inline void ResetContent(void);
|
||||
|
||||
inline RingBuffer_Slide(size_t in_size = 4096);
|
||||
inline void FullCompress(void);
|
||||
inline void Compress(void);
|
||||
inline bool Put(const char * data, size_t len);
|
||||
inline bool Get(char * data, size_t len);
|
||||
};
|
||||
|
||||
#include "ringbuffer_slide.i"
|
||||
|
||||
#endif //__RINGBUFFER_GM_H__
|
||||
|
||||
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::GetMessageHead
|
||||
// Description : This will get a pointer to the fist undelivered data in buffer
|
||||
// Return type : char *
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline char * RingBuffer_Slide::GetMessageHead(void)
|
||||
{
|
||||
return _Buffer+_StartPos;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::GetBufferOpen
|
||||
// Description : This will get the first writabe section of the buffer space
|
||||
// Return type :
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline char * RingBuffer_Slide::GetBufferOpen(void)
|
||||
{
|
||||
return _Buffer+_EndPos;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::ForceWindowSlide
|
||||
// Description : Will force a compression of data // shift left to start position
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline void RingBuffer_Slide::ForceWindowSlide(void)
|
||||
{
|
||||
size_t len = AmountBuffered();
|
||||
if(len > 0 && _StartPos != 0) // basic flush left..
|
||||
{
|
||||
memmove(_Buffer,GetMessageHead(),len);
|
||||
_StartPos = 0;
|
||||
_EndPos = len;
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::AmountBuffered
|
||||
// Description : Will report the number of unread chars in buffer
|
||||
// Return type : int
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline size_t RingBuffer_Slide::AmountBuffered(void)
|
||||
{
|
||||
return _EndPos - _StartPos;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::BufferAvailabe
|
||||
// Description : Will report amount of data that is contiguas that can be writen at
|
||||
// the location returned by GetBufferOpen
|
||||
// Return type : inline int
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline size_t RingBuffer_Slide::BufferAvailabe(void)
|
||||
{
|
||||
return GetBufferSize() - _EndPos;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::ResetContent
|
||||
// Description : Throw away all inread information
|
||||
// Return type : void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
void RingBuffer_Slide::ResetContent(void)
|
||||
{
|
||||
_StartPos = 0;
|
||||
_EndPos = 0;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::RingBuffer_Slide
|
||||
// Description :
|
||||
// Return type : inline
|
||||
// Argument : int in_size
|
||||
//////////////////////////////////////////////////////////
|
||||
inline RingBuffer_Slide::RingBuffer_Slide(size_t in_size) : MemBuffer(in_size)
|
||||
{
|
||||
_EndPos = 0;
|
||||
_StartPos = 0;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::FullCompress
|
||||
// Description : Force a compress of the data
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline void RingBuffer_Slide::FullCompress(void)
|
||||
{
|
||||
if(_StartPos == _EndPos)
|
||||
{
|
||||
_StartPos = 0;
|
||||
_EndPos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ForceWindowSlide();
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::Compress
|
||||
// Description : Try and do a intelegent compress of the data space
|
||||
// the algorithem is really stupid right know.. just say if i have
|
||||
// read past 1/2 my space do a compress...Im open for sugestions
|
||||
//
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline void RingBuffer_Slide::Compress(void)
|
||||
{
|
||||
if(_StartPos == _EndPos)
|
||||
{
|
||||
_StartPos = 0;
|
||||
_EndPos = 0;
|
||||
}
|
||||
else if(_StartPos >= GetBufferSize() / 2)
|
||||
{
|
||||
ForceWindowSlide();
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::Put
|
||||
// Description : Adds Data to a ring Buffer
|
||||
// Will do a compress if needed so pointers suplied by Get Call are no longer valide
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char * data
|
||||
// Argument : int len
|
||||
//////////////////////////////////////////////////////////
|
||||
inline bool RingBuffer_Slide::Put(const char * data, size_t len)
|
||||
{
|
||||
bool answer = false;
|
||||
|
||||
if(len > BufferAvailabe() )
|
||||
Compress();
|
||||
|
||||
if(len <= BufferAvailabe() )
|
||||
{
|
||||
memcpy(GetBufferOpen(),data,len);
|
||||
_EndPos += len;
|
||||
answer = true;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::PutFast
|
||||
// Description :
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : const char * data
|
||||
// Argument : int len
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool RingBuffer_Slide::PutFast(const char * data, size_t len)
|
||||
{
|
||||
// no checking be carefull
|
||||
memcpy(GetBufferOpen(),data,len); // should i be using memcopy..
|
||||
_EndPos += len;
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::Get
|
||||
// Description : will copy the data ..
|
||||
// false indicates not enogh data to read .. sorry...
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char * data
|
||||
// Argument : int len
|
||||
//////////////////////////////////////////////////////////
|
||||
inline bool RingBuffer_Slide::Get(char * data, size_t len)
|
||||
{
|
||||
bool answer = false;
|
||||
|
||||
if(len <= AmountBuffered() )
|
||||
{
|
||||
memcpy(data,GetMessageHead(),len);
|
||||
_StartPos += len;
|
||||
Compress();
|
||||
answer = true;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
#ifndef StrTargetBuffer_h_
|
||||
#define StrTargetBuffer_h_
|
||||
|
||||
#include <string>
|
||||
|
||||
class StrTargetBuffer : public std::string
|
||||
{
|
||||
size_t _target_size;
|
||||
public:
|
||||
StrTargetBuffer() : std::string(), _target_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
size_t left_to_fill()
|
||||
{
|
||||
if(_target_size < size())
|
||||
return 0;
|
||||
|
||||
return _target_size - size();
|
||||
};
|
||||
|
||||
void SetDataSize(size_t target)
|
||||
{
|
||||
_target_size = target;
|
||||
}
|
||||
|
||||
size_t GetTargetSize() { return _target_size; };
|
||||
};
|
||||
|
||||
#endif // StrTargetBuffer_h_
|
||||
|
||||
|
|
@ -1,487 +0,0 @@
|
|||
"""This is a web based inspector for the AI System. It can be accessed via
|
||||
http://hostname.domain:port/inspect
|
||||
|
||||
The hostname.domain would of course be the computer that the AI is running on.
|
||||
The port will need to be defined when the instance is inited.
|
||||
|
||||
"""
|
||||
|
||||
import string, time, direct, inspect, socket
|
||||
from operator import itemgetter
|
||||
from direct.http import WebRequest
|
||||
from socket import gethostname
|
||||
from direct.task.Task import Task
|
||||
from sys import platform
|
||||
from pirates.uberdog.AIMagicWordTrade import AIMagicWordTrade
|
||||
from pirates.quest.QuestDB import QuestDict
|
||||
|
||||
# Need to figure out which systeminfo module to import
|
||||
if platform == 'win32':
|
||||
from windowsSystemInfo import SystemInformation
|
||||
else:
|
||||
from linuxSystemInfo import SystemInformation
|
||||
|
||||
class aiWebServer(SystemInformation):
|
||||
def __init__(self, air, listenPort=8080):
|
||||
SystemInformation.__init__(self)
|
||||
self.listenPort = listenPort
|
||||
self.air = simbase.air
|
||||
# self.taskMgr = Task.TaskManager()
|
||||
if __debug__:
|
||||
print "Listen port set to: %d" % self.listenPort
|
||||
# Start dispatcher
|
||||
self.web = WebRequest.WebRequestDispatcher()
|
||||
self.web.listenOnPort(self.listenPort)
|
||||
self.localHostName = gethostname()
|
||||
self.web.registerGETHandler('inspect', self.inspect)
|
||||
self.web.registerGETHandler('systemInfo', self.systemInfo)
|
||||
self.web.registerGETHandler('oMenu', self.oMenu)
|
||||
self.web.registerGETHandler('oType', self.oType)
|
||||
self.web.registerGETHandler('oInst', self.oInst)
|
||||
self.web.registerGETHandler('blank', self.blank)
|
||||
self.web.registerGETHandler('magicWord', self.magicWord)
|
||||
self.startCheckingIncomingHTTP()
|
||||
|
||||
self.air.setConnectionURL("http://%s:%s/" % (socket.gethostbyname(socket.gethostname()),self.HTTPListenPort))
|
||||
|
||||
def magicWord(self, replyTo, **kw):
|
||||
# This will process Magic Word requests
|
||||
# Currently the following words are supported:
|
||||
# ~aiobjectcount
|
||||
# ~aitaskmgr
|
||||
# ~aijobmgr
|
||||
# ~assignQuest
|
||||
# ~money
|
||||
|
||||
# First we need to figure out which magic word is being called
|
||||
try:
|
||||
theMagicWord = kw['magicWord']
|
||||
except KeyError:
|
||||
# MagicWord issue. Malformed URL
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>Magic Word Error</title>\n</head><body>Please check the URL. Transaction could not be completed. Malformed URL.</BODY>\n</HTML>')
|
||||
return
|
||||
|
||||
# Next we execute the magic word request
|
||||
if theMagicWord == 'aiobjectcount':
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>%s</title>\n</head><body><PRE>%s</PRE></body>\n</HTML>' % (theMagicWord, simbase.air.webPrintObjectCount()))
|
||||
return
|
||||
elif theMagicWord == 'aitaskmgr':
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>%s</title>\n</head><body><PRE>%s</PRE></body>\n</HTML>' % (theMagicWord, taskMgr))
|
||||
return
|
||||
elif theMagicWord == 'aijobmgr':
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>%s</title>\n</head><body><PRE>%s</PRE></body>\n</HTML>' % (theMagicWord, jobMgr))
|
||||
|
||||
elif theMagicWord == 'money':
|
||||
# First, generate the Avatar HTML Select widget.
|
||||
|
||||
selectWidget = self.genAvSelect()
|
||||
|
||||
# Now that we've built the avatar list, we can repond with the HTML
|
||||
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>Money</title>\n</head><body><form method="get" action="magicWord" name="magicWord">AvatarID: %s\nAmmount: <input maxlength="3" size="3" name="amount" value="100"><br><INPUT TYPE=HIDDEN NAME="magicWord" value="MONEY_ADD"><button value="Submit" name="Submit"></button><br></form></body>\n</HTML>' % selectWidget)
|
||||
|
||||
elif theMagicWord == 'MONEY_ADD':
|
||||
av = kw['avatarId']
|
||||
count = kw['amount']
|
||||
try:
|
||||
av = int(av)
|
||||
count = int(count)
|
||||
except ValueError:
|
||||
# One or both of the two args could not be converted into a int
|
||||
# This being the case, the transaction mut be stopped.
|
||||
# The most likely cause is the input of a non num type into
|
||||
# the amount field
|
||||
|
||||
print 'Incorrect value entered.'
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>Money Error</title>\n</head><body>Please check the Amount field. Transaction could not be completed.</BODY>\n</HTML>')
|
||||
return
|
||||
|
||||
try:
|
||||
av = simbase.air.doId2do[av]
|
||||
except KeyError:
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>Money Error</title>\n</head><body>Please check the AvatarID field; the Avatar might have logged out. Transaction could not be completed.</BODY>\n</HTML>')
|
||||
return
|
||||
curGold = av.getInventory().getGoldInPocket()
|
||||
# print "Debug: Args being passed to AIMAgicWordTrade:\t%s" % av
|
||||
trade = AIMagicWordTrade(av, av.getDoId(), avatarId = av.getDoId())
|
||||
if count > curGold:
|
||||
trade.giveGoldInPocket(count - curGold)
|
||||
else:
|
||||
trade.takeGoldInPocket(curGold - count)
|
||||
trade.sendTrade()
|
||||
# I don't think I need to issue a tradeRejected or
|
||||
# tradeSucceesed call here.
|
||||
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>Money Modified</title>\n</head><body>Transaction complete.</BODY>\n</HTML>')
|
||||
return
|
||||
|
||||
elif theMagicWord == 'assignQuest':
|
||||
|
||||
avSelectWidget = self.genAvSelect()
|
||||
questSelectWidget = self.genQuestSelect()
|
||||
|
||||
# Present HTML menu with options
|
||||
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>AssignQuest</title>\n</head><body><form method="get" action="magicWord" name="magicWord">AvatarID: %s\nQuest to Assign: %s<br><INPUT TYPE=HIDDEN NAME="magicWord" value="QUEST_ADD"><button value="Submit" name="Submit"></button><br></form></body>\n</HTML>' % (avSelectWidget, questSelectWidget))
|
||||
|
||||
elif theMagicWord == 'QUEST_ADD':
|
||||
av = kw['avatarId']
|
||||
av = int(av)
|
||||
questId = kw['questId']
|
||||
# print 'Avatarid = %s\nQuestID = %s' % (av, questId)
|
||||
try:
|
||||
av = simbase.air.doId2do[av]
|
||||
except KeyError:
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>Money Error</title>\n</head><body>Please check the AvatarID field; the Avatar might have logged out. Transaction could not be completed.</BODY>\n</HTML>')
|
||||
return
|
||||
av.assignQuest(questId)
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>Quest Assigned</title>\n</head><body>The avatar with id: %s<BR>Has been assigned Quest: %s</body>\n</HTML>' % (kw['avatarId'], questId))
|
||||
return
|
||||
|
||||
else:
|
||||
# No word Matches
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>No Word Matches</title>\n</head><body>The Magic word provided does not exist or is not accessable via the web interface at this time.</body>\n</HTML>')
|
||||
return
|
||||
|
||||
def timeStamp(self):
|
||||
# Returns the local time in the following string format:
|
||||
# Month-Day-Year Hour:Minute:Seconds
|
||||
# Example: 09-17-2007 15:36:04
|
||||
return time.strftime("%m-%d-%Y %H:%M:%S", time.localtime())
|
||||
|
||||
def oMenu(self, replyTo, **kw):
|
||||
# Menu listing Magic words and Raw object list (all HTML links)
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>Menu Options</title>\n</head><body>Magic Words:<BR><UL><LI><A HREF="magicWord?magicWord=money" TARGET="oInst">Money</a><LI><A HREF="magicWord?magicWord=assignQuest" TARGET="oInst">AssignQuest</A>\n<LI><A HREF="magicWord?magicWord=aijobmgr" TARGET="oInst">AIjobMgr</A>\n<LI><A HREF="magicWord?magicWord=aitaskmgr" TARGET="oInst">AITaskMgr</a><LI><A HREF="magicWord?magicWord=aiobjectcount" TARGET="oInst">AIObjectCount</A>\n</UL><P><A HREF="oType" TARGET="oType">Raw Object List</a></body>\n</HTML>')
|
||||
return
|
||||
|
||||
def genAvSelect(self):
|
||||
# We will need to populate HTML FORM menus to make this work.
|
||||
# We will need to provide a list of Avatars on the AI
|
||||
# along with a field to allow an int value to be sent
|
||||
# First, we need to get a dict of DistributedPlayerPirateAI's
|
||||
|
||||
playerPirates = []
|
||||
objList = self.generateSortedIDList()
|
||||
objList.reverse()
|
||||
while objList:
|
||||
tempObjElement = objList.pop()
|
||||
if str(tempObjElement[0]).find('DistributedPlayerPirateAI') != -1:
|
||||
playerPirates.append(tempObjElement[1])
|
||||
|
||||
# OK, now playerPirates should be a list of avatar ids
|
||||
# We should build a HTML select widget with the new list
|
||||
selectWidget = '<select name="avatarId">\n'
|
||||
while playerPirates:
|
||||
selectWidget = '%s<option>%s</option>\n' % (selectWidget, str(playerPirates.pop()))
|
||||
selectWidget = '%s</select><br>\n' % selectWidget
|
||||
return selectWidget
|
||||
|
||||
def genQuestSelect(self):
|
||||
# Will generate an HTML select widget, with the Key vals from the QuestDB
|
||||
selectWidget = '<select name="questId">\n'
|
||||
for k, v in QuestDict.iteritems():
|
||||
selectWidget = '%s<option>%s</option>\n' % (selectWidget, k)
|
||||
selectWidget = '%s</select><br>\n' % selectWidget
|
||||
return selectWidget
|
||||
|
||||
def blank(self, replyTo, **kw):
|
||||
# This simple generates a blank page for the middle and right
|
||||
# frames;( for when the page is first accessed)
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>Word not found</title>\n</head><body></body>\n</HTML>')
|
||||
|
||||
def oInst(self, replyTo, **kw):
|
||||
# This will populate the middle frame with list of the members of
|
||||
# the object selected in the left frame
|
||||
|
||||
#print "%s|oInst Frame Accessed, Request ID %s" % (self.timeStamp(), str(kw))
|
||||
|
||||
head = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<title>member List</title>\n</head>\n<body>\n<UL>'
|
||||
foot = '</ul></body></HTML>'
|
||||
body = ''
|
||||
doIdRequested = ''
|
||||
for j, k in kw.iteritems():
|
||||
doIdRequested = int(k)
|
||||
#print j,k
|
||||
try:
|
||||
memberList = inspect.getmembers(simbase.air.doId2do[doIdRequested])
|
||||
except KeyError:
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<TITLE>OBJ Gone</title>\n</head><body>The object is no longer on the system</body>\n</HTML>')
|
||||
return
|
||||
memberList.sort()
|
||||
memberList.reverse()
|
||||
while memberList:
|
||||
tempMember = memberList.pop()
|
||||
if (type(tempMember[1]) == str or type(tempMember[1]) == int or type(tempMember[1]) == float or type(tempMember[1]) == dict):
|
||||
body = '%s<LI>%s\n' % (body, str(tempMember))
|
||||
replyTo.respond('%s%s%s' % (head,body,foot))
|
||||
|
||||
|
||||
def oType(self, replyTo, **kw):
|
||||
# This will populate the left frame with a alpha sorted list of
|
||||
# objects.
|
||||
|
||||
# print "%s|oType Frame Accessed" % self.timeStamp()
|
||||
head = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<title>Object List</title>\n</head>\n<body>\n<UL>'
|
||||
foot = '</ul></body></HTML>'
|
||||
objList = self.generateSortedIDList()
|
||||
# Need to sort objList by second col (the doid)
|
||||
objList = sorted(objList, key=itemgetter(1))
|
||||
objList.reverse()
|
||||
body = ''
|
||||
# Pop off the Null entry
|
||||
while objList:
|
||||
tempObjElement = objList.pop()
|
||||
# tempObjElement[0].replace('<','')
|
||||
# tempObjElement[0].replace('>','')
|
||||
# if str(tempObjElement[0]).find('render') == -1:
|
||||
body = '%s<LI><A HREF="oInst?id=%s" target="oInst">%s:%s</A>\n' % (body, tempObjElement[1], tempObjElement[1], str(tempObjElement[0]).replace('<','').replace('>',''))
|
||||
replyTo.respond('%s%s%s' % (head,body,foot))
|
||||
|
||||
def inspect(self, replyTo, **kw):
|
||||
# This is the index. Basically, it will generate the frames for the
|
||||
# other functions to populate: systemInfo, oType, oInst, oAttrib
|
||||
# Three frames on the bottom row
|
||||
# frameset = '<frameset rows="35\%,65\%">\n<frame src="systemInfo" name="systemInfo" frameborder=1>\n<frameset cols="25\%,25\%,50\%">\n<frame src="oType" name="oType" frameborder=1>\n<frame src="blank" name="oInst" frameborder=1>\n<frame src="blank" name="oAttrib" frameborder=1>\n</frameset>\n</frameset>\n</html>'
|
||||
# Two Frames on the bottom row
|
||||
frameset = '<frameset rows="35\%,65\%">\n<frame src="systemInfo" name="systemInfo" frameborder=1>\n<frameset cols="50\%,50\%">\n<frame src="oMenu" name="oType" frameborder=1>\n<frame src="blank" name="oInst" frameborder=1>\n</frameset>\n</frameset>\n</html>'
|
||||
#print "%s|Index Frame Accessed" % self.timeStamp()
|
||||
# print str(simbase.air.doid2do)
|
||||
replyTo.respond('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">\n<html lang="en">\n<head>\n<title>AI HTTP Interface: %s</title>\n</head>\n%s' % (self.localHostName, frameset))
|
||||
|
||||
def systemInfo(self, replyTo, **kw):
|
||||
# This is the contents of the top frame; i.e. system information
|
||||
|
||||
self.refresh()
|
||||
#print "%s|SystemInfo Frame Accessed" % self.timeStamp()
|
||||
replyTo.respond('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">\n<title>System Info</title>\n</head>\n<body>\n<center><table style="text-align: left; width: 443px; height: 128px;" border="1" cellpadding="2" cellspacing="2">\n<tbody>\n<tr>\n<td style="text-align: center;" colspan="4">Hostname: %s<br>\nOperating System: %s<br>\nCPU: %s</td>\n</tr>\n<tr>\n<td>Total RAM:</td>\n<td>%d</td>\n<td>Total VM</td>\n<td>%d</td>\n</tr>\n<tr>\n<td>Available RAM:</td>\n<td>%d</td>\n<td>Available VM</td>\n<td>%d</td>\n</tr>\n</tbody>\n</table></center>\n</body>\n</html>' % (self.localHostName, self.os, self.cpu, self.totalRAM, self.totalVM, self.availableRAM, self.availableVM))
|
||||
|
||||
def startCheckingIncomingHTTP(self):
|
||||
taskMgr.remove('pollHTTPTask')
|
||||
taskMgr.doMethodLater(0.3,self.pollHTTPTask,'pollHTTPTask')
|
||||
|
||||
def stopCheckingIncomingHTTP(self):
|
||||
taskMgr.remove('pollHTTPTask')
|
||||
|
||||
def pollHTTPTask(self,task):
|
||||
"""
|
||||
Task that polls the HTTP server for new requests.
|
||||
"""
|
||||
# print 'Polling...'
|
||||
self.web.poll()
|
||||
#taskMgr.doMethodLater(0.3,self.pollHTTPTask,'pollHTTPTask')
|
||||
return Task.again
|
||||
|
||||
def generateSortedIDList(self):
|
||||
# looks at the simbase.air.doID2do dict, and returns a list
|
||||
# sorted by alpha order.
|
||||
IDlist = []
|
||||
for key, val in simbase.air.doId2do.iteritems():
|
||||
IDlist.append([val,key])
|
||||
IDlist.sort()
|
||||
return IDlist
|
||||
|
||||
|
||||
def inspectObject(anObject):
|
||||
inspector = inspectorFor(anObject)
|
||||
# inspectorWindow = InspectorWindow(inspector)
|
||||
# inspectorWindow.open()
|
||||
# return inspectorWindow
|
||||
return inspector
|
||||
|
||||
### private
|
||||
|
||||
def inspectorFor(anObject):
|
||||
typeName = string.capitalize(type(anObject).__name__) + 'Type'
|
||||
if typeName in _InspectorMap:
|
||||
inspectorName = _InspectorMap[typeName]
|
||||
else:
|
||||
print "Can't find an inspector for " + typeName
|
||||
inspectorName = 'Inspector'
|
||||
inspector = globals()[inspectorName](anObject)
|
||||
return inspector
|
||||
|
||||
def initializeInspectorMap():
|
||||
global _InspectorMap
|
||||
notFinishedTypes = ['BufferType', 'EllipsisType', 'FrameType', 'TracebackType', 'XRangeType']
|
||||
|
||||
_InspectorMap = {
|
||||
'Builtin_function_or_methodType': 'FunctionInspector',
|
||||
'BuiltinFunctionType': 'FunctionInspector',
|
||||
'BuiltinMethodType': 'FunctionInspector',
|
||||
'ClassType': 'ClassInspector',
|
||||
'CodeType': 'CodeInspector',
|
||||
'ComplexType': 'Inspector',
|
||||
'DictionaryType': 'DictionaryInspector',
|
||||
'DictType': 'DictionaryInspector',
|
||||
'FileType': 'Inspector',
|
||||
'FloatType': 'Inspector',
|
||||
'FunctionType': 'FunctionInspector',
|
||||
'Instance methodType': 'InstanceMethodInspector',
|
||||
'InstanceType': 'InstanceInspector',
|
||||
'IntType': 'Inspector',
|
||||
'LambdaType': 'Inspector',
|
||||
'ListType': 'SequenceInspector',
|
||||
'LongType': 'Inspector',
|
||||
'MethodType': 'FunctionInspector',
|
||||
'ModuleType': 'ModuleInspector',
|
||||
'NoneType': 'Inspector',
|
||||
'SliceType': 'SliceInspector',
|
||||
'StringType': 'SequenceInspector',
|
||||
'TupleType': 'SequenceInspector',
|
||||
'TypeType': 'Inspector',
|
||||
'UnboundMethodType': 'FunctionInspector',
|
||||
'DistributedshipcannonaiType': 'ClassInspector'}
|
||||
|
||||
for each in notFinishedTypes:
|
||||
_InspectorMap[each] = 'Inspector'
|
||||
|
||||
class Inspector:
|
||||
def __init__(self, anObject):
|
||||
self.object = anObject
|
||||
self.lastPartNumber = 0
|
||||
self.initializePartsList()
|
||||
self.initializePartNames()
|
||||
|
||||
def __str__(self):
|
||||
return __name__ + '(' + str(self.object) + ')'
|
||||
|
||||
def initializePartsList(self):
|
||||
self._partsList = []
|
||||
keys = self.namedParts()
|
||||
keys.sort()
|
||||
for each in keys:
|
||||
self._partsList.append(each)
|
||||
#if not callable(getattr(self.object, each)):
|
||||
# self._partsList.append(each)
|
||||
|
||||
def initializePartNames(self):
|
||||
self._partNames = ['up'] + [str(each) for each in self._partsList]
|
||||
|
||||
def title(self):
|
||||
"Subclasses may override."
|
||||
return string.capitalize(self.objectType().__name__)
|
||||
|
||||
def getLastPartNumber(self):
|
||||
return self.lastPartNumber
|
||||
|
||||
def selectedPart(self):
|
||||
return self.partNumber(self.getLastPartNumber())
|
||||
|
||||
def namedParts(self):
|
||||
return dir(self.object)
|
||||
|
||||
def stringForPartNumber(self, partNumber):
|
||||
object = self.partNumber(partNumber)
|
||||
doc = None
|
||||
if callable(object):
|
||||
try:
|
||||
doc = object.__doc__
|
||||
except:
|
||||
pass
|
||||
if doc:
|
||||
return (str(object) + '\n' + str(doc))
|
||||
else:
|
||||
return str(object)
|
||||
|
||||
def partNumber(self, partNumber):
|
||||
self.lastPartNumber = partNumber
|
||||
if partNumber == 0:
|
||||
return self.object
|
||||
else:
|
||||
part = self.privatePartNumber(partNumber)
|
||||
return getattr(self.object, part)
|
||||
|
||||
def inspectorFor(self, part):
|
||||
return inspectorFor(part)
|
||||
|
||||
def privatePartNumber(self, partNumber):
|
||||
return self._partsList[partNumber - 1]
|
||||
|
||||
def partNames(self):
|
||||
return self._partNames
|
||||
|
||||
def objectType(self):
|
||||
return type(self.object)
|
||||
|
||||
###
|
||||
|
||||
class ModuleInspector(Inspector):
|
||||
def namedParts(self):
|
||||
return ['__dict__']
|
||||
|
||||
class ClassInspector(Inspector):
|
||||
def namedParts(self):
|
||||
return ['__bases__'] + self.object.__dict__.keys()
|
||||
|
||||
def title(self):
|
||||
return self.object.__name__ + ' Class'
|
||||
|
||||
class InstanceInspector(Inspector):
|
||||
def title(self):
|
||||
return self.object.__class__.__name__
|
||||
def namedParts(self):
|
||||
return ['__class__'] + dir(self.object)
|
||||
|
||||
###
|
||||
|
||||
class FunctionInspector(Inspector):
|
||||
def title(self):
|
||||
return self.object.__name__ + "()"
|
||||
|
||||
class InstanceMethodInspector(Inspector):
|
||||
def title(self):
|
||||
return str(self.object.im_class) + "." + self.object.__name__ + "()"
|
||||
|
||||
class CodeInspector(Inspector):
|
||||
def title(self):
|
||||
return str(self.object)
|
||||
|
||||
###
|
||||
|
||||
class ComplexInspector(Inspector):
|
||||
def namedParts(self):
|
||||
return ['real', 'imag']
|
||||
|
||||
###
|
||||
|
||||
class DictionaryInspector(Inspector):
|
||||
|
||||
def initializePartsList(self):
|
||||
Inspector.initializePartsList(self)
|
||||
keys = self.object.keys()
|
||||
keys.sort()
|
||||
for each in keys:
|
||||
self._partsList.append(each)
|
||||
|
||||
def partNumber(self, partNumber):
|
||||
self.lastPartNumber = partNumber
|
||||
if partNumber == 0:
|
||||
return self.object
|
||||
key = self.privatePartNumber(partNumber)
|
||||
if key in self.object:
|
||||
return self.object[key]
|
||||
else:
|
||||
return getattr(self.object, key)
|
||||
|
||||
class SequenceInspector(Inspector):
|
||||
def initializePartsList(self):
|
||||
Inspector.initializePartsList(self)
|
||||
for each in range(len(self.object)):
|
||||
self._partsList.append(each)
|
||||
|
||||
def partNumber(self, partNumber):
|
||||
self.lastPartNumber = partNumber
|
||||
if partNumber == 0:
|
||||
return self.object
|
||||
index = self.privatePartNumber(partNumber)
|
||||
if type(index) == IntType:
|
||||
return self.object[index]
|
||||
else:
|
||||
return getattr(self.object, index)
|
||||
|
||||
class SliceInspector(Inspector):
|
||||
def namedParts(self):
|
||||
return ['start', 'stop', 'step']
|
||||
|
||||
### Initialization
|
||||
initializeInspectorMap()
|
||||
|
|
@ -1,275 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
import sys
|
||||
import os
|
||||
import ctypes
|
||||
import _winreg
|
||||
|
||||
"""Class to extract system information from a MS-Windows Box:
|
||||
|
||||
Instructions for Using:
|
||||
|
||||
Instance the class WindowsSystemInformation
|
||||
Then in the instance, access the following variables:
|
||||
|
||||
os
|
||||
cpu
|
||||
totalRAM
|
||||
totalVM
|
||||
availableVM
|
||||
availableRAM
|
||||
|
||||
Example:
|
||||
|
||||
s = SystemInformation()
|
||||
print s.os
|
||||
|
||||
s.refresh() # if you need to refresh the dynamic data (i.e. Memory stats, etc)
|
||||
"""
|
||||
|
||||
def get_registry_value(key, subkey, value):
|
||||
if sys.platform != 'win32':
|
||||
raise OSError("get_registry_value is only supported on Windows")
|
||||
|
||||
key = getattr(_winreg, key)
|
||||
handle = _winreg.OpenKey(key, subkey)
|
||||
(value, type) = _winreg.QueryValueEx(handle, value)
|
||||
return value
|
||||
|
||||
c_ulong = ctypes.c_ulong
|
||||
|
||||
class MEMORYSTATUS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('dwLength', c_ulong),
|
||||
('dwMemoryLoad', c_ulong),
|
||||
('dwTotalPhys', c_ulong),
|
||||
('dwAvailPhys', c_ulong),
|
||||
('dwTotalPageFile', c_ulong),
|
||||
('dwAvailPageFile', c_ulong),
|
||||
('dwTotalVirtual', c_ulong),
|
||||
('dwAvailVirtual', c_ulong)
|
||||
]
|
||||
|
||||
class SystemInformation:
|
||||
def __init__(self):
|
||||
|
||||
# Just in in case somebody called this class by accident, we should
|
||||
# check to make sure the OS is MS-Windows before continuing.
|
||||
|
||||
assert sys.platform == 'win32', "Not an MS-Windows Computer. This class should not be called"
|
||||
|
||||
# os contains the Operating System Name with Service Pack and Build
|
||||
# Example: Microsoft Windows XP Service Pack 2 (build 2600)
|
||||
|
||||
self.os = self._os_version().strip()
|
||||
|
||||
# cpu contains the CPU model and speed
|
||||
# Example: Intel Core(TM)2 CPU 6700 @ 2.66GHz
|
||||
|
||||
self.cpu = self._cpu().strip()
|
||||
|
||||
self.totalRAM, self.availableRAM, self.totalPF, self.availablePF, self.memoryLoad, self.totalVM, self.availableVM = self._ram()
|
||||
|
||||
# totalRam contains the total amount of RAM in the system
|
||||
|
||||
self.totalRAM = self.totalRAM / 1024
|
||||
|
||||
# totalVM contains the total amount of VM available to the system
|
||||
|
||||
self.totalVM = self.totalVM / 1024
|
||||
|
||||
# availableVM contains the amount of VM that is free
|
||||
|
||||
self.availableVM = self.availableVM / 1024
|
||||
|
||||
# availableRam: Ammount of available RAM in the system
|
||||
|
||||
self.availableRAM = self.availableRAM / 1024
|
||||
|
||||
def refresh(self):
|
||||
self.totalRAM, self.availableRAM, self.totalPF, self.availablePF, self.memoryLoad, self.totalVM, self.availableVM = self._ram()
|
||||
self.totalRAM = self.totalRAM / 1024
|
||||
self.totalVM = self.totalVM / 1024
|
||||
self.availableVM = self.availableVM / 1024
|
||||
self.availableRAM = self.availableRAM / 1024
|
||||
|
||||
def _os_version(self):
|
||||
def get(key):
|
||||
return get_registry_value(
|
||||
"HKEY_LOCAL_MACHINE",
|
||||
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
|
||||
key)
|
||||
os = get("ProductName")
|
||||
sp = get("CSDVersion")
|
||||
build = get("CurrentBuildNumber")
|
||||
return "%s %s (build %s)" % (os, sp, build)
|
||||
|
||||
def _cpu(self):
|
||||
return get_registry_value(
|
||||
"HKEY_LOCAL_MACHINE",
|
||||
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
|
||||
"ProcessorNameString")
|
||||
|
||||
def _ram(self):
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
|
||||
|
||||
memoryStatus = MEMORYSTATUS()
|
||||
memoryStatus.dwLength = ctypes.sizeof(MEMORYSTATUS)
|
||||
kernel32.GlobalMemoryStatus(ctypes.byref(memoryStatus))
|
||||
return (memoryStatus.dwTotalPhys, memoryStatus.dwAvailPhys, memoryStatus.dwTotalPageFile, memoryStatus.dwAvailPageFile, memoryStatus.dwMemoryLoad, memoryStatus.dwTotalVirtual, memoryStatus.dwAvailVirtual)
|
||||
|
||||
# To test, execute the script standalone.
|
||||
|
||||
if __name__ == "__main__":
|
||||
s = SystemInformation()
|
||||
print s.os
|
||||
print s.cpu
|
||||
print "RAM : %dKb total" % s.totalRAM
|
||||
print "RAM : %dKb free" % s.availableRAM
|
||||
print "Total VM: %dKb" % s.totalVM
|
||||
print "Available VM: %dKb" % s.availableVM
|
||||
|
|
@ -5637,26 +5637,6 @@
|
|||
<File RelativePath="..\direct\src\plugin\p3dOsxSplashWindow.I"></File>
|
||||
<File RelativePath="..\direct\src\plugin\p3dWinSplashWindow.cxx"></File>
|
||||
</Filter>
|
||||
<Filter Name="http">
|
||||
<File RelativePath="..\direct\src\http\application_log.h"></File>
|
||||
<File RelativePath="..\direct\src\http\baseincomingset.i"></File>
|
||||
<File RelativePath="..\direct\src\http\strtargetbuffer.h"></File>
|
||||
<File RelativePath="..\direct\src\http\parsedhttprequest.h"></File>
|
||||
<File RelativePath="..\direct\src\http\ringbuffer_slide.i"></File>
|
||||
<File RelativePath="..\direct\src\http\http_request.cxx"></File>
|
||||
<File RelativePath="..\direct\src\http\baseincomingset.h"></File>
|
||||
<File RelativePath="..\direct\src\http\http_bufferedreader.h"></File>
|
||||
<File RelativePath="..\direct\src\http\http_composite1.cxx"></File>
|
||||
<File RelativePath="..\direct\src\http\config_http.cxx"></File>
|
||||
<File RelativePath="..\direct\src\http\config_http.h"></File>
|
||||
<File RelativePath="..\direct\src\http\http_bufferedreader.i"></File>
|
||||
<File RelativePath="..\direct\src\http\ringbuffer_slide.h"></File>
|
||||
<File RelativePath="..\direct\src\http\bufferedwriter_growable.h"></File>
|
||||
<File RelativePath="..\direct\src\http\http_connection.cxx"></File>
|
||||
<File RelativePath="..\direct\src\http\http_connection.h"></File>
|
||||
<File RelativePath="..\direct\src\http\http_request.h"></File>
|
||||
<File RelativePath="..\direct\src\http\parsedhttprequest.cxx"></File>
|
||||
</Filter>
|
||||
<Filter Name="p3d">
|
||||
<File RelativePath="..\direct\src\p3d\p3dWrapper.c"></File>
|
||||
</Filter>
|
||||
|
|
|
|||
Loading…
Reference in New Issue