[gopher] Re: PyGS - a Python Gopher Server...
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
>
> Hi all,
> I've finally gotten PyGS, the Python Gopher Server that I've been
> tinkering with for some time to a point where it actually dishes stuff out
> semi-consistently.
Hey.
I also wrote a python gopher server (quite a while ago).
I haven't had time to mess with it, but it's yours to take a look at if you
like. If you think any of it is worth keeping (I hope so), then let's
talk about collaboration on a merged project?
-- Attached file included as plaintext by Listar --
-- File: Log.py
-- Desc: Log.py
import sys
LOG_FATAL = 0
LOG_ERROR = 1
LOG_WARN = 2
LOG_ALERT = 3
LOG_INFO = 4
LOG_DEBUG = 5
class Log:
def __init__(self, logfile=sys.stderr, loglevel=LOG_INFO):
self.logfile = logfile
self.loglevel = loglevel
def log (self, msg, level=LOG_INFO):
"just prints its parameter"
if level == LOG_FATAL:
self.logfile.write("F:" + msg + "\n")
sys.exit(1)
elif level == LOG_ERROR:
self.logfile.write("E:" + msg + "\n")
elif level == LOG_WARN:
if level <= self.loglevel:
self.logfile.write("W:" + msg + "\n")
elif level == LOG_ALERT:
if level <= self.loglevel:
self.logfile.write("A:" + msg + "\n")
elif level == LOG_INFO:
if level <= self.loglevel:
self.logfile.write("I:" + msg + "\n")
elif level == LOG_DEBUG:
if level <= self.loglevel:
self.logfile.write("D:" + msg + "\n")
else:
self.logfile.write("?:" + msg + "\n")
-- Attached file included as plaintext by Listar --
-- File: gopherd.py
-- Desc: gopherd.py
#! /usr/bin/python
import SocketServer,os,re,string,signal,socket,sys,threading,os.path,time
from stat import *
from Log import *
log=None
VERSION="$Id$"
sighup_flag=0
sigterm_flag=0
myLock = threading.Lock()
DOCROOT=""
request_counter = 0
def dirsplit(base):
try:
files = os.listdir(base)
except OSError, details:
log("Unable to list directory (%s)" % base, LOG_ERROR)
return ([],[])
dirs = []
for f in files[:]:
if f[0] == '.':
continue
newfile = base + "/" + f
try:
if S_ISDIR(os.stat(newfile)[ST_MODE]):
dirs.append(f)
files.remove(f)
except:
files.remove(f)
return(files, dirs)
def alarm_handler(a,b):
log("client timed out", LOG_ALERT)
def hup_handler(a,b):
global sighup_flag
log('caught sighup...', LOG_ALERT)
sighup_flag = 1
def term_handler(a,b):
global sigterm_flag
log('caught sigterm...', LOG_ALERT)
sigterm_flag = 1
class myHandler(SocketServer.StreamRequestHandler):
protocol = """
{File/Directory=0/1}{User Display String}\t{selector
string}\t{host}\t{port}crlf
0 Item is a file
1 Item is a directory
2 Item is a CSO phone-book server
3 Error
4 Item is a BinHexed Macintosh file.
5 Item is DOS binary archive of some sort.
Client must read until the TCP connection closes. Beware.
6 Item is a UNIX uuencoded file.
7 Item is an Index-Search server.
8 Item points to a text-based telnet session.
9 Item is a binary file!
Client must read until the TCP connection closes. Beware.
+ Item is a redundant server
T Item points to a text-based tn3270 session.
g Item is a GIF format graphics file.
h HTML, HyperText Markup Language
I Item is some kind of image file. Client decides how to display.
"""
notes = """
for files:
Note: Lines beginning with periods must be prepended with an extra
period to ensure that the transmission is not terminated early.
The client should strip extra periods at the beginning of the line.
"""
def getFile(self, path):
# print "File: %s" % path
try:
f = open(self.docroot + path, 'rb')
lines = f.readlines()
f.close()
return string.join(lines)
except IOError:
return "There was an error!"
def fileType(self, path):
root, ext = os.path.splitext(path)
type = '9'
if ext == '.jpg' or ext == '.jpeg':
type = 'I'
elif ext == '.gif':
type = 'g'
elif ext == '.html' or ext == '.htm':
type = 'h'
elif ext == '.txt' or ext == '.text':
type = '0'
return type
def getDirectory(self, path):
# print "Dir: %s" % path
files, dirs = dirsplit(self.docroot + path)
response = ""
for i in files:
response = response + "%c%s\t%s/%s\t%s\t%d\r\n" % (self.fileType(i), i,
path, i, self.host, self.port)
for i in dirs:
response = response + "1%s\t%s/%s/\t%s\t%d\r\n" % (i, path, i, self.host,
self.port)
return response
def start(self, blah):
return self.getDirectory("")
pass
def respond(self, response):
# make response pretty (ie, lines that start w/periods, etc....)
response = response + ".\r\n"
try:
self.wfile.write(response)
log("[%d] Wrote %d bytes." % (self.counter, len(response)), LOG_INFO)
except socket.error, details:
log("[%d] Socket error %s writing to client ." % (self.counter,
str(details)), LOG_ALERT)
# print response
return
def handle_error(request, client_address):
request.close()
SocketServer.BaseRequestHandler.handle_error(request, client_address)
def handle(self):
global request_counter, myLock, DOCROOT
myLock.acquire()
request_counter = request_counter + 1
self.counter = request_counter
myLock.release()
self.docroot = DOCROOT
self.host, self.port = self.connection.getsockname()
peerhost, peerport = self.client_address
log("[%d] Handling request from %s:%d" % (self.counter, peerhost,
peerport), LOG_INFO)
signal.alarm(15)
try:
data = self.rfile.readline()
signal.alarm(0)
except socket.error:
log("[%d] Socket error receiving from client." % self.counter, LOG_ALERT)
return
if not data:
log("[%d] No response from client." % self.counter, LOG_ALERT)
self.respond('400 ERR no data recieved.\n')
return
if string.find(data, '..') != -1:
log("[%d] Illegal Request." % (self.counter), LOG_ALERT)
self.respond('400 ERR Illegal request.\n')
return
# log("[%d] Attempting to match request: '%s'" % (self.counter, data),
LOG_INFO)
START_RE = re.compile(r'^(\B|/)\r\n$')
FILE_RE = re.compile(r'^(.+)\r\n$')
DIR_RE = re.compile(r'^(.+)/\r\n$')
mycommands = [ (START_RE, self.start, {}), \
(DIR_RE, self.getDirectory, {}),\
(FILE_RE, self.getFile, {})\
]
for c in mycommands:
myre, myfunc, myargs = c
m = myre.match(data)
if m:
self.file = m.group(1)
log('[%d] Matched request for "%s"' % (self.counter, self.file),
LOG_INFO)
response = apply(myfunc, m.groups(), myargs)
if response:
self.respond(response)
return
log("[%d] Unable to match request. (\"%s\")" % (self.counter, data),
LOG_ALERT)
self.respond('400 ERR Unable to match request.\n')
return
class MyServer(SocketServer.TCPServer):
pass
def main():
global log
global sighup_flag
global sigterm_flag
global VERSION
global DOCROOT
# LOGFILE='mylog'
# myLog = Log(open(LOGFILE, "a+", 0), LOG_INFO)
myLog = Log(sys.stderr, LOG_INFO)
log = myLog.log
if len(sys.argv) != 2:
log("Insufficient parameters.", LOG_FATAL)
host = "" # bind to all addresses
s = MyServer( (host, 1170 ), myHandler)
signal.signal(signal.SIGALRM,alarm_handler)
signal.signal(signal.SIGHUP,hup_handler)
signal.signal(signal.SIGTERM,term_handler)
sighup_flag = 1
DOCROOT=sys.argv[1]
if DOCROOT[-1:] != "/":
DOCROOT = DOCROOT + "/"
log("Setting DOCROOT to %s" % DOCROOT, LOG_ALERT)
log("Starting pygopherd server version %s." % VERSION, LOG_ALERT)
# child = not os.fork()
child = 1
if child:
while 1:
try:
if sighup_flag:
sighup_flag=0
# do something here
if sigterm_flag:
raise KeyboardInterrupt
s.handle_request()
except KeyboardInterrupt:
s.socket.close()
del s
try:
log("Shutting down.", LOG_ALERT)
except:
pass
sys.exit(0)
except socket.error, details:
if details[0] == 4: # interrupted system call
continue
else:
del s
log("socket received an error: %s" % str(details), LOG_ERROR)
sys.exit(1)
except:
del s
log("aiieee! unknown error! closing socket first.", LOG_ERROR)
raise
sys.exit(0) # never gets here
if __name__ == "__main__":
main()
-- Attached file included as plaintext by Listar --
Pound for pound, the amoeba is the most vicious animal on earth.
Jon Nelson
jnelson@xxxxxxx
- [gopher] PyGS - a Python Gopher Server..., Adam Gurno, 2001/07/09
- [gopher] Re: PyGS - a Python Gopher Server..., Cameron Kaiser, 2001/07/09
- [gopher] Re: PyGS - a Python Gopher Server..., Adam Gurno, 2001/07/09
- [gopher] Re: PyGS - a Python Gopher Server..., Cameron Kaiser, 2001/07/09
- [gopher] Re: PyGS - a Python Gopher Server..., Adam Gurno, 2001/07/09
- [gopher] Re: PyGS - a Python Gopher Server..., David Allen, 2001/07/09
- [gopher] Re: PyGS - a Python Gopher Server..., David Allen, 2001/07/09
- Message not available
- [gopher] Re: PyGS - a Python Gopher Server..., David Allen, 2001/07/09
- [gopher] Re: PyGS - a Python Gopher Server..., Cameron Kaiser, 2001/07/09
[gopher] Re: PyGS - a Python Gopher Server..., em@nuel, 2001/07/09
[gopher] Re: PyGS - a Python Gopher Server...,
Jon Nelson <=
|
|