[Zope-Checkins] CVS: Zope3/lib/python/Zope/Server/LineReceiver - LineCommandParser.py:1.2 LineServerChannel.py:1.2 LineTask.py:1.2 __init__.py:1.2
Jim Fulton
jim@zope.com
Mon, 10 Jun 2002 19:30:07 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/Server/LineReceiver
In directory cvs.zope.org:/tmp/cvs-serv20468/lib/python/Zope/Server/LineReceiver
Added Files:
LineCommandParser.py LineServerChannel.py LineTask.py
__init__.py
Log Message:
Merged Zope-3x-branch into newly forked Zope3 CVS Tree.
=== Zope3/lib/python/Zope/Server/LineReceiver/LineCommandParser.py 1.1 => 1.2 ===
+#
+# 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$
+"""
+
+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]
=== Zope3/lib/python/Zope/Server/LineReceiver/LineServerChannel.py 1.1 => 1.2 ===
+#
+# 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$
+"""
+
+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()
=== Zope3/lib/python/Zope/Server/LineReceiver/LineTask.py 1.1 => 1.2 ===
+#
+# 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$
+"""
+
+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)
=== Zope3/lib/python/Zope/Server/LineReceiver/__init__.py 1.1 => 1.2 ===
+#
+# 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$
+"""