Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
Zope
Commits
b9e5da32
Commit
b9e5da32
authored
May 01, 2001
by
Andreas Jung
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
we *hate* tabs - lets get rid of them
parent
91134442
Changes
102
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
102 changed files
with
16152 additions
and
16152 deletions
+16152
-16152
ZServer/medusa/asynchat.py
ZServer/medusa/asynchat.py
+236
-236
ZServer/medusa/auth_handler.py
ZServer/medusa/auth_handler.py
+104
-104
ZServer/medusa/chat_server.py
ZServer/medusa/chat_server.py
+128
-128
ZServer/medusa/continuation.py
ZServer/medusa/continuation.py
+21
-21
ZServer/medusa/contrib/bobo_handler.py
ZServer/medusa/contrib/bobo_handler.py
+208
-208
ZServer/medusa/contrib/sample_cgi.py
ZServer/medusa/contrib/sample_cgi.py
+14
-14
ZServer/medusa/counter.py
ZServer/medusa/counter.py
+32
-32
ZServer/medusa/default_handler.py
ZServer/medusa/default_handler.py
+165
-165
ZServer/medusa/event_loop.py
ZServer/medusa/event_loop.py
+68
-68
ZServer/medusa/fifo.py
ZServer/medusa/fifo.py
+192
-192
ZServer/medusa/filesys.py
ZServer/medusa/filesys.py
+425
-425
ZServer/medusa/ftp_server.py
ZServer/medusa/ftp_server.py
+1047
-1047
ZServer/medusa/http_bobo.py
ZServer/medusa/http_bobo.py
+67
-67
ZServer/medusa/http_date.py
ZServer/medusa/http_date.py
+83
-83
ZServer/medusa/http_server.py
ZServer/medusa/http_server.py
+731
-731
ZServer/medusa/logger.py
ZServer/medusa/logger.py
+214
-214
ZServer/medusa/m_syslog.py
ZServer/medusa/m_syslog.py
+71
-71
ZServer/medusa/misc/async_mysql.py
ZServer/medusa/misc/async_mysql.py
+467
-467
ZServer/medusa/misc/recorder.py
ZServer/medusa/misc/recorder.py
+53
-53
ZServer/medusa/misc/syncsock.py
ZServer/medusa/misc/syncsock.py
+34
-34
ZServer/medusa/monitor.py
ZServer/medusa/monitor.py
+319
-319
ZServer/medusa/monitor_client.py
ZServer/medusa/monitor_client.py
+106
-106
ZServer/medusa/monitor_client_win32.py
ZServer/medusa/monitor_client_win32.py
+35
-35
ZServer/medusa/producers.py
ZServer/medusa/producers.py
+302
-302
ZServer/medusa/put_handler.py
ZServer/medusa/put_handler.py
+95
-95
ZServer/medusa/redirecting_handler.py
ZServer/medusa/redirecting_handler.py
+33
-33
ZServer/medusa/resolver.py
ZServer/medusa/resolver.py
+375
-375
ZServer/medusa/rpc_client.py
ZServer/medusa/rpc_client.py
+257
-257
ZServer/medusa/rpc_server.py
ZServer/medusa/rpc_server.py
+256
-256
ZServer/medusa/script_handler.py
ZServer/medusa/script_handler.py
+174
-174
ZServer/medusa/script_handler_demo/form.mpy
ZServer/medusa/script_handler_demo/form.mpy
+4
-4
ZServer/medusa/script_handler_demo/persistent.py
ZServer/medusa/script_handler_demo/persistent.py
+13
-13
ZServer/medusa/script_handler_demo/today.mpy
ZServer/medusa/script_handler_demo/today.mpy
+10
-10
ZServer/medusa/sendfile/asynchat_sendfile.py
ZServer/medusa/sendfile/asynchat_sendfile.py
+45
-45
ZServer/medusa/sendfile/test_sendfile.py
ZServer/medusa/sendfile/test_sendfile.py
+67
-67
ZServer/medusa/start_medusa.py
ZServer/medusa/start_medusa.py
+49
-49
ZServer/medusa/status_handler.py
ZServer/medusa/status_handler.py
+249
-249
ZServer/medusa/test/asyn_http_bench.py
ZServer/medusa/test/asyn_http_bench.py
+78
-78
ZServer/medusa/test/max_sockets.py
ZServer/medusa/test/max_sockets.py
+52
-52
ZServer/medusa/test/test_11.py
ZServer/medusa/test/test_11.py
+93
-93
ZServer/medusa/test/test_lb.py
ZServer/medusa/test/test_lb.py
+132
-132
ZServer/medusa/test/test_medusa.py
ZServer/medusa/test/test_medusa.py
+33
-33
ZServer/medusa/test/test_single_11.py
ZServer/medusa/test/test_single_11.py
+41
-41
ZServer/medusa/thread/pi_module.py
ZServer/medusa/thread/pi_module.py
+42
-42
ZServer/medusa/thread/select_trigger.py
ZServer/medusa/thread/select_trigger.py
+247
-247
ZServer/medusa/thread/test_module.py
ZServer/medusa/thread/test_module.py
+7
-7
ZServer/medusa/thread/thread_channel.py
ZServer/medusa/thread/thread_channel.py
+95
-95
ZServer/medusa/thread/thread_handler.py
ZServer/medusa/thread/thread_handler.py
+320
-320
ZServer/medusa/unix_user_handler.py
ZServer/medusa/unix_user_handler.py
+57
-57
ZServer/medusa/virtual_handler.py
ZServer/medusa/virtual_handler.py
+46
-46
ZServer/medusa/xmlrpc_handler.py
ZServer/medusa/xmlrpc_handler.py
+84
-84
lib/python/ZServer/medusa/asynchat.py
lib/python/ZServer/medusa/asynchat.py
+236
-236
lib/python/ZServer/medusa/auth_handler.py
lib/python/ZServer/medusa/auth_handler.py
+104
-104
lib/python/ZServer/medusa/chat_server.py
lib/python/ZServer/medusa/chat_server.py
+128
-128
lib/python/ZServer/medusa/continuation.py
lib/python/ZServer/medusa/continuation.py
+21
-21
lib/python/ZServer/medusa/contrib/bobo_handler.py
lib/python/ZServer/medusa/contrib/bobo_handler.py
+208
-208
lib/python/ZServer/medusa/contrib/sample_cgi.py
lib/python/ZServer/medusa/contrib/sample_cgi.py
+14
-14
lib/python/ZServer/medusa/counter.py
lib/python/ZServer/medusa/counter.py
+32
-32
lib/python/ZServer/medusa/default_handler.py
lib/python/ZServer/medusa/default_handler.py
+165
-165
lib/python/ZServer/medusa/event_loop.py
lib/python/ZServer/medusa/event_loop.py
+68
-68
lib/python/ZServer/medusa/fifo.py
lib/python/ZServer/medusa/fifo.py
+192
-192
lib/python/ZServer/medusa/filesys.py
lib/python/ZServer/medusa/filesys.py
+425
-425
lib/python/ZServer/medusa/ftp_server.py
lib/python/ZServer/medusa/ftp_server.py
+1047
-1047
lib/python/ZServer/medusa/http_bobo.py
lib/python/ZServer/medusa/http_bobo.py
+67
-67
lib/python/ZServer/medusa/http_date.py
lib/python/ZServer/medusa/http_date.py
+83
-83
lib/python/ZServer/medusa/http_server.py
lib/python/ZServer/medusa/http_server.py
+731
-731
lib/python/ZServer/medusa/logger.py
lib/python/ZServer/medusa/logger.py
+214
-214
lib/python/ZServer/medusa/m_syslog.py
lib/python/ZServer/medusa/m_syslog.py
+71
-71
lib/python/ZServer/medusa/misc/async_mysql.py
lib/python/ZServer/medusa/misc/async_mysql.py
+467
-467
lib/python/ZServer/medusa/misc/recorder.py
lib/python/ZServer/medusa/misc/recorder.py
+53
-53
lib/python/ZServer/medusa/misc/syncsock.py
lib/python/ZServer/medusa/misc/syncsock.py
+34
-34
lib/python/ZServer/medusa/monitor.py
lib/python/ZServer/medusa/monitor.py
+319
-319
lib/python/ZServer/medusa/monitor_client.py
lib/python/ZServer/medusa/monitor_client.py
+106
-106
lib/python/ZServer/medusa/monitor_client_win32.py
lib/python/ZServer/medusa/monitor_client_win32.py
+35
-35
lib/python/ZServer/medusa/producers.py
lib/python/ZServer/medusa/producers.py
+302
-302
lib/python/ZServer/medusa/put_handler.py
lib/python/ZServer/medusa/put_handler.py
+95
-95
lib/python/ZServer/medusa/redirecting_handler.py
lib/python/ZServer/medusa/redirecting_handler.py
+33
-33
lib/python/ZServer/medusa/resolver.py
lib/python/ZServer/medusa/resolver.py
+375
-375
lib/python/ZServer/medusa/rpc_client.py
lib/python/ZServer/medusa/rpc_client.py
+257
-257
lib/python/ZServer/medusa/rpc_server.py
lib/python/ZServer/medusa/rpc_server.py
+256
-256
lib/python/ZServer/medusa/script_handler.py
lib/python/ZServer/medusa/script_handler.py
+174
-174
lib/python/ZServer/medusa/script_handler_demo/form.mpy
lib/python/ZServer/medusa/script_handler_demo/form.mpy
+4
-4
lib/python/ZServer/medusa/script_handler_demo/persistent.py
lib/python/ZServer/medusa/script_handler_demo/persistent.py
+13
-13
lib/python/ZServer/medusa/script_handler_demo/today.mpy
lib/python/ZServer/medusa/script_handler_demo/today.mpy
+10
-10
lib/python/ZServer/medusa/sendfile/asynchat_sendfile.py
lib/python/ZServer/medusa/sendfile/asynchat_sendfile.py
+45
-45
lib/python/ZServer/medusa/sendfile/test_sendfile.py
lib/python/ZServer/medusa/sendfile/test_sendfile.py
+67
-67
lib/python/ZServer/medusa/start_medusa.py
lib/python/ZServer/medusa/start_medusa.py
+49
-49
lib/python/ZServer/medusa/status_handler.py
lib/python/ZServer/medusa/status_handler.py
+249
-249
lib/python/ZServer/medusa/test/asyn_http_bench.py
lib/python/ZServer/medusa/test/asyn_http_bench.py
+78
-78
lib/python/ZServer/medusa/test/max_sockets.py
lib/python/ZServer/medusa/test/max_sockets.py
+52
-52
lib/python/ZServer/medusa/test/test_11.py
lib/python/ZServer/medusa/test/test_11.py
+93
-93
lib/python/ZServer/medusa/test/test_lb.py
lib/python/ZServer/medusa/test/test_lb.py
+132
-132
lib/python/ZServer/medusa/test/test_medusa.py
lib/python/ZServer/medusa/test/test_medusa.py
+33
-33
lib/python/ZServer/medusa/test/test_single_11.py
lib/python/ZServer/medusa/test/test_single_11.py
+41
-41
lib/python/ZServer/medusa/thread/pi_module.py
lib/python/ZServer/medusa/thread/pi_module.py
+42
-42
lib/python/ZServer/medusa/thread/select_trigger.py
lib/python/ZServer/medusa/thread/select_trigger.py
+247
-247
lib/python/ZServer/medusa/thread/test_module.py
lib/python/ZServer/medusa/thread/test_module.py
+7
-7
lib/python/ZServer/medusa/thread/thread_channel.py
lib/python/ZServer/medusa/thread/thread_channel.py
+95
-95
lib/python/ZServer/medusa/thread/thread_handler.py
lib/python/ZServer/medusa/thread/thread_handler.py
+320
-320
lib/python/ZServer/medusa/unix_user_handler.py
lib/python/ZServer/medusa/unix_user_handler.py
+57
-57
lib/python/ZServer/medusa/virtual_handler.py
lib/python/ZServer/medusa/virtual_handler.py
+46
-46
lib/python/ZServer/medusa/xmlrpc_handler.py
lib/python/ZServer/medusa/xmlrpc_handler.py
+84
-84
No files found.
ZServer/medusa/asynchat.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
# $Id: asynchat.py,v 1.1
6 2001/04/25 19:07:29
andreas Exp $
# $Id: asynchat.py,v 1.1
7 2001/05/01 11:44:48
andreas Exp $
# Author: Sam Rushing <rushing@nightmare.com>
# ======================================================================
...
...
@@ -270,20 +270,20 @@ class fifo:
else
:
return
(
0
,
None
)
# Given 'haystack', see if any prefix of 'needle' is at its end. This
# assumes an exact match has already been checked. Return the number of
# characters matched.
# for example:
# f_p_a_e ("qwerty\r", "\r\n") => 1
# f_p_a_e ("qwertydkjf", "\r\n") => 0
# f_p_a_e ("qwerty\r\n", "\r\n") => <undefined>
# this could maybe be made faster with a computed regex?
# [answer: no; circa Python-2.0, Jan 2001]
# new python: 28961/s
# old python: 18307/s
# re: 12820/s
# regex: 14035/s
# Given 'haystack', see if any prefix of 'needle' is at its end. This
# assumes an exact match has already been checked. Return the number of
# characters matched.
# for example:
# f_p_a_e ("qwerty\r", "\r\n") => 1
# f_p_a_e ("qwertydkjf", "\r\n") => 0
# f_p_a_e ("qwerty\r\n", "\r\n") => <undefined>
# this could maybe be made faster with a computed regex?
# [answer: no; circa Python-2.0, Jan 2001]
# new python: 28961/s
# old python: 18307/s
# re: 12820/s
# regex: 14035/s
def
find_prefix_at_end
(
haystack
,
needle
):
l
=
len
(
needle
)
-
1
...
...
ZServer/medusa/auth_handler.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: auth_handler.py,v 1.
2 2001/04/25 19:07:30
andreas Exp $'
RCS_ID
=
'$Id: auth_handler.py,v 1.
3 2001/05/01 11:44:48
andreas Exp $'
# support for 'basic' authenticaion.
...
...
ZServer/medusa/chat_server.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: chat_server.py,v 1.
2 2001/04/25 19:07:30
andreas Exp $'
RCS_ID
=
'$Id: chat_server.py,v 1.
3 2001/05/01 11:44:48
andreas Exp $'
import
string
...
...
ZServer/medusa/continuation.py
View file @
b9e5da32
ZServer/medusa/contrib/bobo_handler.py
View file @
b9e5da32
ZServer/medusa/contrib/sample_cgi.py
View file @
b9e5da32
ZServer/medusa/counter.py
View file @
b9e5da32
ZServer/medusa/default_handler.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: default_handler.py,v 1.
6 2001/04/25 19:07:30
andreas Exp $'
RCS_ID
=
'$Id: default_handler.py,v 1.
7 2001/05/01 11:44:48
andreas Exp $'
# standard python modules
import
os
...
...
@@ -190,9 +190,9 @@ class default_handler:
+
'</ul>'
)
# HTTP/1.0 doesn't say anything about the "; length=nnnn" addition
# to this header. I suppose it's purpose is to avoid the overhead
# of parsing dates...
# HTTP/1.0 doesn't say anything about the "; length=nnnn" addition
# to this header. I suppose it's purpose is to avoid the overhead
# of parsing dates...
IF_MODIFIED_SINCE
=
re
.
compile
(
'If-Modified-Since: ([^;]+)((; length=([0-9]+)$)|$)'
,
re
.
IGNORECASE
...
...
ZServer/medusa/event_loop.py
View file @
b9e5da32
ZServer/medusa/fifo.py
View file @
b9e5da32
ZServer/medusa/filesys.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
# $Id: filesys.py,v 1.
8 2001/04/27 18:25:42
andreas Exp $
# $Id: filesys.py,v 1.
9 2001/05/01 11:44:48
andreas Exp $
# Author: Sam Rushing <rushing@nightmare.com>
#
# Generic filesystem interface.
...
...
@@ -59,15 +59,15 @@ class abstract_filesystem:
[for the output of the LIST command]"""
pass
# standard wrapper around a unix-like filesystem, with a 'false root'
# capability.
# standard wrapper around a unix-like filesystem, with a 'false root'
# capability.
# security considerations: can symbolic links be used to 'escape' the
# root? should we allow it? if not, then we could scan the
# filesystem on startup, but that would not help if they were added
# later. We will probably need to check for symlinks in the cwd method.
# security considerations: can symbolic links be used to 'escape' the
# root? should we allow it? if not, then we could scan the
# filesystem on startup, but that would not help if they were added
# later. We will probably need to check for symlinks in the cwd method.
# what to do if wd is an invalid directory?
# what to do if wd is an invalid directory?
import
os
,
re
import
stat
...
...
@@ -251,88 +251,88 @@ if os.name == 'posix':
finally
:
self
.
become_nobody
()
# This hasn't been very reliable across different platforms.
# maybe think about a separate 'directory server'.
#
# import posixpath
# import fcntl
# import FCNTL
# import select
# import asyncore
#
# # pipes /bin/ls for directory listings.
# class unix_filesystem (os_filesystem):
# pass
# path_module = posixpath
#
# def listdir (self, path, long=0):
# p = self.translate (path)
# if not long:
# return list_producer (os.listdir (p), 0, None)
# else:
# command = '/bin/ls -l %s' % p
# print 'opening pipe to "%s"' % command
# fd = os.popen (command, 'rt')
# return pipe_channel (fd)
#
# # this is both a dispatcher, _and_ a producer
# class pipe_channel (asyncore.file_dispatcher):
# buffer_size = 4096
#
# def __init__ (self, fd):
# asyncore.file_dispatcher.__init__ (self, fd)
# self.fd = fd
# self.done = 0
# self.data = ''
#
# def handle_read (self):
# if len (self.data) < self.buffer_size:
# self.data = self.data + self.fd.read (self.buffer_size)
# #print '%s.handle_read() => len(self.data) == %d' % (self, len(self.data))
#
# def handle_expt (self):
# #print '%s.handle_expt()' % self
# self.done = 1
#
# def ready (self):
# #print '%s.ready() => %d' % (self, len(self.data))
# return ((len (self.data) > 0) or self.done)
#
# def more (self):
# if self.data:
# r = self.data
# self.data = ''
# elif self.done:
# self.close()
# self.downstream.finished()
# r = ''
# else:
# r = None
# #print '%s.more() => %s' % (self, (r and len(r)))
# return r
# For the 'real' root, we could obtain a list of drives, and then
# use that. Doesn't win32 provide such a 'real' filesystem?
# [yes, I think something like this "\\.\c\windows"]
# This hasn't been very reliable across different platforms.
# maybe think about a separate 'directory server'.
#
# import posixpath
# import fcntl
# import FCNTL
# import select
# import asyncore
#
# # pipes /bin/ls for directory listings.
# class unix_filesystem (os_filesystem):
# pass
# path_module = posixpath
#
# def listdir (self, path, long=0):
# p = self.translate (path)
# if not long:
# return list_producer (os.listdir (p), 0, None)
# else:
# command = '/bin/ls -l %s' % p
# print 'opening pipe to "%s"' % command
# fd = os.popen (command, 'rt')
# return pipe_channel (fd)
#
# # this is both a dispatcher, _and_ a producer
# class pipe_channel (asyncore.file_dispatcher):
# buffer_size = 4096
#
# def __init__ (self, fd):
# asyncore.file_dispatcher.__init__ (self, fd)
# self.fd = fd
# self.done = 0
# self.data = ''
#
# def handle_read (self):
# if len (self.data) < self.buffer_size:
# self.data = self.data + self.fd.read (self.buffer_size)
# #print '%s.handle_read() => len(self.data) == %d' % (self, len(self.data))
#
# def handle_expt (self):
# #print '%s.handle_expt()' % self
# self.done = 1
#
# def ready (self):
# #print '%s.ready() => %d' % (self, len(self.data))
# return ((len (self.data) > 0) or self.done)
#
# def more (self):
# if self.data:
# r = self.data
# self.data = ''
# elif self.done:
# self.close()
# self.downstream.finished()
# r = ''
# else:
# r = None
# #print '%s.more() => %s' % (self, (r and len(r)))
# return r
# For the 'real' root, we could obtain a list of drives, and then
# use that. Doesn't win32 provide such a 'real' filesystem?
# [yes, I think something like this "\\.\c\windows"]
class
msdos_filesystem
(
os_filesystem
):
def
longify
(
self
,
(
path
,
stat_info
)):
return
msdos_longify
(
path
,
stat_info
)
# A merged filesystem will let you plug other filesystems together.
# We really need the equivalent of a 'mount' capability - this seems
# to be the most general idea. So you'd use a 'mount' method to place
# another filesystem somewhere in the hierarchy.
# A merged filesystem will let you plug other filesystems together.
# We really need the equivalent of a 'mount' capability - this seems
# to be the most general idea. So you'd use a 'mount' method to place
# another filesystem somewhere in the hierarchy.
# Note: this is most likely how I will handle ~user directories
# with the http server.
# Note: this is most likely how I will handle ~user directories
# with the http server.
class
merged_filesystem
:
def
__init__
(
self
,
*
fsys
):
pass
# this matches the output of NT's ftp server (when in
# MSDOS mode) exactly.
# this matches the output of NT's ftp server (when in
# MSDOS mode) exactly.
def
msdos_longify
(
file
,
stat_info
):
if
stat
.
S_ISDIR
(
stat_info
[
stat
.
ST_MODE
]):
...
...
@@ -403,12 +403,12 @@ def unix_longify (file, stat_info):
file
)
# Emulate the unix 'ls' command's date field.
# it has two formats - if the date is more than 180
# days in the past, then it's like this:
# Oct 19 1995
# otherwise, it looks like this:
# Oct 19 17:33
# Emulate the unix 'ls' command's date field.
# it has two formats - if the date is more than 180
# days in the past, then it's like this:
# Oct 19 1995
# otherwise, it looks like this:
# Oct 19 17:33
def
ls_date
(
now
,
t
):
try
:
...
...
@@ -430,9 +430,9 @@ def ls_date (now, t):
info
[
4
]
)
# ===========================================================================
# Producers
# ===========================================================================
# ===========================================================================
# Producers
# ===========================================================================
class
list_producer
:
def
__init__
(
self
,
file_list
,
long
,
longify
):
...
...
ZServer/medusa/ftp_server.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: ftp_server.py,v 1.1
6 2001/04/27 18:26:51
andreas Exp $'
RCS_ID
=
'$Id: ftp_server.py,v 1.1
7 2001/05/01 11:44:48
andreas Exp $'
# An extensible, configurable, asynchronous FTP server.
#
...
...
@@ -99,8 +99,8 @@ class ftp_channel (asynchat.async_chat):
)
)
# def __del__ (self):
# print 'ftp_channel.__del__()'
# def __del__ (self):
# print 'ftp_channel.__del__()'
# --------------------------------------------------
# async-library methods
...
...
@@ -633,15 +633,15 @@ class ftp_channel (asynchat.async_chat):
else
:
self
.
respond
(
'502 Unimplemented MODE type'
)
# The stat command has two personalities. Normally it returns status
# information about the current connection. But if given an argument,
# it is equivalent to the LIST command, with the data sent over the
# control connection. Strange. But wuftpd, ftpd, and nt's ftp server
# all support it.
#
## def cmd_stat (self, line):
## 'return status of server'
## pass
# The stat command has two personalities. Normally it returns status
# information about the current connection. But if given an argument,
# it is equivalent to the LIST command, with the data sent over the
# control connection. Strange. But wuftpd, ftpd, and nt's ftp server
# all support it.
#
## def cmd_stat (self, line):
## 'return status of server'
## pass
def
cmd_syst
(
self
,
line
):
'show operating system type of server system'
...
...
@@ -777,32 +777,32 @@ class ftp_server (asyncore.dispatcher):
]
)
# ======================================================================
# Data Channel Classes
# ======================================================================
# ======================================================================
# Data Channel Classes
# ======================================================================
# This socket accepts a data connection, used when the server has been
# placed in passive mode. Although the RFC implies that we ought to
# be able to use the same acceptor over and over again, this presents
# a problem: how do we shut it off, so that we are accepting
# connections only when we expect them? [we can't]
#
# wuftpd, and probably all the other servers, solve this by allowing
# only one connection to hit this acceptor. They then close it. Any
# subsequent data-connection command will then try for the default
# port on the client side [which is of course never there]. So the
# 'always-send-PORT/PASV' behavior seems required.
#
# Another note: wuftpd will also be listening on the channel as soon
# as the PASV command is sent. It does not wait for a data command
# first.
# This socket accepts a data connection, used when the server has been
# placed in passive mode. Although the RFC implies that we ought to
# be able to use the same acceptor over and over again, this presents
# a problem: how do we shut it off, so that we are accepting
# connections only when we expect them? [we can't]
#
# wuftpd, and probably all the other servers, solve this by allowing
# only one connection to hit this acceptor. They then close it. Any
# subsequent data-connection command will then try for the default
# port on the client side [which is of course never there]. So the
# 'always-send-PORT/PASV' behavior seems required.
#
# Another note: wuftpd will also be listening on the channel as soon
# as the PASV command is sent. It does not wait for a data command
# first.
# --- we need to queue up a particular behavior:
# 1) xmit : queue up producer[s]
# 2) recv : the file object
#
# It would be nice if we could make both channels the same. Hmmm..
#
# --- we need to queue up a particular behavior:
# 1) xmit : queue up producer[s]
# 2) recv : the file object
#
# It would be nice if we could make both channels the same. Hmmm..
#
class
passive_acceptor
(
asyncore
.
dispatcher
):
ready
=
None
...
...
@@ -821,8 +821,8 @@ class passive_acceptor (asyncore.dispatcher):
self
.
addr
=
self
.
getsockname
()
self
.
listen
(
1
)
# def __del__ (self):
# print 'passive_acceptor.__del__()'
# def __del__ (self):
# print 'passive_acceptor.__del__()'
def
log
(
self
,
*
ignore
):
pass
...
...
@@ -854,8 +854,8 @@ class xmit_channel (asynchat.async_chat):
self
.
client_addr
=
client_addr
asynchat
.
async_chat
.
__init__
(
self
)
# def __del__ (self):
# print 'xmit_channel.__del__()'
# def __del__ (self):
# print 'xmit_channel.__del__()'
def
log
(
*
args
):
pass
...
...
@@ -962,9 +962,9 @@ class anon_authorizer:
else
:
return
0
,
'Password invalid.'
,
None
# ===========================================================================
# Unix-specific improvements
# ===========================================================================
# ===========================================================================
# Unix-specific improvements
# ===========================================================================
if
os
.
name
==
'posix'
:
...
...
@@ -1046,9 +1046,9 @@ class file_producer:
self
.
done
=
1
return
block
# usage: ftp_server /PATH/TO/FTP/ROOT PORT
# for example:
# $ ftp_server /home/users/ftp 8021
# usage: ftp_server /PATH/TO/FTP/ROOT PORT
# for example:
# $ ftp_server /home/users/ftp 8021
if
os
.
name
==
'posix'
:
def
test
(
port
=
'8021'
):
...
...
@@ -1067,17 +1067,17 @@ if os.name == 'posix':
if
__name__
==
'__main__'
:
test
(
sys
.
argv
[
1
])
# not unix
# not unix
else
:
def
test
():
fs
=
ftp_server
(
dummy_authorizer
())
if
__name__
==
'__main__'
:
test
()
# this is the command list from the wuftpd man page
# '*' means we've implemented it.
# '!' requires write access
#
# this is the command list from the wuftpd man page
# '*' means we've implemented it.
# '!' requires write access
#
command_documentation
=
{
'abor'
:
'abort previous command'
,
#*
'acct'
:
'specify account (ignored)'
,
...
...
ZServer/medusa/http_bobo.py
View file @
b9e5da32
...
...
@@ -3,7 +3,7 @@
import
string
import
regex
RCS_ID
=
'$Id: http_bobo.py,v 1.
3 2001/04/26 00:07:52
andreas Exp $'
RCS_ID
=
'$Id: http_bobo.py,v 1.
4 2001/05/01 11:44:48
andreas Exp $'
VERSION_STRING
=
string
.
split
(
RCS_ID
)[
2
]
class
bobo_extension
:
...
...
ZServer/medusa/http_date.py
View file @
b9e5da32
...
...
@@ -68,7 +68,7 @@ def unpack_rfc822 (m):
0
)
# rfc850 format
# rfc850 format
rfc850_date
=
join
(
[
concat
(
long_day_reg
,
','
),
join
(
...
...
@@ -101,8 +101,8 @@ def unpack_rfc850 (m):
0
)
# parsdate.parsedate - ~700/sec.
# parse_http_date - ~1333/sec.
# parsdate.parsedate - ~700/sec.
# parse_http_date - ~1333/sec.
def
build_http_date
(
when
):
return
time
.
strftime
(
'%a, %d %b %Y %H:%M:%S GMT'
,
time
.
gmtime
(
when
))
...
...
ZServer/medusa/http_server.py
View file @
b9e5da32
...
...
@@ -6,7 +6,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: http_server.py,v 1.2
3 2001/04/30 14:38:40
andreas Exp $'
RCS_ID
=
'$Id: http_server.py,v 1.2
4 2001/05/01 11:44:48
andreas Exp $'
# python modules
import
os
...
...
@@ -331,9 +331,9 @@ class http_request:
)
# ===========================================================================
# HTTP Channel Object
# ===========================================================================
# ===========================================================================
# HTTP Channel Object
# ===========================================================================
class
http_channel
(
asynchat
.
async_chat
):
...
...
@@ -523,9 +523,9 @@ class http_channel (asynchat.async_chat):
else
:
return
1
# ===========================================================================
# HTTP Server Object
# ===========================================================================
# ===========================================================================
# HTTP Server Object
# ===========================================================================
class
http_server
(
asyncore
.
dispatcher
):
...
...
@@ -748,7 +748,7 @@ def compute_timezone_for_log ():
else
:
return
'+%02d%02d'
%
(
h
,
m
)
# if you run this program over a TZ change boundary, this will be invalid.
# if you run this program over a TZ change boundary, this will be invalid.
tz_for_log
=
compute_timezone_for_log
()
if
__name__
==
'__main__'
:
...
...
ZServer/medusa/logger.py
View file @
b9e5da32
...
...
@@ -76,11 +76,11 @@ class file_logger:
else
:
self
.
write
(
message
)
# like a file_logger, but it must be attached to a filename.
# When the log gets too full, or a certain time has passed,
# it backs up the log and starts a new one. Note that backing
# up the log is done via "mv" because anything else (cp, gzip)
# would take time, during which medusa would do nothing else.
# like a file_logger, but it must be attached to a filename.
# When the log gets too full, or a certain time has passed,
# it backs up the log and starts a new one. Note that backing
# up the log is done via "mv" because anything else (cp, gzip)
# would take time, during which medusa would do nothing else.
class
rotating_file_logger
(
file_logger
):
...
...
@@ -142,14 +142,14 @@ class rotating_file_logger (file_logger):
except
:
pass
# syslog is a line-oriented log protocol - this class would be
# appropriate for FTP or HTTP logs, but not for dumping stderr to.
# syslog is a line-oriented log protocol - this class would be
# appropriate for FTP or HTTP logs, but not for dumping stderr to.
# TODO: a simple safety wrapper that will ensure that the line sent
# to syslog is reasonable.
# TODO: a simple safety wrapper that will ensure that the line sent
# to syslog is reasonable.
# TODO: async version of syslog_client: now, log entries use blocking
# send()
# TODO: async version of syslog_client: now, log entries use blocking
# send()
import
m_syslog
syslog_logger
=
m_syslog
.
syslog_client
...
...
@@ -171,7 +171,7 @@ class syslog_logger (m_syslog.syslog_client):
priority
=
m_syslog
.
LOG_INFO
)
# log to a stream socket, asynchronously
# log to a stream socket, asynchronously
class
socket_logger
(
asynchat
.
async_chat
):
...
...
@@ -194,7 +194,7 @@ class socket_logger (asynchat.async_chat):
else
:
self
.
socket
.
push
(
message
)
# log to multiple places
# log to multiple places
class
multi_logger
:
def
__init__
(
self
,
loggers
):
self
.
loggers
=
loggers
...
...
ZServer/medusa/m_syslog.py
View file @
b9e5da32
ZServer/medusa/misc/async_mysql.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
VERSION_STRING
=
'$Id: async_mysql.py,v 1.
2 2001/04/25 19:09:49
andreas Exp $'
VERSION_STRING
=
'$Id: async_mysql.py,v 1.
3 2001/05/01 11:45:26
andreas Exp $'
import
exceptions
import
math
...
...
@@ -17,18 +17,18 @@ from fifo import fifo
class
mysql_error
(
exceptions
.
Exception
):
pass
# ===========================================================================
# Authentication
# ===========================================================================
# ===========================================================================
# Authentication
# ===========================================================================
# Note: I've ignored the stuff to support an older version of the protocol.
#
# The code is based on the file mysql-3.21.33/client/password.c
#
# The auth scheme is challenge/response. Upon connection the server
# sends an 8-byte challenge message. This is hashed with the password
# to produce an 8-byte response. The server side performs an identical
# hash to verify the password is correct.
# Note: I've ignored the stuff to support an older version of the protocol.
#
# The code is based on the file mysql-3.21.33/client/password.c
#
# The auth scheme is challenge/response. Upon connection the server
# sends an 8-byte challenge message. This is hashed with the password
# to produce an 8-byte response. The server side performs an identical
# hash to verify the password is correct.
class
random_state
:
...
...
@@ -73,9 +73,9 @@ def scramble (message, password):
to
[
i
]
=
to
[
i
]
^
extra
return
to
# ===========================================================================
# Packet Protocol
# ===========================================================================
# ===========================================================================
# Packet Protocol
# ===========================================================================
def
unpacket
(
p
):
# 3-byte length, one-byte packet number, followed by packet data
...
...
@@ -110,7 +110,7 @@ def net_field_length (data, pos=0):
# libmysql adds 6, why?
return
n_byte_num
(
data
,
4
),
5
# used to generate the dumps below
# used to generate the dumps below
def
dump_hex
(
s
):
r1
=
[]
r2
=
[]
...
...
@@ -122,9 +122,9 @@ def dump_hex (s):
r2
.
append
(
' '
)
return
string
.
join
(
r1
,
''
),
string
.
join
(
r2
,
''
)
# ===========================================================================
# MySQL Client
# ===========================================================================
# ===========================================================================
# MySQL Client
# ===========================================================================
class
mysql_client
(
asynchat
.
async_chat
):
...
...
@@ -305,9 +305,9 @@ class mysql_client (asynchat.async_chat):
def
cmd_query
(
self
,
query
,
callback
=
None
):
self
.
command
(
'query'
,
query
,
result_set
(
callback
))
# ===========================================================================
# Result Set
# ===========================================================================
# ===========================================================================
# Result Set
# ===========================================================================
class
result_set
:
...
...
@@ -440,59 +440,59 @@ if __name__ == '__main__':
c
=
mysql_client
(
username
,
password
,
go
,
(
host
,
3306
))
asyncore
.
loop
()
# greeting:
# * first byte is the protocol version (currently 10)
# * null-terminated version string
# * 4-byte thread id.
# * 8-byte challenge
# * 2-byte server capabilities?
# message = [0x00, 0x39, 0x4d, 0x59, 0x59, 0x31, 0x29, 0x79, 0x47]
# password = [0x66, 0x6e, 0x6f, 0x72, 0x64]
# Handshake:
#----------------------------------------
#<== 000 0a 33 2e 32 32 2e 31 30 2d 62 65 74 61 00 1b 00 00 00 39 4d 59 59 31 29 79 47 00 0c 00
# 3 2 2 1 0 b e t a 9 M Y Y 1 y G
#----------------------------------------
#==> 1
# 05 00 00 00 10 72 75 73 68 69 6e 67 00 48 51 42 50 5d 4a 54 57
# r u s h i n g H Q B P J T W
#----------------------------------------
#<== 002 00 00 00
# Insertion/Query (no result set)
#----------------------------------------
#==> 0
# 03 69 6e 73 65 72 74 20 69 6e 74 6f 20 75 73 65 72 73 20 76 61 6c 75 65 73 20 28 22 61 73 64 66 40 61 73 64 66 2e 61 73 64 66 22 2c 20 22 6e 22 29
# i n s e r t i n t o u s e r s v a l u e s a s d f a s d f a s d f n
#----------------------------------------
#<== 001 00 01 00
# Query (with result set)
#----------------------------------------
#==> 0
# 03 73 65 6c 65 63 74 20 2a 20 66 72 6f 6d 20 75 73 65 72 73
# s e l e c t f r o m u s e r s
#----------------------------------------
#<== 001 02
#
#<== 002 05 75 73 65 72 73 04 6e 61 6d 65 03 80 00 00 01 fe 03 00 00 00
# u s e r s n a m e
#<== 003 05 75 73 65 72 73 0a 69 73 62 6f 75 6e 63 69 6e 67 03 01 00 00 01 fe 03 00 00 00
# u s e r s i s b o u n c i n g
#<== 004 fe
#
#<== 005 15 72 75 73 68 69 6e 67 40 6e 69 67 68 74 6d 61 72 65 2e 63 6f 6d 01 6e
# r u s h i n g n i g h t m a r e c o m n
#<== 006 0e 61 73 64 66 40 61 73 64 66 2e 61 73 64 66 01 6e
# a s d f a s d f a s d f n
#<== 007 fe
# "use bouncer_test"
#==> 0
# 02 62 6f 75 6e 63 65 72 5f 74 65 73 74
# b o u n c e r t e s t
#----------------------------------------
#<== 001 00 00 00
# greeting:
# * first byte is the protocol version (currently 10)
# * null-terminated version string
# * 4-byte thread id.
# * 8-byte challenge
# * 2-byte server capabilities?
# message = [0x00, 0x39, 0x4d, 0x59, 0x59, 0x31, 0x29, 0x79, 0x47]
# password = [0x66, 0x6e, 0x6f, 0x72, 0x64]
# Handshake:
#----------------------------------------
#<== 000 0a 33 2e 32 32 2e 31 30 2d 62 65 74 61 00 1b 00 00 00 39 4d 59 59 31 29 79 47 00 0c 00
# 3 2 2 1 0 b e t a 9 M Y Y 1 y G
#----------------------------------------
#==> 1
# 05 00 00 00 10 72 75 73 68 69 6e 67 00 48 51 42 50 5d 4a 54 57
# r u s h i n g H Q B P J T W
#----------------------------------------
#<== 002 00 00 00
# Insertion/Query (no result set)
#----------------------------------------
#==> 0
# 03 69 6e 73 65 72 74 20 69 6e 74 6f 20 75 73 65 72 73 20 76 61 6c 75 65 73 20 28 22 61 73 64 66 40 61 73 64 66 2e 61 73 64 66 22 2c 20 22 6e 22 29
# i n s e r t i n t o u s e r s v a l u e s a s d f a s d f a s d f n
#----------------------------------------
#<== 001 00 01 00
# Query (with result set)
#----------------------------------------
#==> 0
# 03 73 65 6c 65 63 74 20 2a 20 66 72 6f 6d 20 75 73 65 72 73
# s e l e c t f r o m u s e r s
#----------------------------------------
#<== 001 02
#
#<== 002 05 75 73 65 72 73 04 6e 61 6d 65 03 80 00 00 01 fe 03 00 00 00
# u s e r s n a m e
#<== 003 05 75 73 65 72 73 0a 69 73 62 6f 75 6e 63 69 6e 67 03 01 00 00 01 fe 03 00 00 00
# u s e r s i s b o u n c i n g
#<== 004 fe
#
#<== 005 15 72 75 73 68 69 6e 67 40 6e 69 67 68 74 6d 61 72 65 2e 63 6f 6d 01 6e
# r u s h i n g n i g h t m a r e c o m n
#<== 006 0e 61 73 64 66 40 61 73 64 66 2e 61 73 64 66 01 6e
# a s d f a s d f a s d f n
#<== 007 fe
# "use bouncer_test"
#==> 0
# 02 62 6f 75 6e 63 65 72 5f 74 65 73 74
# b o u n c e r t e s t
#----------------------------------------
#<== 001 00 00 00
ZServer/medusa/misc/recorder.py
View file @
b9e5da32
...
...
@@ -35,7 +35,7 @@ class recorder_server (asyncore.dispatcher):
print
'incoming connection'
,
addr
recorder_channel
(
conn
,
addr
)
# force a clean shutdown
# force a clean shutdown
def
shutdown
():
sm
=
asyncore
.
socket_map
asyncore
.
socket_map
=
{}
...
...
ZServer/medusa/misc/syncsock.py
View file @
b9e5da32
ZServer/medusa/monitor.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# python REPL channel.
#
RCS_ID
=
'$Id: monitor.py,v 1.1
1 2001/04/25 19:07:33
andreas Exp $'
RCS_ID
=
'$Id: monitor.py,v 1.1
2 2001/05/01 11:44:48
andreas Exp $'
import
md5
import
socket
...
...
@@ -268,8 +268,8 @@ class secure_monitor_server (monitor_server):
p
.
data
=
p
.
data
+
(
'<br><b>Failed Authorizations:</b> %d'
%
self
.
failed_auths
)
return
p
# don't try to print from within any of the methods
# of this object. 8^)
# don't try to print from within any of the methods
# of this object. 8^)
class
output_producer
:
def
__init__
(
self
,
channel
,
real_stderr
):
...
...
ZServer/medusa/monitor_client.py
View file @
b9e5da32
ZServer/medusa/monitor_client_win32.py
View file @
b9e5da32
ZServer/medusa/producers.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
RCS_ID
=
'$Id: producers.py,v 1.
9 2001/04/25 19:07:33
andreas Exp $'
RCS_ID
=
'$Id: producers.py,v 1.
10 2001/05/01 11:44:48
andreas Exp $'
import
string
...
...
@@ -107,12 +107,12 @@ class file_producer:
else
:
return
data
# A simple output producer. This one does not [yet] have
# the safety feature builtin to the monitor channel: runaway
# output will not be caught.
# A simple output producer. This one does not [yet] have
# the safety feature builtin to the monitor channel: runaway
# output will not be caught.
# don't try to print from within any of the methods
# of this object.
# don't try to print from within any of the methods
# of this object.
class
output_producer
:
"Acts like an output file; suitable for capturing sys.stdout"
...
...
@@ -215,13 +215,13 @@ class hooked_producer:
else
:
return
''
# HTTP 1.1 emphasizes that an advertised Content-Length header MUST be
# correct. In the face of Strange Files, it is conceivable that
# reading a 'file' may produce an amount of data not matching that
# reported by os.stat() [text/binary mode issues, perhaps the file is
# being appended to, etc..] This makes the chunked encoding a True
# Blessing, and it really ought to be used even with normal files.
# How beautifully it blends with the concept of the producer.
# HTTP 1.1 emphasizes that an advertised Content-Length header MUST be
# correct. In the face of Strange Files, it is conceivable that
# reading a 'file' may produce an amount of data not matching that
# reported by os.stat() [text/binary mode issues, perhaps the file is
# being appended to, etc..] This makes the chunked encoding a True
# Blessing, and it really ought to be used even with normal files.
# How beautifully it blends with the concept of the producer.
class
chunked_producer
:
"""A producer that implements the 'chunked' transfer coding for HTTP/1.1.
...
...
@@ -254,10 +254,10 @@ class chunked_producer:
else
:
return
''
# Unfortunately this isn't very useful right now (Aug 97), because
# apparently the browsers don't do on-the-fly decompression. Which
# is sad, because this could _really_ speed things up, especially for
# low-bandwidth clients (i.e., most everyone).
# Unfortunately this isn't very useful right now (Aug 97), because
# apparently the browsers don't do on-the-fly decompression. Which
# is sad, because this could _really_ speed things up, especially for
# low-bandwidth clients (i.e., most everyone).
try
:
import
zlib
...
...
ZServer/medusa/put_handler.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: put_handler.py,v 1.
2 2001/04/25 19:07:33
andreas Exp $'
RCS_ID
=
'$Id: put_handler.py,v 1.
3 2001/05/01 11:44:48
andreas Exp $'
import
re
import
string
...
...
ZServer/medusa/redirecting_handler.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: redirecting_handler.py,v 1.
2 2001/04/25 19:07:33
andreas Exp $'
RCS_ID
=
'$Id: redirecting_handler.py,v 1.
3 2001/05/01 11:44:49
andreas Exp $'
import
re
import
counter
...
...
ZServer/medusa/resolver.py
View file @
b9e5da32
...
...
@@ -4,7 +4,7 @@
# Author: Sam Rushing <rushing@nightmare.com>
#
RCS_ID
=
'$Id: resolver.py,v 1.
8 2001/04/25 19:07:34
andreas Exp $'
RCS_ID
=
'$Id: resolver.py,v 1.
9 2001/05/01 11:44:49
andreas Exp $'
# Fast, low-overhead asynchronous name resolver. uses 'pre-cooked'
...
...
@@ -114,27 +114,27 @@ def unpack_ttl (r,pos):
map
(
ord
,
r
[
pos
:
pos
+
4
])
)
# resource record
# 1 1 1 1 1 1
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | |
# / /
# / NAME /
# | |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | TYPE |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | CLASS |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | TTL |
# | |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | RDLENGTH |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
# / RDATA /
# / /
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# resource record
# 1 1 1 1 1 1
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | |
# / /
# / NAME /
# | |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | TYPE |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | CLASS |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | TTL |
# | |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | RDLENGTH |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
# / RDATA /
# / /
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
def
unpack_address_reply
(
r
):
ancount
=
(
ord
(
r
[
6
])
<<
8
)
+
(
ord
(
r
[
7
]))
...
...
@@ -183,18 +183,18 @@ def unpack_ptr_reply (r):
return
0
,
None
# This is a UDP (datagram) resolver.
# This is a UDP (datagram) resolver.
#
# It may be useful to implement a TCP resolver. This would presumably
# give us more reliable behavior when things get too busy. A TCP
# client would have to manage the connection carefully, since the
# server is allowed to close it at will (the RFC recommends closing
# after 2 minutes of idle time).
#
# Note also that the TCP client will have to prepend each request
# with a 2-byte length indicator (see rfc1035).
#
#
# It may be useful to implement a TCP resolver. This would presumably
# give us more reliable behavior when things get too busy. A TCP
# client would have to manage the connection carefully, since the
# server is allowed to close it at will (the RFC recommends closing
# after 2 minutes of idle time).
#
# Note also that the TCP client will have to prepend each request
# with a 2-byte length indicator (see rfc1035).
#
class
resolver
(
asyncore
.
dispatcher
):
id
=
counter
()
...
...
@@ -366,28 +366,28 @@ class caching_resolver (resolver):
+
'<br>Cache Hits: %s'
%
self
.
cache_hits
)
#test_reply = """\000\000\205\200\000\001\000\001\000\002\000\002\006squirl\011nightmare\003com\000\000\001\000\001\300\014\000\001\000\001\000\001Q\200\000\004\315\240\260\005\011nightmare\003com\000\000\002\000\001\000\001Q\200\000\002\300\014\3006\000\002\000\001\000\001Q\200\000\015\003ns1\003iag\003net\000\300\014\000\001\000\001\000\001Q\200\000\004\315\240\260\005\300]\000\001\000\001\000\000\350\227\000\004\314\033\322\005"""
# def test_unpacker ():
# print unpack_address_reply (test_reply)
#
# import time
# class timer:
# def __init__ (self):
# self.start = time.time()
# def end (self):
# return time.time() - self.start
#
# # I get ~290 unpacks per second for the typical case, compared to ~48
# # using dnslib directly. also, that latter number does not include
# # picking the actual data out.
#
# def benchmark_unpacker():
#
# r = range(1000)
# t = timer()
# for i in r:
# unpack_address_reply (test_reply)
# print '%.2f unpacks per second' % (1000.0 / t.end())
#test_reply = """\000\000\205\200\000\001\000\001\000\002\000\002\006squirl\011nightmare\003com\000\000\001\000\001\300\014\000\001\000\001\000\001Q\200\000\004\315\240\260\005\011nightmare\003com\000\000\002\000\001\000\001Q\200\000\002\300\014\3006\000\002\000\001\000\001Q\200\000\015\003ns1\003iag\003net\000\300\014\000\001\000\001\000\001Q\200\000\004\315\240\260\005\300]\000\001\000\001\000\000\350\227\000\004\314\033\322\005"""
# def test_unpacker ():
# print unpack_address_reply (test_reply)
#
# import time
# class timer:
# def __init__ (self):
# self.start = time.time()
# def end (self):
# return time.time() - self.start
#
# # I get ~290 unpacks per second for the typical case, compared to ~48
# # using dnslib directly. also, that latter number does not include
# # picking the actual data out.
#
# def benchmark_unpacker():
#
# r = range(1000)
# t = timer()
# for i in r:
# unpack_address_reply (test_reply)
# print '%.2f unpacks per second' % (1000.0 / t.end())
if
__name__
==
'__main__'
:
import
sys
...
...
ZServer/medusa/rpc_client.py
View file @
b9e5da32
...
...
@@ -47,16 +47,16 @@ import errno
class
RPC_Error
(
exceptions
.
StandardError
):
pass
# ===========================================================================
# RPC Client
# ===========================================================================
# ===========================================================================
# RPC Client
# ===========================================================================
# request types:
# 0 call
# 1 getattr
# 2 setattr
# 3 repr
# 4 del
# request types:
# 0 call
# 1 getattr
# 2 setattr
# 3 repr
# 4 del
class
rpc_proxy
:
...
...
@@ -187,9 +187,9 @@ def rpc_connect (address = ('localhost', 8746)):
rpc_connection
.
cache
[
address
]
=
rpc_proxy
(
conn
,
oid
)
return
rpc_connection
.
cache
[
address
]
# ===========================================================================
# fastrpc client
# ===========================================================================
# ===========================================================================
# fastrpc client
# ===========================================================================
class
fastrpc_proxy
:
...
...
@@ -224,9 +224,9 @@ def fastrpc_connect (address = ('localhost', 8748)):
rpc_connection
.
cache
[
address
]
=
fastrpc_proxy
(
conn
)
return
rpc_connection
.
cache
[
address
]
# ===========================================================================
# async fastrpc client
# ===========================================================================
# ===========================================================================
# async fastrpc client
# ===========================================================================
import
asynchat
import
fifo
...
...
ZServer/medusa/rpc_server.py
View file @
b9e5da32
...
...
@@ -202,21 +202,21 @@ class rpc_server (asyncore.dispatcher):
rpc_channel
(
self
.
root
,
conn
,
addr
)
# ===========================================================================
# Fast RPC server
# ===========================================================================
# no proxies, request consists
# of a 'chain' of getattrs terminated by a __call__.
# Protocol:
# <path>.<to>.<object> ( <param1>, <param2>, ... )
# => ( <value1>, <value2>, ... )
#
#
# (<path>, <params>)
# path: tuple of strings
# params: tuple of objects
# ===========================================================================
# Fast RPC server
# ===========================================================================
# no proxies, request consists
# of a 'chain' of getattrs terminated by a __call__.
# Protocol:
# <path>.<to>.<object> ( <param1>, <param2>, ... )
# => ( <value1>, <value2>, ... )
#
#
# (<path>, <params>)
# path: tuple of strings
# params: tuple of objects
class
fastrpc_channel
(
asynchat
.
async_chat
):
...
...
@@ -285,7 +285,7 @@ class fastrpc_server (asyncore.dispatcher):
conn
,
addr
=
self
.
accept
()
fastrpc_channel
(
self
.
root
,
conn
,
addr
)
# ===========================================================================
# ===========================================================================
if
__name__
==
'__main__'
:
...
...
ZServer/medusa/script_handler.py
View file @
b9e5da32
ZServer/medusa/script_handler_demo/form.mpy
View file @
b9e5da32
ZServer/medusa/script_handler_demo/persistent.py
View file @
b9e5da32
ZServer/medusa/script_handler_demo/today.mpy
View file @
b9e5da32
ZServer/medusa/sendfile/asynchat_sendfile.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
RCS_ID
=
'$Id: asynchat_sendfile.py,v 1.
2 2001/04/25 19:09:54
andreas Exp $'
RCS_ID
=
'$Id: asynchat_sendfile.py,v 1.
3 2001/05/01 11:45:27
andreas Exp $'
import
sendfile
import
asynchat
...
...
@@ -49,9 +49,9 @@ class async_chat_with_sendfile (async_chat):
if
callback
is
not
None
:
callback
(
0
,
fd
)
# here's how you might use this:
# fd = os.open (filename, os.O_RDONLY, 0644)
# size = os.lseek (fd, 0, 2)
# os.lseek (fd, 0, 0)
# self.push ('%08x' % size)
# self.push_sendfile (fd, 0, size)
# here's how you might use this:
# fd = os.open (filename, os.O_RDONLY, 0644)
# size = os.lseek (fd, 0, 2)
# os.lseek (fd, 0, 0)
# self.push ('%08x' % size)
# self.push_sendfile (fd, 0, size)
ZServer/medusa/sendfile/test_sendfile.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
RCS_ID
=
'$Id: test_sendfile.py,v 1.
2 2001/04/25 19:09:54
andreas Exp $'
RCS_ID
=
'$Id: test_sendfile.py,v 1.
3 2001/05/01 11:45:27
andreas Exp $'
import
asyncore
import
os
...
...
ZServer/medusa/start_medusa.py
View file @
b9e5da32
...
...
@@ -115,13 +115,13 @@ if os.name == 'posix':
uh
=
unix_user_handler
.
unix_user_handler
(
'public_html'
)
hs
.
install_handler
(
uh
)
# ===========================================================================
# FTP Server
# ===========================================================================
# ===========================================================================
# FTP Server
# ===========================================================================
# Here we create an 'anonymous' ftp server.
# Note: the ftp server is read-only by default. [in this mode, all
# 'write-capable' commands are unavailable]
# Here we create an 'anonymous' ftp server.
# Note: the ftp server is read-only by default. [in this mode, all
# 'write-capable' commands are unavailable]
ftp
=
ftp_server
.
ftp_server
(
ftp_server
.
anon_authorizer
(
...
...
@@ -192,7 +192,7 @@ if os.name == 'posix':
os
.
setegid
(
gid
)
os
.
seteuid
(
uid
)
# Finally, start up the server loop! This loop will not exit until
# all clients and servers are closed. You may cleanly shut the system
# down by sending SIGINT (a.k.a. KeyboardInterrupt).
# Finally, start up the server loop! This loop will not exit until
# all clients and servers are closed. You may cleanly shut the system
# down by sending SIGINT (a.k.a. KeyboardInterrupt).
asyncore
.
loop
()
ZServer/medusa/status_handler.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
VERSION_STRING
=
"$Id: status_handler.py,v 1.
6 2001/04/25 19:07:34
andreas Exp $"
VERSION_STRING
=
"$Id: status_handler.py,v 1.
7 2001/05/01 11:44:49
andreas Exp $"
#
# medusa status extension
...
...
@@ -215,7 +215,7 @@ class channel_list_producer (lines_producer):
)
# this really needs a full-blown quoter...
# this really needs a full-blown quoter...
def
sanitize
(
s
):
if
'<'
in
s
:
s
=
string
.
join
(
string
.
split
(
s
,
'<'
),
'<'
)
...
...
@@ -238,11 +238,11 @@ def html_reprs (list, front='', back=''):
reprs
.
sort
()
return
reprs
# for example, tera, giga, mega, kilo
# p_d (n, (1024, 1024, 1024, 1024))
# smallest divider goes first - for example
# minutes, hours, days
# p_d (n, (60, 60, 24))
# for example, tera, giga, mega, kilo
# p_d (n, (1024, 1024, 1024, 1024))
# smallest divider goes first - for example
# minutes, hours, days
# p_d (n, (60, 60, 24))
def
progressive_divide
(
n
,
parts
):
result
=
[]
...
...
@@ -252,7 +252,7 @@ def progressive_divide (n, parts):
result
.
append
(
n
)
return
result
# b,k,m,g,t
# b,k,m,g,t
def
split_by_units
(
n
,
units
,
dividers
,
format_string
):
divs
=
progressive_divide
(
n
,
dividers
)
result
=
[]
...
...
ZServer/medusa/test/asyn_http_bench.py
View file @
b9e5da32
...
...
@@ -28,17 +28,17 @@ class http_client (asyncore.dispatcher_with_send):
def
handle_connect
(
self
):
self
.
connected
=
1
# blurt ('o')
# blurt ('o')
self
.
send
(
'GET %s HTTP/1.0
\
r
\
n
\
r
\
n
'
%
self
.
uri
)
def
handle_read
(
self
):
# blurt ('.')
# blurt ('.')
d
=
self
.
recv
(
8192
)
self
.
bytes
=
self
.
bytes
+
len
(
d
)
def
handle_close
(
self
):
global
total_sessions
# blurt ('(%d)' % (self.bytes))
# blurt ('(%d)' % (self.bytes))
self
.
close
()
total_sessions
=
total_sessions
+
1
if
self
.
num
:
...
...
@@ -89,10 +89,10 @@ if __name__ == '__main__':
print
'Max. number of concurrent sessions: %d'
%
(
MAX
)
# linux 2.x, talking to medusa
# 50 clients
# 1000 hits/client
# total_hits:50000
# 2255.858 seconds
# total hits/sec:22.165
# Max. number of concurrent sessions: 50
# linux 2.x, talking to medusa
# 50 clients
# 1000 hits/client
# total_hits:50000
# 2255.858 seconds
# total hits/sec:22.165
# Max. number of concurrent sessions: 50
ZServer/medusa/test/max_sockets.py
View file @
b9e5da32
ZServer/medusa/test/test_11.py
View file @
b9e5da32
ZServer/medusa/test/test_lb.py
View file @
b9e5da32
...
...
@@ -62,12 +62,12 @@ class test_server (asyncore.dispatcher):
conn
,
addr
=
self
.
accept
()
test_channel
(
conn
,
addr
)
# ==================================================
# client
# ==================================================
# ==================================================
# client
# ==================================================
# pretty much the same behavior, except that we kick
# off the exchange and decide when to quit
# pretty much the same behavior, except that we kick
# off the exchange and decide when to quit
class
test_client
(
test_channel
):
...
...
ZServer/medusa/test/test_medusa.py
View file @
b9e5da32
ZServer/medusa/test/test_single_11.py
View file @
b9e5da32
ZServer/medusa/thread/pi_module.py
View file @
b9e5da32
ZServer/medusa/thread/select_trigger.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
VERSION_STRING
=
"$Id: select_trigger.py,v 1.
2 2001/04/25 19:09:56
andreas Exp $"
VERSION_STRING
=
"$Id: select_trigger.py,v 1.
3 2001/05/01 11:45:27
andreas Exp $"
import
asyncore
import
asynchat
...
...
ZServer/medusa/thread/test_module.py
View file @
b9e5da32
ZServer/medusa/thread/thread_channel.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
VERSION_STRING
=
"$Id: thread_channel.py,v 1.
2 2001/04/25 19:09:56
andreas Exp $"
VERSION_STRING
=
"$Id: thread_channel.py,v 1.
3 2001/05/01 11:45:27
andreas Exp $"
# This will probably only work on Unix.
...
...
@@ -72,7 +72,7 @@ class thread_channel (asyncore.file_dispatcher):
# the parent channel here.
self
.
close
()
# Yeah, it's bad when the test code is bigger than the library code.
# Yeah, it's bad when the test code is bigger than the library code.
if
__name__
==
'__main__'
:
...
...
ZServer/medusa/thread/thread_handler.py
View file @
b9e5da32
...
...
@@ -320,9 +320,9 @@ class request_loop_thread (threading.Thread):
function
(
env
,
stdin
,
stdout
)
stdout
.
close
()
# ===========================================================================
# Testing
# ===========================================================================
# ===========================================================================
# Testing
# ===========================================================================
if
__name__
==
'__main__'
:
...
...
ZServer/medusa/unix_user_handler.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: unix_user_handler.py,v 1.
2 2001/04/25 19:07:34
andreas Exp $'
RCS_ID
=
'$Id: unix_user_handler.py,v 1.
3 2001/05/01 11:44:49
andreas Exp $'
# support for `~user/public_html'.
...
...
ZServer/medusa/virtual_handler.py
View file @
b9e5da32
ZServer/medusa/xmlrpc_handler.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# Based on "xmlrpcserver.py" by Fredrik Lundh (fredrik@pythonware.com)
VERSION
=
"$Id: xmlrpc_handler.py,v 1.
2 2001/04/25 19:07:34
andreas Exp $"
VERSION
=
"$Id: xmlrpc_handler.py,v 1.
3 2001/05/01 11:44:49
andreas Exp $"
import
http_server
import
xmlrpclib
...
...
lib/python/ZServer/medusa/asynchat.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
# $Id: asynchat.py,v 1.1
6 2001/04/25 19:07:29
andreas Exp $
# $Id: asynchat.py,v 1.1
7 2001/05/01 11:44:48
andreas Exp $
# Author: Sam Rushing <rushing@nightmare.com>
# ======================================================================
...
...
@@ -270,20 +270,20 @@ class fifo:
else
:
return
(
0
,
None
)
# Given 'haystack', see if any prefix of 'needle' is at its end. This
# assumes an exact match has already been checked. Return the number of
# characters matched.
# for example:
# f_p_a_e ("qwerty\r", "\r\n") => 1
# f_p_a_e ("qwertydkjf", "\r\n") => 0
# f_p_a_e ("qwerty\r\n", "\r\n") => <undefined>
# this could maybe be made faster with a computed regex?
# [answer: no; circa Python-2.0, Jan 2001]
# new python: 28961/s
# old python: 18307/s
# re: 12820/s
# regex: 14035/s
# Given 'haystack', see if any prefix of 'needle' is at its end. This
# assumes an exact match has already been checked. Return the number of
# characters matched.
# for example:
# f_p_a_e ("qwerty\r", "\r\n") => 1
# f_p_a_e ("qwertydkjf", "\r\n") => 0
# f_p_a_e ("qwerty\r\n", "\r\n") => <undefined>
# this could maybe be made faster with a computed regex?
# [answer: no; circa Python-2.0, Jan 2001]
# new python: 28961/s
# old python: 18307/s
# re: 12820/s
# regex: 14035/s
def
find_prefix_at_end
(
haystack
,
needle
):
l
=
len
(
needle
)
-
1
...
...
lib/python/ZServer/medusa/auth_handler.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: auth_handler.py,v 1.
2 2001/04/25 19:07:30
andreas Exp $'
RCS_ID
=
'$Id: auth_handler.py,v 1.
3 2001/05/01 11:44:48
andreas Exp $'
# support for 'basic' authenticaion.
...
...
lib/python/ZServer/medusa/chat_server.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: chat_server.py,v 1.
2 2001/04/25 19:07:30
andreas Exp $'
RCS_ID
=
'$Id: chat_server.py,v 1.
3 2001/05/01 11:44:48
andreas Exp $'
import
string
...
...
lib/python/ZServer/medusa/continuation.py
View file @
b9e5da32
lib/python/ZServer/medusa/contrib/bobo_handler.py
View file @
b9e5da32
lib/python/ZServer/medusa/contrib/sample_cgi.py
View file @
b9e5da32
lib/python/ZServer/medusa/counter.py
View file @
b9e5da32
lib/python/ZServer/medusa/default_handler.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: default_handler.py,v 1.
6 2001/04/25 19:07:30
andreas Exp $'
RCS_ID
=
'$Id: default_handler.py,v 1.
7 2001/05/01 11:44:48
andreas Exp $'
# standard python modules
import
os
...
...
@@ -190,9 +190,9 @@ class default_handler:
+
'</ul>'
)
# HTTP/1.0 doesn't say anything about the "; length=nnnn" addition
# to this header. I suppose it's purpose is to avoid the overhead
# of parsing dates...
# HTTP/1.0 doesn't say anything about the "; length=nnnn" addition
# to this header. I suppose it's purpose is to avoid the overhead
# of parsing dates...
IF_MODIFIED_SINCE
=
re
.
compile
(
'If-Modified-Since: ([^;]+)((; length=([0-9]+)$)|$)'
,
re
.
IGNORECASE
...
...
lib/python/ZServer/medusa/event_loop.py
View file @
b9e5da32
lib/python/ZServer/medusa/fifo.py
View file @
b9e5da32
lib/python/ZServer/medusa/filesys.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
# $Id: filesys.py,v 1.
8 2001/04/27 18:25:42
andreas Exp $
# $Id: filesys.py,v 1.
9 2001/05/01 11:44:48
andreas Exp $
# Author: Sam Rushing <rushing@nightmare.com>
#
# Generic filesystem interface.
...
...
@@ -59,15 +59,15 @@ class abstract_filesystem:
[for the output of the LIST command]"""
pass
# standard wrapper around a unix-like filesystem, with a 'false root'
# capability.
# standard wrapper around a unix-like filesystem, with a 'false root'
# capability.
# security considerations: can symbolic links be used to 'escape' the
# root? should we allow it? if not, then we could scan the
# filesystem on startup, but that would not help if they were added
# later. We will probably need to check for symlinks in the cwd method.
# security considerations: can symbolic links be used to 'escape' the
# root? should we allow it? if not, then we could scan the
# filesystem on startup, but that would not help if they were added
# later. We will probably need to check for symlinks in the cwd method.
# what to do if wd is an invalid directory?
# what to do if wd is an invalid directory?
import
os
,
re
import
stat
...
...
@@ -251,88 +251,88 @@ if os.name == 'posix':
finally
:
self
.
become_nobody
()
# This hasn't been very reliable across different platforms.
# maybe think about a separate 'directory server'.
#
# import posixpath
# import fcntl
# import FCNTL
# import select
# import asyncore
#
# # pipes /bin/ls for directory listings.
# class unix_filesystem (os_filesystem):
# pass
# path_module = posixpath
#
# def listdir (self, path, long=0):
# p = self.translate (path)
# if not long:
# return list_producer (os.listdir (p), 0, None)
# else:
# command = '/bin/ls -l %s' % p
# print 'opening pipe to "%s"' % command
# fd = os.popen (command, 'rt')
# return pipe_channel (fd)
#
# # this is both a dispatcher, _and_ a producer
# class pipe_channel (asyncore.file_dispatcher):
# buffer_size = 4096
#
# def __init__ (self, fd):
# asyncore.file_dispatcher.__init__ (self, fd)
# self.fd = fd
# self.done = 0
# self.data = ''
#
# def handle_read (self):
# if len (self.data) < self.buffer_size:
# self.data = self.data + self.fd.read (self.buffer_size)
# #print '%s.handle_read() => len(self.data) == %d' % (self, len(self.data))
#
# def handle_expt (self):
# #print '%s.handle_expt()' % self
# self.done = 1
#
# def ready (self):
# #print '%s.ready() => %d' % (self, len(self.data))
# return ((len (self.data) > 0) or self.done)
#
# def more (self):
# if self.data:
# r = self.data
# self.data = ''
# elif self.done:
# self.close()
# self.downstream.finished()
# r = ''
# else:
# r = None
# #print '%s.more() => %s' % (self, (r and len(r)))
# return r
# For the 'real' root, we could obtain a list of drives, and then
# use that. Doesn't win32 provide such a 'real' filesystem?
# [yes, I think something like this "\\.\c\windows"]
# This hasn't been very reliable across different platforms.
# maybe think about a separate 'directory server'.
#
# import posixpath
# import fcntl
# import FCNTL
# import select
# import asyncore
#
# # pipes /bin/ls for directory listings.
# class unix_filesystem (os_filesystem):
# pass
# path_module = posixpath
#
# def listdir (self, path, long=0):
# p = self.translate (path)
# if not long:
# return list_producer (os.listdir (p), 0, None)
# else:
# command = '/bin/ls -l %s' % p
# print 'opening pipe to "%s"' % command
# fd = os.popen (command, 'rt')
# return pipe_channel (fd)
#
# # this is both a dispatcher, _and_ a producer
# class pipe_channel (asyncore.file_dispatcher):
# buffer_size = 4096
#
# def __init__ (self, fd):
# asyncore.file_dispatcher.__init__ (self, fd)
# self.fd = fd
# self.done = 0
# self.data = ''
#
# def handle_read (self):
# if len (self.data) < self.buffer_size:
# self.data = self.data + self.fd.read (self.buffer_size)
# #print '%s.handle_read() => len(self.data) == %d' % (self, len(self.data))
#
# def handle_expt (self):
# #print '%s.handle_expt()' % self
# self.done = 1
#
# def ready (self):
# #print '%s.ready() => %d' % (self, len(self.data))
# return ((len (self.data) > 0) or self.done)
#
# def more (self):
# if self.data:
# r = self.data
# self.data = ''
# elif self.done:
# self.close()
# self.downstream.finished()
# r = ''
# else:
# r = None
# #print '%s.more() => %s' % (self, (r and len(r)))
# return r
# For the 'real' root, we could obtain a list of drives, and then
# use that. Doesn't win32 provide such a 'real' filesystem?
# [yes, I think something like this "\\.\c\windows"]
class
msdos_filesystem
(
os_filesystem
):
def
longify
(
self
,
(
path
,
stat_info
)):
return
msdos_longify
(
path
,
stat_info
)
# A merged filesystem will let you plug other filesystems together.
# We really need the equivalent of a 'mount' capability - this seems
# to be the most general idea. So you'd use a 'mount' method to place
# another filesystem somewhere in the hierarchy.
# A merged filesystem will let you plug other filesystems together.
# We really need the equivalent of a 'mount' capability - this seems
# to be the most general idea. So you'd use a 'mount' method to place
# another filesystem somewhere in the hierarchy.
# Note: this is most likely how I will handle ~user directories
# with the http server.
# Note: this is most likely how I will handle ~user directories
# with the http server.
class
merged_filesystem
:
def
__init__
(
self
,
*
fsys
):
pass
# this matches the output of NT's ftp server (when in
# MSDOS mode) exactly.
# this matches the output of NT's ftp server (when in
# MSDOS mode) exactly.
def
msdos_longify
(
file
,
stat_info
):
if
stat
.
S_ISDIR
(
stat_info
[
stat
.
ST_MODE
]):
...
...
@@ -403,12 +403,12 @@ def unix_longify (file, stat_info):
file
)
# Emulate the unix 'ls' command's date field.
# it has two formats - if the date is more than 180
# days in the past, then it's like this:
# Oct 19 1995
# otherwise, it looks like this:
# Oct 19 17:33
# Emulate the unix 'ls' command's date field.
# it has two formats - if the date is more than 180
# days in the past, then it's like this:
# Oct 19 1995
# otherwise, it looks like this:
# Oct 19 17:33
def
ls_date
(
now
,
t
):
try
:
...
...
@@ -430,9 +430,9 @@ def ls_date (now, t):
info
[
4
]
)
# ===========================================================================
# Producers
# ===========================================================================
# ===========================================================================
# Producers
# ===========================================================================
class
list_producer
:
def
__init__
(
self
,
file_list
,
long
,
longify
):
...
...
lib/python/ZServer/medusa/ftp_server.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: ftp_server.py,v 1.1
6 2001/04/27 18:26:51
andreas Exp $'
RCS_ID
=
'$Id: ftp_server.py,v 1.1
7 2001/05/01 11:44:48
andreas Exp $'
# An extensible, configurable, asynchronous FTP server.
#
...
...
@@ -99,8 +99,8 @@ class ftp_channel (asynchat.async_chat):
)
)
# def __del__ (self):
# print 'ftp_channel.__del__()'
# def __del__ (self):
# print 'ftp_channel.__del__()'
# --------------------------------------------------
# async-library methods
...
...
@@ -633,15 +633,15 @@ class ftp_channel (asynchat.async_chat):
else
:
self
.
respond
(
'502 Unimplemented MODE type'
)
# The stat command has two personalities. Normally it returns status
# information about the current connection. But if given an argument,
# it is equivalent to the LIST command, with the data sent over the
# control connection. Strange. But wuftpd, ftpd, and nt's ftp server
# all support it.
#
## def cmd_stat (self, line):
## 'return status of server'
## pass
# The stat command has two personalities. Normally it returns status
# information about the current connection. But if given an argument,
# it is equivalent to the LIST command, with the data sent over the
# control connection. Strange. But wuftpd, ftpd, and nt's ftp server
# all support it.
#
## def cmd_stat (self, line):
## 'return status of server'
## pass
def
cmd_syst
(
self
,
line
):
'show operating system type of server system'
...
...
@@ -777,32 +777,32 @@ class ftp_server (asyncore.dispatcher):
]
)
# ======================================================================
# Data Channel Classes
# ======================================================================
# ======================================================================
# Data Channel Classes
# ======================================================================
# This socket accepts a data connection, used when the server has been
# placed in passive mode. Although the RFC implies that we ought to
# be able to use the same acceptor over and over again, this presents
# a problem: how do we shut it off, so that we are accepting
# connections only when we expect them? [we can't]
#
# wuftpd, and probably all the other servers, solve this by allowing
# only one connection to hit this acceptor. They then close it. Any
# subsequent data-connection command will then try for the default
# port on the client side [which is of course never there]. So the
# 'always-send-PORT/PASV' behavior seems required.
#
# Another note: wuftpd will also be listening on the channel as soon
# as the PASV command is sent. It does not wait for a data command
# first.
# This socket accepts a data connection, used when the server has been
# placed in passive mode. Although the RFC implies that we ought to
# be able to use the same acceptor over and over again, this presents
# a problem: how do we shut it off, so that we are accepting
# connections only when we expect them? [we can't]
#
# wuftpd, and probably all the other servers, solve this by allowing
# only one connection to hit this acceptor. They then close it. Any
# subsequent data-connection command will then try for the default
# port on the client side [which is of course never there]. So the
# 'always-send-PORT/PASV' behavior seems required.
#
# Another note: wuftpd will also be listening on the channel as soon
# as the PASV command is sent. It does not wait for a data command
# first.
# --- we need to queue up a particular behavior:
# 1) xmit : queue up producer[s]
# 2) recv : the file object
#
# It would be nice if we could make both channels the same. Hmmm..
#
# --- we need to queue up a particular behavior:
# 1) xmit : queue up producer[s]
# 2) recv : the file object
#
# It would be nice if we could make both channels the same. Hmmm..
#
class
passive_acceptor
(
asyncore
.
dispatcher
):
ready
=
None
...
...
@@ -821,8 +821,8 @@ class passive_acceptor (asyncore.dispatcher):
self
.
addr
=
self
.
getsockname
()
self
.
listen
(
1
)
# def __del__ (self):
# print 'passive_acceptor.__del__()'
# def __del__ (self):
# print 'passive_acceptor.__del__()'
def
log
(
self
,
*
ignore
):
pass
...
...
@@ -854,8 +854,8 @@ class xmit_channel (asynchat.async_chat):
self
.
client_addr
=
client_addr
asynchat
.
async_chat
.
__init__
(
self
)
# def __del__ (self):
# print 'xmit_channel.__del__()'
# def __del__ (self):
# print 'xmit_channel.__del__()'
def
log
(
*
args
):
pass
...
...
@@ -962,9 +962,9 @@ class anon_authorizer:
else
:
return
0
,
'Password invalid.'
,
None
# ===========================================================================
# Unix-specific improvements
# ===========================================================================
# ===========================================================================
# Unix-specific improvements
# ===========================================================================
if
os
.
name
==
'posix'
:
...
...
@@ -1046,9 +1046,9 @@ class file_producer:
self
.
done
=
1
return
block
# usage: ftp_server /PATH/TO/FTP/ROOT PORT
# for example:
# $ ftp_server /home/users/ftp 8021
# usage: ftp_server /PATH/TO/FTP/ROOT PORT
# for example:
# $ ftp_server /home/users/ftp 8021
if
os
.
name
==
'posix'
:
def
test
(
port
=
'8021'
):
...
...
@@ -1067,17 +1067,17 @@ if os.name == 'posix':
if
__name__
==
'__main__'
:
test
(
sys
.
argv
[
1
])
# not unix
# not unix
else
:
def
test
():
fs
=
ftp_server
(
dummy_authorizer
())
if
__name__
==
'__main__'
:
test
()
# this is the command list from the wuftpd man page
# '*' means we've implemented it.
# '!' requires write access
#
# this is the command list from the wuftpd man page
# '*' means we've implemented it.
# '!' requires write access
#
command_documentation
=
{
'abor'
:
'abort previous command'
,
#*
'acct'
:
'specify account (ignored)'
,
...
...
lib/python/ZServer/medusa/http_bobo.py
View file @
b9e5da32
...
...
@@ -3,7 +3,7 @@
import
string
import
regex
RCS_ID
=
'$Id: http_bobo.py,v 1.
3 2001/04/26 00:07:52
andreas Exp $'
RCS_ID
=
'$Id: http_bobo.py,v 1.
4 2001/05/01 11:44:48
andreas Exp $'
VERSION_STRING
=
string
.
split
(
RCS_ID
)[
2
]
class
bobo_extension
:
...
...
lib/python/ZServer/medusa/http_date.py
View file @
b9e5da32
...
...
@@ -68,7 +68,7 @@ def unpack_rfc822 (m):
0
)
# rfc850 format
# rfc850 format
rfc850_date
=
join
(
[
concat
(
long_day_reg
,
','
),
join
(
...
...
@@ -101,8 +101,8 @@ def unpack_rfc850 (m):
0
)
# parsdate.parsedate - ~700/sec.
# parse_http_date - ~1333/sec.
# parsdate.parsedate - ~700/sec.
# parse_http_date - ~1333/sec.
def
build_http_date
(
when
):
return
time
.
strftime
(
'%a, %d %b %Y %H:%M:%S GMT'
,
time
.
gmtime
(
when
))
...
...
lib/python/ZServer/medusa/http_server.py
View file @
b9e5da32
...
...
@@ -6,7 +6,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: http_server.py,v 1.2
3 2001/04/30 14:38:40
andreas Exp $'
RCS_ID
=
'$Id: http_server.py,v 1.2
4 2001/05/01 11:44:48
andreas Exp $'
# python modules
import
os
...
...
@@ -331,9 +331,9 @@ class http_request:
)
# ===========================================================================
# HTTP Channel Object
# ===========================================================================
# ===========================================================================
# HTTP Channel Object
# ===========================================================================
class
http_channel
(
asynchat
.
async_chat
):
...
...
@@ -523,9 +523,9 @@ class http_channel (asynchat.async_chat):
else
:
return
1
# ===========================================================================
# HTTP Server Object
# ===========================================================================
# ===========================================================================
# HTTP Server Object
# ===========================================================================
class
http_server
(
asyncore
.
dispatcher
):
...
...
@@ -748,7 +748,7 @@ def compute_timezone_for_log ():
else
:
return
'+%02d%02d'
%
(
h
,
m
)
# if you run this program over a TZ change boundary, this will be invalid.
# if you run this program over a TZ change boundary, this will be invalid.
tz_for_log
=
compute_timezone_for_log
()
if
__name__
==
'__main__'
:
...
...
lib/python/ZServer/medusa/logger.py
View file @
b9e5da32
...
...
@@ -76,11 +76,11 @@ class file_logger:
else
:
self
.
write
(
message
)
# like a file_logger, but it must be attached to a filename.
# When the log gets too full, or a certain time has passed,
# it backs up the log and starts a new one. Note that backing
# up the log is done via "mv" because anything else (cp, gzip)
# would take time, during which medusa would do nothing else.
# like a file_logger, but it must be attached to a filename.
# When the log gets too full, or a certain time has passed,
# it backs up the log and starts a new one. Note that backing
# up the log is done via "mv" because anything else (cp, gzip)
# would take time, during which medusa would do nothing else.
class
rotating_file_logger
(
file_logger
):
...
...
@@ -142,14 +142,14 @@ class rotating_file_logger (file_logger):
except
:
pass
# syslog is a line-oriented log protocol - this class would be
# appropriate for FTP or HTTP logs, but not for dumping stderr to.
# syslog is a line-oriented log protocol - this class would be
# appropriate for FTP or HTTP logs, but not for dumping stderr to.
# TODO: a simple safety wrapper that will ensure that the line sent
# to syslog is reasonable.
# TODO: a simple safety wrapper that will ensure that the line sent
# to syslog is reasonable.
# TODO: async version of syslog_client: now, log entries use blocking
# send()
# TODO: async version of syslog_client: now, log entries use blocking
# send()
import
m_syslog
syslog_logger
=
m_syslog
.
syslog_client
...
...
@@ -171,7 +171,7 @@ class syslog_logger (m_syslog.syslog_client):
priority
=
m_syslog
.
LOG_INFO
)
# log to a stream socket, asynchronously
# log to a stream socket, asynchronously
class
socket_logger
(
asynchat
.
async_chat
):
...
...
@@ -194,7 +194,7 @@ class socket_logger (asynchat.async_chat):
else
:
self
.
socket
.
push
(
message
)
# log to multiple places
# log to multiple places
class
multi_logger
:
def
__init__
(
self
,
loggers
):
self
.
loggers
=
loggers
...
...
lib/python/ZServer/medusa/m_syslog.py
View file @
b9e5da32
lib/python/ZServer/medusa/misc/async_mysql.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
VERSION_STRING
=
'$Id: async_mysql.py,v 1.
2 2001/04/25 19:09:49
andreas Exp $'
VERSION_STRING
=
'$Id: async_mysql.py,v 1.
3 2001/05/01 11:45:26
andreas Exp $'
import
exceptions
import
math
...
...
@@ -17,18 +17,18 @@ from fifo import fifo
class
mysql_error
(
exceptions
.
Exception
):
pass
# ===========================================================================
# Authentication
# ===========================================================================
# ===========================================================================
# Authentication
# ===========================================================================
# Note: I've ignored the stuff to support an older version of the protocol.
#
# The code is based on the file mysql-3.21.33/client/password.c
#
# The auth scheme is challenge/response. Upon connection the server
# sends an 8-byte challenge message. This is hashed with the password
# to produce an 8-byte response. The server side performs an identical
# hash to verify the password is correct.
# Note: I've ignored the stuff to support an older version of the protocol.
#
# The code is based on the file mysql-3.21.33/client/password.c
#
# The auth scheme is challenge/response. Upon connection the server
# sends an 8-byte challenge message. This is hashed with the password
# to produce an 8-byte response. The server side performs an identical
# hash to verify the password is correct.
class
random_state
:
...
...
@@ -73,9 +73,9 @@ def scramble (message, password):
to
[
i
]
=
to
[
i
]
^
extra
return
to
# ===========================================================================
# Packet Protocol
# ===========================================================================
# ===========================================================================
# Packet Protocol
# ===========================================================================
def
unpacket
(
p
):
# 3-byte length, one-byte packet number, followed by packet data
...
...
@@ -110,7 +110,7 @@ def net_field_length (data, pos=0):
# libmysql adds 6, why?
return
n_byte_num
(
data
,
4
),
5
# used to generate the dumps below
# used to generate the dumps below
def
dump_hex
(
s
):
r1
=
[]
r2
=
[]
...
...
@@ -122,9 +122,9 @@ def dump_hex (s):
r2
.
append
(
' '
)
return
string
.
join
(
r1
,
''
),
string
.
join
(
r2
,
''
)
# ===========================================================================
# MySQL Client
# ===========================================================================
# ===========================================================================
# MySQL Client
# ===========================================================================
class
mysql_client
(
asynchat
.
async_chat
):
...
...
@@ -305,9 +305,9 @@ class mysql_client (asynchat.async_chat):
def
cmd_query
(
self
,
query
,
callback
=
None
):
self
.
command
(
'query'
,
query
,
result_set
(
callback
))
# ===========================================================================
# Result Set
# ===========================================================================
# ===========================================================================
# Result Set
# ===========================================================================
class
result_set
:
...
...
@@ -440,59 +440,59 @@ if __name__ == '__main__':
c
=
mysql_client
(
username
,
password
,
go
,
(
host
,
3306
))
asyncore
.
loop
()
# greeting:
# * first byte is the protocol version (currently 10)
# * null-terminated version string
# * 4-byte thread id.
# * 8-byte challenge
# * 2-byte server capabilities?
# message = [0x00, 0x39, 0x4d, 0x59, 0x59, 0x31, 0x29, 0x79, 0x47]
# password = [0x66, 0x6e, 0x6f, 0x72, 0x64]
# Handshake:
#----------------------------------------
#<== 000 0a 33 2e 32 32 2e 31 30 2d 62 65 74 61 00 1b 00 00 00 39 4d 59 59 31 29 79 47 00 0c 00
# 3 2 2 1 0 b e t a 9 M Y Y 1 y G
#----------------------------------------
#==> 1
# 05 00 00 00 10 72 75 73 68 69 6e 67 00 48 51 42 50 5d 4a 54 57
# r u s h i n g H Q B P J T W
#----------------------------------------
#<== 002 00 00 00
# Insertion/Query (no result set)
#----------------------------------------
#==> 0
# 03 69 6e 73 65 72 74 20 69 6e 74 6f 20 75 73 65 72 73 20 76 61 6c 75 65 73 20 28 22 61 73 64 66 40 61 73 64 66 2e 61 73 64 66 22 2c 20 22 6e 22 29
# i n s e r t i n t o u s e r s v a l u e s a s d f a s d f a s d f n
#----------------------------------------
#<== 001 00 01 00
# Query (with result set)
#----------------------------------------
#==> 0
# 03 73 65 6c 65 63 74 20 2a 20 66 72 6f 6d 20 75 73 65 72 73
# s e l e c t f r o m u s e r s
#----------------------------------------
#<== 001 02
#
#<== 002 05 75 73 65 72 73 04 6e 61 6d 65 03 80 00 00 01 fe 03 00 00 00
# u s e r s n a m e
#<== 003 05 75 73 65 72 73 0a 69 73 62 6f 75 6e 63 69 6e 67 03 01 00 00 01 fe 03 00 00 00
# u s e r s i s b o u n c i n g
#<== 004 fe
#
#<== 005 15 72 75 73 68 69 6e 67 40 6e 69 67 68 74 6d 61 72 65 2e 63 6f 6d 01 6e
# r u s h i n g n i g h t m a r e c o m n
#<== 006 0e 61 73 64 66 40 61 73 64 66 2e 61 73 64 66 01 6e
# a s d f a s d f a s d f n
#<== 007 fe
# "use bouncer_test"
#==> 0
# 02 62 6f 75 6e 63 65 72 5f 74 65 73 74
# b o u n c e r t e s t
#----------------------------------------
#<== 001 00 00 00
# greeting:
# * first byte is the protocol version (currently 10)
# * null-terminated version string
# * 4-byte thread id.
# * 8-byte challenge
# * 2-byte server capabilities?
# message = [0x00, 0x39, 0x4d, 0x59, 0x59, 0x31, 0x29, 0x79, 0x47]
# password = [0x66, 0x6e, 0x6f, 0x72, 0x64]
# Handshake:
#----------------------------------------
#<== 000 0a 33 2e 32 32 2e 31 30 2d 62 65 74 61 00 1b 00 00 00 39 4d 59 59 31 29 79 47 00 0c 00
# 3 2 2 1 0 b e t a 9 M Y Y 1 y G
#----------------------------------------
#==> 1
# 05 00 00 00 10 72 75 73 68 69 6e 67 00 48 51 42 50 5d 4a 54 57
# r u s h i n g H Q B P J T W
#----------------------------------------
#<== 002 00 00 00
# Insertion/Query (no result set)
#----------------------------------------
#==> 0
# 03 69 6e 73 65 72 74 20 69 6e 74 6f 20 75 73 65 72 73 20 76 61 6c 75 65 73 20 28 22 61 73 64 66 40 61 73 64 66 2e 61 73 64 66 22 2c 20 22 6e 22 29
# i n s e r t i n t o u s e r s v a l u e s a s d f a s d f a s d f n
#----------------------------------------
#<== 001 00 01 00
# Query (with result set)
#----------------------------------------
#==> 0
# 03 73 65 6c 65 63 74 20 2a 20 66 72 6f 6d 20 75 73 65 72 73
# s e l e c t f r o m u s e r s
#----------------------------------------
#<== 001 02
#
#<== 002 05 75 73 65 72 73 04 6e 61 6d 65 03 80 00 00 01 fe 03 00 00 00
# u s e r s n a m e
#<== 003 05 75 73 65 72 73 0a 69 73 62 6f 75 6e 63 69 6e 67 03 01 00 00 01 fe 03 00 00 00
# u s e r s i s b o u n c i n g
#<== 004 fe
#
#<== 005 15 72 75 73 68 69 6e 67 40 6e 69 67 68 74 6d 61 72 65 2e 63 6f 6d 01 6e
# r u s h i n g n i g h t m a r e c o m n
#<== 006 0e 61 73 64 66 40 61 73 64 66 2e 61 73 64 66 01 6e
# a s d f a s d f a s d f n
#<== 007 fe
# "use bouncer_test"
#==> 0
# 02 62 6f 75 6e 63 65 72 5f 74 65 73 74
# b o u n c e r t e s t
#----------------------------------------
#<== 001 00 00 00
lib/python/ZServer/medusa/misc/recorder.py
View file @
b9e5da32
...
...
@@ -35,7 +35,7 @@ class recorder_server (asyncore.dispatcher):
print
'incoming connection'
,
addr
recorder_channel
(
conn
,
addr
)
# force a clean shutdown
# force a clean shutdown
def
shutdown
():
sm
=
asyncore
.
socket_map
asyncore
.
socket_map
=
{}
...
...
lib/python/ZServer/medusa/misc/syncsock.py
View file @
b9e5da32
lib/python/ZServer/medusa/monitor.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# python REPL channel.
#
RCS_ID
=
'$Id: monitor.py,v 1.1
1 2001/04/25 19:07:33
andreas Exp $'
RCS_ID
=
'$Id: monitor.py,v 1.1
2 2001/05/01 11:44:48
andreas Exp $'
import
md5
import
socket
...
...
@@ -268,8 +268,8 @@ class secure_monitor_server (monitor_server):
p
.
data
=
p
.
data
+
(
'<br><b>Failed Authorizations:</b> %d'
%
self
.
failed_auths
)
return
p
# don't try to print from within any of the methods
# of this object. 8^)
# don't try to print from within any of the methods
# of this object. 8^)
class
output_producer
:
def
__init__
(
self
,
channel
,
real_stderr
):
...
...
lib/python/ZServer/medusa/monitor_client.py
View file @
b9e5da32
lib/python/ZServer/medusa/monitor_client_win32.py
View file @
b9e5da32
lib/python/ZServer/medusa/producers.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
RCS_ID
=
'$Id: producers.py,v 1.
9 2001/04/25 19:07:33
andreas Exp $'
RCS_ID
=
'$Id: producers.py,v 1.
10 2001/05/01 11:44:48
andreas Exp $'
import
string
...
...
@@ -107,12 +107,12 @@ class file_producer:
else
:
return
data
# A simple output producer. This one does not [yet] have
# the safety feature builtin to the monitor channel: runaway
# output will not be caught.
# A simple output producer. This one does not [yet] have
# the safety feature builtin to the monitor channel: runaway
# output will not be caught.
# don't try to print from within any of the methods
# of this object.
# don't try to print from within any of the methods
# of this object.
class
output_producer
:
"Acts like an output file; suitable for capturing sys.stdout"
...
...
@@ -215,13 +215,13 @@ class hooked_producer:
else
:
return
''
# HTTP 1.1 emphasizes that an advertised Content-Length header MUST be
# correct. In the face of Strange Files, it is conceivable that
# reading a 'file' may produce an amount of data not matching that
# reported by os.stat() [text/binary mode issues, perhaps the file is
# being appended to, etc..] This makes the chunked encoding a True
# Blessing, and it really ought to be used even with normal files.
# How beautifully it blends with the concept of the producer.
# HTTP 1.1 emphasizes that an advertised Content-Length header MUST be
# correct. In the face of Strange Files, it is conceivable that
# reading a 'file' may produce an amount of data not matching that
# reported by os.stat() [text/binary mode issues, perhaps the file is
# being appended to, etc..] This makes the chunked encoding a True
# Blessing, and it really ought to be used even with normal files.
# How beautifully it blends with the concept of the producer.
class
chunked_producer
:
"""A producer that implements the 'chunked' transfer coding for HTTP/1.1.
...
...
@@ -254,10 +254,10 @@ class chunked_producer:
else
:
return
''
# Unfortunately this isn't very useful right now (Aug 97), because
# apparently the browsers don't do on-the-fly decompression. Which
# is sad, because this could _really_ speed things up, especially for
# low-bandwidth clients (i.e., most everyone).
# Unfortunately this isn't very useful right now (Aug 97), because
# apparently the browsers don't do on-the-fly decompression. Which
# is sad, because this could _really_ speed things up, especially for
# low-bandwidth clients (i.e., most everyone).
try
:
import
zlib
...
...
lib/python/ZServer/medusa/put_handler.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: put_handler.py,v 1.
2 2001/04/25 19:07:33
andreas Exp $'
RCS_ID
=
'$Id: put_handler.py,v 1.
3 2001/05/01 11:44:48
andreas Exp $'
import
re
import
string
...
...
lib/python/ZServer/medusa/redirecting_handler.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: redirecting_handler.py,v 1.
2 2001/04/25 19:07:33
andreas Exp $'
RCS_ID
=
'$Id: redirecting_handler.py,v 1.
3 2001/05/01 11:44:49
andreas Exp $'
import
re
import
counter
...
...
lib/python/ZServer/medusa/resolver.py
View file @
b9e5da32
...
...
@@ -4,7 +4,7 @@
# Author: Sam Rushing <rushing@nightmare.com>
#
RCS_ID
=
'$Id: resolver.py,v 1.
8 2001/04/25 19:07:34
andreas Exp $'
RCS_ID
=
'$Id: resolver.py,v 1.
9 2001/05/01 11:44:49
andreas Exp $'
# Fast, low-overhead asynchronous name resolver. uses 'pre-cooked'
...
...
@@ -114,27 +114,27 @@ def unpack_ttl (r,pos):
map
(
ord
,
r
[
pos
:
pos
+
4
])
)
# resource record
# 1 1 1 1 1 1
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | |
# / /
# / NAME /
# | |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | TYPE |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | CLASS |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | TTL |
# | |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | RDLENGTH |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
# / RDATA /
# / /
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# resource record
# 1 1 1 1 1 1
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | |
# / /
# / NAME /
# | |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | TYPE |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | CLASS |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | TTL |
# | |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | RDLENGTH |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
# / RDATA /
# / /
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
def
unpack_address_reply
(
r
):
ancount
=
(
ord
(
r
[
6
])
<<
8
)
+
(
ord
(
r
[
7
]))
...
...
@@ -183,18 +183,18 @@ def unpack_ptr_reply (r):
return
0
,
None
# This is a UDP (datagram) resolver.
# This is a UDP (datagram) resolver.
#
# It may be useful to implement a TCP resolver. This would presumably
# give us more reliable behavior when things get too busy. A TCP
# client would have to manage the connection carefully, since the
# server is allowed to close it at will (the RFC recommends closing
# after 2 minutes of idle time).
#
# Note also that the TCP client will have to prepend each request
# with a 2-byte length indicator (see rfc1035).
#
#
# It may be useful to implement a TCP resolver. This would presumably
# give us more reliable behavior when things get too busy. A TCP
# client would have to manage the connection carefully, since the
# server is allowed to close it at will (the RFC recommends closing
# after 2 minutes of idle time).
#
# Note also that the TCP client will have to prepend each request
# with a 2-byte length indicator (see rfc1035).
#
class
resolver
(
asyncore
.
dispatcher
):
id
=
counter
()
...
...
@@ -366,28 +366,28 @@ class caching_resolver (resolver):
+
'<br>Cache Hits: %s'
%
self
.
cache_hits
)
#test_reply = """\000\000\205\200\000\001\000\001\000\002\000\002\006squirl\011nightmare\003com\000\000\001\000\001\300\014\000\001\000\001\000\001Q\200\000\004\315\240\260\005\011nightmare\003com\000\000\002\000\001\000\001Q\200\000\002\300\014\3006\000\002\000\001\000\001Q\200\000\015\003ns1\003iag\003net\000\300\014\000\001\000\001\000\001Q\200\000\004\315\240\260\005\300]\000\001\000\001\000\000\350\227\000\004\314\033\322\005"""
# def test_unpacker ():
# print unpack_address_reply (test_reply)
#
# import time
# class timer:
# def __init__ (self):
# self.start = time.time()
# def end (self):
# return time.time() - self.start
#
# # I get ~290 unpacks per second for the typical case, compared to ~48
# # using dnslib directly. also, that latter number does not include
# # picking the actual data out.
#
# def benchmark_unpacker():
#
# r = range(1000)
# t = timer()
# for i in r:
# unpack_address_reply (test_reply)
# print '%.2f unpacks per second' % (1000.0 / t.end())
#test_reply = """\000\000\205\200\000\001\000\001\000\002\000\002\006squirl\011nightmare\003com\000\000\001\000\001\300\014\000\001\000\001\000\001Q\200\000\004\315\240\260\005\011nightmare\003com\000\000\002\000\001\000\001Q\200\000\002\300\014\3006\000\002\000\001\000\001Q\200\000\015\003ns1\003iag\003net\000\300\014\000\001\000\001\000\001Q\200\000\004\315\240\260\005\300]\000\001\000\001\000\000\350\227\000\004\314\033\322\005"""
# def test_unpacker ():
# print unpack_address_reply (test_reply)
#
# import time
# class timer:
# def __init__ (self):
# self.start = time.time()
# def end (self):
# return time.time() - self.start
#
# # I get ~290 unpacks per second for the typical case, compared to ~48
# # using dnslib directly. also, that latter number does not include
# # picking the actual data out.
#
# def benchmark_unpacker():
#
# r = range(1000)
# t = timer()
# for i in r:
# unpack_address_reply (test_reply)
# print '%.2f unpacks per second' % (1000.0 / t.end())
if
__name__
==
'__main__'
:
import
sys
...
...
lib/python/ZServer/medusa/rpc_client.py
View file @
b9e5da32
...
...
@@ -47,16 +47,16 @@ import errno
class
RPC_Error
(
exceptions
.
StandardError
):
pass
# ===========================================================================
# RPC Client
# ===========================================================================
# ===========================================================================
# RPC Client
# ===========================================================================
# request types:
# 0 call
# 1 getattr
# 2 setattr
# 3 repr
# 4 del
# request types:
# 0 call
# 1 getattr
# 2 setattr
# 3 repr
# 4 del
class
rpc_proxy
:
...
...
@@ -187,9 +187,9 @@ def rpc_connect (address = ('localhost', 8746)):
rpc_connection
.
cache
[
address
]
=
rpc_proxy
(
conn
,
oid
)
return
rpc_connection
.
cache
[
address
]
# ===========================================================================
# fastrpc client
# ===========================================================================
# ===========================================================================
# fastrpc client
# ===========================================================================
class
fastrpc_proxy
:
...
...
@@ -224,9 +224,9 @@ def fastrpc_connect (address = ('localhost', 8748)):
rpc_connection
.
cache
[
address
]
=
fastrpc_proxy
(
conn
)
return
rpc_connection
.
cache
[
address
]
# ===========================================================================
# async fastrpc client
# ===========================================================================
# ===========================================================================
# async fastrpc client
# ===========================================================================
import
asynchat
import
fifo
...
...
lib/python/ZServer/medusa/rpc_server.py
View file @
b9e5da32
...
...
@@ -202,21 +202,21 @@ class rpc_server (asyncore.dispatcher):
rpc_channel
(
self
.
root
,
conn
,
addr
)
# ===========================================================================
# Fast RPC server
# ===========================================================================
# no proxies, request consists
# of a 'chain' of getattrs terminated by a __call__.
# Protocol:
# <path>.<to>.<object> ( <param1>, <param2>, ... )
# => ( <value1>, <value2>, ... )
#
#
# (<path>, <params>)
# path: tuple of strings
# params: tuple of objects
# ===========================================================================
# Fast RPC server
# ===========================================================================
# no proxies, request consists
# of a 'chain' of getattrs terminated by a __call__.
# Protocol:
# <path>.<to>.<object> ( <param1>, <param2>, ... )
# => ( <value1>, <value2>, ... )
#
#
# (<path>, <params>)
# path: tuple of strings
# params: tuple of objects
class
fastrpc_channel
(
asynchat
.
async_chat
):
...
...
@@ -285,7 +285,7 @@ class fastrpc_server (asyncore.dispatcher):
conn
,
addr
=
self
.
accept
()
fastrpc_channel
(
self
.
root
,
conn
,
addr
)
# ===========================================================================
# ===========================================================================
if
__name__
==
'__main__'
:
...
...
lib/python/ZServer/medusa/script_handler.py
View file @
b9e5da32
lib/python/ZServer/medusa/script_handler_demo/form.mpy
View file @
b9e5da32
lib/python/ZServer/medusa/script_handler_demo/persistent.py
View file @
b9e5da32
lib/python/ZServer/medusa/script_handler_demo/today.mpy
View file @
b9e5da32
lib/python/ZServer/medusa/sendfile/asynchat_sendfile.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
RCS_ID
=
'$Id: asynchat_sendfile.py,v 1.
2 2001/04/25 19:09:54
andreas Exp $'
RCS_ID
=
'$Id: asynchat_sendfile.py,v 1.
3 2001/05/01 11:45:27
andreas Exp $'
import
sendfile
import
asynchat
...
...
@@ -49,9 +49,9 @@ class async_chat_with_sendfile (async_chat):
if
callback
is
not
None
:
callback
(
0
,
fd
)
# here's how you might use this:
# fd = os.open (filename, os.O_RDONLY, 0644)
# size = os.lseek (fd, 0, 2)
# os.lseek (fd, 0, 0)
# self.push ('%08x' % size)
# self.push_sendfile (fd, 0, size)
# here's how you might use this:
# fd = os.open (filename, os.O_RDONLY, 0644)
# size = os.lseek (fd, 0, 2)
# os.lseek (fd, 0, 0)
# self.push ('%08x' % size)
# self.push_sendfile (fd, 0, size)
lib/python/ZServer/medusa/sendfile/test_sendfile.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
RCS_ID
=
'$Id: test_sendfile.py,v 1.
2 2001/04/25 19:09:54
andreas Exp $'
RCS_ID
=
'$Id: test_sendfile.py,v 1.
3 2001/05/01 11:45:27
andreas Exp $'
import
asyncore
import
os
...
...
lib/python/ZServer/medusa/start_medusa.py
View file @
b9e5da32
...
...
@@ -115,13 +115,13 @@ if os.name == 'posix':
uh
=
unix_user_handler
.
unix_user_handler
(
'public_html'
)
hs
.
install_handler
(
uh
)
# ===========================================================================
# FTP Server
# ===========================================================================
# ===========================================================================
# FTP Server
# ===========================================================================
# Here we create an 'anonymous' ftp server.
# Note: the ftp server is read-only by default. [in this mode, all
# 'write-capable' commands are unavailable]
# Here we create an 'anonymous' ftp server.
# Note: the ftp server is read-only by default. [in this mode, all
# 'write-capable' commands are unavailable]
ftp
=
ftp_server
.
ftp_server
(
ftp_server
.
anon_authorizer
(
...
...
@@ -192,7 +192,7 @@ if os.name == 'posix':
os
.
setegid
(
gid
)
os
.
seteuid
(
uid
)
# Finally, start up the server loop! This loop will not exit until
# all clients and servers are closed. You may cleanly shut the system
# down by sending SIGINT (a.k.a. KeyboardInterrupt).
# Finally, start up the server loop! This loop will not exit until
# all clients and servers are closed. You may cleanly shut the system
# down by sending SIGINT (a.k.a. KeyboardInterrupt).
asyncore
.
loop
()
lib/python/ZServer/medusa/status_handler.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
VERSION_STRING
=
"$Id: status_handler.py,v 1.
6 2001/04/25 19:07:34
andreas Exp $"
VERSION_STRING
=
"$Id: status_handler.py,v 1.
7 2001/05/01 11:44:49
andreas Exp $"
#
# medusa status extension
...
...
@@ -215,7 +215,7 @@ class channel_list_producer (lines_producer):
)
# this really needs a full-blown quoter...
# this really needs a full-blown quoter...
def
sanitize
(
s
):
if
'<'
in
s
:
s
=
string
.
join
(
string
.
split
(
s
,
'<'
),
'<'
)
...
...
@@ -238,11 +238,11 @@ def html_reprs (list, front='', back=''):
reprs
.
sort
()
return
reprs
# for example, tera, giga, mega, kilo
# p_d (n, (1024, 1024, 1024, 1024))
# smallest divider goes first - for example
# minutes, hours, days
# p_d (n, (60, 60, 24))
# for example, tera, giga, mega, kilo
# p_d (n, (1024, 1024, 1024, 1024))
# smallest divider goes first - for example
# minutes, hours, days
# p_d (n, (60, 60, 24))
def
progressive_divide
(
n
,
parts
):
result
=
[]
...
...
@@ -252,7 +252,7 @@ def progressive_divide (n, parts):
result
.
append
(
n
)
return
result
# b,k,m,g,t
# b,k,m,g,t
def
split_by_units
(
n
,
units
,
dividers
,
format_string
):
divs
=
progressive_divide
(
n
,
dividers
)
result
=
[]
...
...
lib/python/ZServer/medusa/test/asyn_http_bench.py
View file @
b9e5da32
...
...
@@ -28,17 +28,17 @@ class http_client (asyncore.dispatcher_with_send):
def
handle_connect
(
self
):
self
.
connected
=
1
# blurt ('o')
# blurt ('o')
self
.
send
(
'GET %s HTTP/1.0
\
r
\
n
\
r
\
n
'
%
self
.
uri
)
def
handle_read
(
self
):
# blurt ('.')
# blurt ('.')
d
=
self
.
recv
(
8192
)
self
.
bytes
=
self
.
bytes
+
len
(
d
)
def
handle_close
(
self
):
global
total_sessions
# blurt ('(%d)' % (self.bytes))
# blurt ('(%d)' % (self.bytes))
self
.
close
()
total_sessions
=
total_sessions
+
1
if
self
.
num
:
...
...
@@ -89,10 +89,10 @@ if __name__ == '__main__':
print
'Max. number of concurrent sessions: %d'
%
(
MAX
)
# linux 2.x, talking to medusa
# 50 clients
# 1000 hits/client
# total_hits:50000
# 2255.858 seconds
# total hits/sec:22.165
# Max. number of concurrent sessions: 50
# linux 2.x, talking to medusa
# 50 clients
# 1000 hits/client
# total_hits:50000
# 2255.858 seconds
# total hits/sec:22.165
# Max. number of concurrent sessions: 50
lib/python/ZServer/medusa/test/max_sockets.py
View file @
b9e5da32
lib/python/ZServer/medusa/test/test_11.py
View file @
b9e5da32
lib/python/ZServer/medusa/test/test_lb.py
View file @
b9e5da32
...
...
@@ -62,12 +62,12 @@ class test_server (asyncore.dispatcher):
conn
,
addr
=
self
.
accept
()
test_channel
(
conn
,
addr
)
# ==================================================
# client
# ==================================================
# ==================================================
# client
# ==================================================
# pretty much the same behavior, except that we kick
# off the exchange and decide when to quit
# pretty much the same behavior, except that we kick
# off the exchange and decide when to quit
class
test_client
(
test_channel
):
...
...
lib/python/ZServer/medusa/test/test_medusa.py
View file @
b9e5da32
lib/python/ZServer/medusa/test/test_single_11.py
View file @
b9e5da32
lib/python/ZServer/medusa/thread/pi_module.py
View file @
b9e5da32
lib/python/ZServer/medusa/thread/select_trigger.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
VERSION_STRING
=
"$Id: select_trigger.py,v 1.
2 2001/04/25 19:09:56
andreas Exp $"
VERSION_STRING
=
"$Id: select_trigger.py,v 1.
3 2001/05/01 11:45:27
andreas Exp $"
import
asyncore
import
asynchat
...
...
lib/python/ZServer/medusa/thread/test_module.py
View file @
b9e5da32
lib/python/ZServer/medusa/thread/thread_channel.py
View file @
b9e5da32
# -*- Mode: Python; tab-width: 4 -*-
VERSION_STRING
=
"$Id: thread_channel.py,v 1.
2 2001/04/25 19:09:56
andreas Exp $"
VERSION_STRING
=
"$Id: thread_channel.py,v 1.
3 2001/05/01 11:45:27
andreas Exp $"
# This will probably only work on Unix.
...
...
@@ -72,7 +72,7 @@ class thread_channel (asyncore.file_dispatcher):
# the parent channel here.
self
.
close
()
# Yeah, it's bad when the test code is bigger than the library code.
# Yeah, it's bad when the test code is bigger than the library code.
if
__name__
==
'__main__'
:
...
...
lib/python/ZServer/medusa/thread/thread_handler.py
View file @
b9e5da32
...
...
@@ -320,9 +320,9 @@ class request_loop_thread (threading.Thread):
function
(
env
,
stdin
,
stdout
)
stdout
.
close
()
# ===========================================================================
# Testing
# ===========================================================================
# ===========================================================================
# Testing
# ===========================================================================
if
__name__
==
'__main__'
:
...
...
lib/python/ZServer/medusa/unix_user_handler.py
View file @
b9e5da32
...
...
@@ -5,7 +5,7 @@
# All Rights Reserved.
#
RCS_ID
=
'$Id: unix_user_handler.py,v 1.
2 2001/04/25 19:07:34
andreas Exp $'
RCS_ID
=
'$Id: unix_user_handler.py,v 1.
3 2001/05/01 11:44:49
andreas Exp $'
# support for `~user/public_html'.
...
...
lib/python/ZServer/medusa/virtual_handler.py
View file @
b9e5da32
lib/python/ZServer/medusa/xmlrpc_handler.py
View file @
b9e5da32
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment