[Zope-Checkins] CVS: Zope3/lib/python/Zope/Server/LineReceiver - LineCommandParser.py:1.1.4.1 LineServerChannel.py:1.1.4.1 LineTask.py:1.1.4.1 __init__.py:1.1.4.1
Shane Hathaway
shane@cvs.zope.org
Fri, 12 Apr 2002 17:30:58 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/Server/LineReceiver
In directory cvs.zope.org:/tmp/cvs-serv20835/lib/python/Zope/Server/LineReceiver
Added Files:
Tag: Zope-3x-branch
LineCommandParser.py LineServerChannel.py LineTask.py
__init__.py
Log Message:
Merged Zope3-Server-Branch.
=== Added File Zope3/lib/python/Zope/Server/LineReceiver/LineCommandParser.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
$Id: LineCommandParser.py,v 1.1.4.1 2002/04/12 21:30:57 shane Exp $
"""
from Zope.Server.IStreamConsumer import IStreamConsumer
class LineCommandParser:
"""Line Command parser. Arguments are left alone for now."""
__implements__ = IStreamConsumer
# See Zope.Server.IStreamConsumer.IStreamConsumer
completed = 0
inbuf = ''
cmd = ''
args = ''
empty = 0
max_line_length = 1024 # Not a hard limit
def __init__(self, adj):
"""
adj is an Adjustments object.
"""
self.adj = adj
############################################################
# Implementation methods for interface
# Zope.Server.IStreamConsumer
def received(self, data):
'See Zope.Server.IStreamConsumer.IStreamConsumer'
if self.completed:
return 0 # Can't consume any more.
pos = data.find('\n')
datalen = len(data)
if pos < 0:
self.inbuf = self.inbuf + data
if len(self.inbuf) > self.max_line_length:
# Don't accept any more.
self.completed = 1
return datalen
else:
# Line finished.
s = data[:pos + 1]
self.inbuf = self.inbuf + s
self.completed = 1
line = self.inbuf.strip()
self.parseLine(line)
return len(s)
#
############################################################
def parseLine(self, line):
parts = line.split(' ', 1)
if len(parts) == 2:
self.cmd, self.args = parts
else:
self.cmd = parts[0]
=== Added File Zope3/lib/python/Zope/Server/LineReceiver/LineServerChannel.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
$Id: LineServerChannel.py,v 1.1.4.1 2002/04/12 21:30:57 shane Exp $
"""
import os
import stat
import socket
import sys
import time
from Zope.Server.ServerChannelBase import ServerChannelBase
from LineCommandParser import LineCommandParser
from LineTask import LineTask
DEBUG = os.environ.get('ZOPE_SERVER_DEBUG')
class LineServerChannel(ServerChannelBase):
"""The Line Server Channel represents a connection to a particular
client. We can therefore store information here."""
__implements__ = ServerChannelBase.__implements__
# Wrapper class that is used to execute a command in a different thread
task_class = LineTask
# Class that is being initialized to parse the input
parser_class = LineCommandParser
# List of commands that are always available
special_commands = ('cmd_quit')
# Commands that are run in a separate thread
thread_commands = ()
# Define the authentication status of the channel. Note that only the
# "special commands" can be executed without having authenticated.
authenticated = 0
# Define the reply code for non-authenticated responses
not_auth_reply = 'LOGIN_REQUIRED'
# Define the reply code for an unrecognized command
unknown_reply = 'CMD_UNKNOWN'
# Define the error message that occurs, when the reply code was not found.
reply_error = '500 Unknown Reply Code: %s.'
# Define the status messages
status_messages = {
'CMD_UNKNOWN' : "500 '%s': command not understood.",
'INTERNAL_ERROR' : "500 Internal error: %s",
'LOGIN_REQUIRED' : '530 Please log in with USER and PASS',
}
def process_request(self, command):
"""Processes a command.
Some commands use an alternate thread.
"""
assert isinstance(command, LineCommandParser)
cmd = command.cmd
method = 'cmd_' + cmd.lower()
if ( not self.authenticated and method not in self.special_commands):
# The user is not logged in, therefore don't allow anything
self.reply(self.not_auth_reply)
elif method in self.thread_commands:
# Process in another thread.
return self.task_class(self, command, method)
elif hasattr(self, method):
try:
getattr(self, method)(command.args)
except:
self.exception()
else:
self.reply(self.unknown_reply, cmd.upper())
return None
def reply(self, code, args=(), flush=1):
""" """
try:
msg = self.status_messages[code] %args
except:
msg = self.reply_error %code
self.write('%s\r\n' %msg)
if flush:
self.flush(0)
# XXX: Some logging should go on here.
def exception(self):
if DEBUG:
import traceback
traceback.print_exc()
t, v = sys.exc_info()[:2]
try:
info = '%s: %s' % (getattr(t, '__name__', t), v)
except:
info = str(t)
self.reply('INTERNAL_ERROR', info)
self.handle_error()
=== Added File Zope3/lib/python/Zope/Server/LineReceiver/LineTask.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
$Id: LineTask.py,v 1.1.4.1 2002/04/12 21:30:57 shane Exp $
"""
import socket
import time
from Zope.Server.ITask import ITask
class LineTask:
"""This is a generic task that can be used with command line
protocols to handle commands in a separate thread.
"""
__implements__ = ITask
def __init__(self, channel, command, m_name):
self.channel = channel
self.m_name = m_name
self.args = command.args
self.close_on_finish = 0
############################################################
# Implementation methods for interface
# Zope.Server.ITask
def service(self):
"""Called to execute the task.
"""
try:
try:
self.start()
getattr(self.channel, self.m_name)(self.args)
self.finish()
except socket.error:
self.close_on_finish = 1
if self.channel.adj.log_socket_errors:
raise
except:
self.channel.exception()
finally:
self.channel.end_task(self.close_on_finish)
def cancel(self):
'See Zope.Server.ITask.ITask'
self.channel.close_when_done()
def defer(self):
'See Zope.Server.ITask.ITask'
pass
#
############################################################
def start(self):
now = time.time()
self.start_time = now
def finish(self):
hit_log = self.channel.server.hit_log
if hit_log is not None:
hit_log.log(self)
=== Added File Zope3/lib/python/Zope/Server/LineReceiver/__init__.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
$Id: __init__.py,v 1.1.4.1 2002/04/12 21:30:57 shane Exp $
"""