You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mod_ftp-commits@incubator.apache.org by ji...@apache.org on 2005/10/06 13:17:04 UTC
svn commit: r306631 [7/8] - in /incubator/mod_ftp/trunk: ./ conf/ docs/
include/ modules/ patches/ src/ tests/ tests/conf/ tests/logs/ tests/tests/
utils/ utils/ftp_proxy/ utils/static_build/ utils/stresstest/
Added: incubator/mod_ftp/trunk/src/mod_ftp.dsp
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/src/mod_ftp.dsp?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/src/mod_ftp.dsp (added)
+++ incubator/mod_ftp/trunk/src/mod_ftp.dsp Thu Oct 6 06:16:28 2005
@@ -0,0 +1,188 @@
+# Microsoft Developer Studio Project File - Name="mod_ftp" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_ftp - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_ftp.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_ftp.mak" CFG="mod_ftp - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_ftp - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_ftp - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_ftp - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "SRC_EXPORTS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /I "../include" /I "$(APACHE_TMPINSTALL_WINNT)/include" /D "FTP_NO_GLOB" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "FTP_DECLARE_EXPORT" /Fd"Release/mod_ftp" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /dll /machine:I386
+# ADD LINK32 libapr.lib libhttpd.lib libaprutil.lib wsock32.lib /nologo /dll /debug /machine:I386 /out:"Release/mod_ftp.so" /libpath:"$(APACHE_TMPINSTALL_WINNT)\lib" /base:@"$(SRCROOT)/dev-bin/cov_dll.ref",ftp_module
+
+!ELSEIF "$(CFG)" == "mod_ftp - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SRC_EXPORTS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../include" /I "$(APACHE_TMPINSTALL_WINNT)/include" /D "FTP_NO_GLOB" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "FTP_DECLARE_EXPORT" /Fd"Debug\mod_ftp" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libapr.lib libhttpd.lib libaprutil.lib wsock32.lib /nologo /dll /debug /machine:I386 /out:"Debug/mod_ftp.so" /libpath:"$(APACHE_TMPINSTALL_WINNT)\lib" /base:@"$(SRCROOT)/dev-bin/cov_dll.ref",ftp_module
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_ftp - Win32 Release"
+# Name "mod_ftp - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\ftp_commands.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ftp_connection.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ftp_data_connection.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ftp_data_filters.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ftp_filters.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ftp_inet_pton.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ftp_limitlogin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ftp_log.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ftp_message.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ftp_protocol.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ftp_request.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ftp_util.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mod_ftp.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\include\ftp_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\mod_ftp.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE="..\config-win32.awk"
+
+!IF "$(CFG)" == "mod_ftp - Win32 Release"
+
+USERDEP__CONFI="..\configure.in"
+# Begin Custom Build - Generating ftp_config.h
+InputPath="..\config-win32.awk"
+
+"..\include\ftp_config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f $(InputPath) < ..\configure.in > ..\include\ftp_config.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "mod_ftp - Win32 Debug"
+
+USERDEP__CONFI="..\configure.in"
+# Begin Custom Build - Generating ftp_config.h
+InputPath="..\config-win32.awk"
+
+"..\include\ftp_config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f $(InputPath) < ..\configure.in > ..\include\ftp_config.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
Propchange: incubator/mod_ftp/trunk/src/mod_ftp.dsp
------------------------------------------------------------------------------
svn:eol-style = CRLF
Added: incubator/mod_ftp/trunk/src/remake_ftp_protocol
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/src/remake_ftp_protocol?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/src/remake_ftp_protocol (added)
+++ incubator/mod_ftp/trunk/src/remake_ftp_protocol Thu Oct 6 06:16:28 2005
@@ -0,0 +1,75 @@
+#!/usr/bin/perl
+# $Date: 2002/01/02 19:14:54 $ $Id: remake_ftp_protocol,v 1.6 2002/01/02 19:14:54 rmorgan Exp $
+#
+$SRCDIR="\.\.";
+
+open FHREPLY,"$SRCDIR/include/mod_ftp.h"
+ or die "Cannot open FTP its mod_ftp.h: $!";
+open FHCOMMAND,"$SRCDIR/src/ftp_commands.c"
+ or die "Cannot open FTP its ftp_commands.c: $!";
+
+$t=scalar(gmtime(time));
+$nr_of_resp = 0;
+$nr_of_req = 0;
+
+print qq|/* ftp_protocol.h
+ *
+ * Dynamicaly generated FTP request types and response types.
+ *
+ * Do not edit manually; but delete the file and do
+ * another gmake (or a make ftp_protocol.h)
+ *
+ * Generated from $SRCDIR on
+ * $t
+ */
+|;
+
+while(<FHREPLY>) {
+ next unless m/^\#define/;
+ if (m/^\#define\s+FTP_REPLY_(\w+)\s*(\d+)/) {
+ $p{ $2 } = $1;
+ $nr_of_resp++;
+ };
+};
+
+@resp = ();
+
+while(<FHCOMMAND>) {
+ next unless m/\s*ftp_hook_cmd\(\"/;
+ if (m/\s*ftp_hook_cmd\(\"/) {
+ $nr_of_req++;
+ s/\s*ftp_hook_cmd\(\"//g;
+ s/\"(.+)//g;
+ chop;
+ push (@resp, $_);
+ };
+};
+
+
+
+print qq|
+
+#define WWW_MIB_TOTAL_FTP_RESPONSES $nr_of_resp
+
+const int ftp_response_types[] = {
+ |;
+
+map {
+ print "$_, ";
+ } sort { $a <=> $b } keys %p;
+
+print qq|0 };
+
+#define WWW_MIB_TOTAL_FTP_REQUESTS $nr_of_req
+
+const char *ftp_request_types[] ={
+ |;
+map {
+ print "\"$_\", ";
+ } sort {
+ $x = length($a) <=> length($b);
+ return $x ? $x : (uc $a cmp uc $b);
+ } @resp;
+print "NULL };
+
+";
Propchange: incubator/mod_ftp/trunk/src/remake_ftp_protocol
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/stamp-h.in
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/stamp-h.in?rev=306631&view=auto
==============================================================================
(empty)
Added: incubator/mod_ftp/trunk/tests/.cvsignore
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/.cvsignore?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/.cvsignore (added)
+++ incubator/mod_ftp/trunk/tests/.cvsignore Thu Oct 6 06:16:28 2005
@@ -0,0 +1,10 @@
+Makefile
+Makefile.in
+apachetest.py
+pytest.py
+pytest.pyc
+server_config.py
+server_config.pyc
+test.out
+test.err
+htdocs
Propchange: incubator/mod_ftp/trunk/tests/.cvsignore
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/Makefile.in
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/Makefile.in?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/Makefile.in (added)
+++ incubator/mod_ftp/trunk/tests/Makefile.in Thu Oct 6 06:16:28 2005
@@ -0,0 +1,12 @@
+check:
+ @-mkdir -p logs htdocs > /dev/null 2>&1
+ @python apachetest.py @TESTBIN@ @PYTESTDIR@/conf/httpd.conf
+
+clean:
+ true
+
+install:
+ true
+
+all:
+ true
Propchange: incubator/mod_ftp/trunk/tests/Makefile.in
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/apachetest.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/apachetest.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/apachetest.py (added)
+++ incubator/mod_ftp/trunk/tests/apachetest.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,191 @@
+#
+# WARNING: This file lives in handy/pytest and is copied over during the
+# configuration process. Changes to the file after it has been copied
+# will be lost!
+#
+
+import signal, os, re, time, sys, StringIO, popen2
+from pytest import Tester
+from string import *
+
+class ApacheTester(Tester):
+ def __init__(self, log_file, apachebin, apacheconf, errfile='test.err'):
+ self.apachebin = apachebin
+ self.apacheconf = apacheconf
+ self.serverroot = self.find_serverroot()
+ self.pidfile = self.find_pidfile()
+ self.maxline = 50
+ self.ntests = 0
+ self.nsuccess = 0
+ self.log_buf = StringIO.StringIO()
+ self.log_real = log_file
+ self.apacheinfo = ''
+ self.teststart = None
+ self.testend = None
+ self.errfile = errfile
+
+ Tester.__init__(self, self.log_buf)
+
+ def snag_take1(self, directive):
+ my_re = re.compile('%s[ \t](("[^"]*")|([^ \t\r\n]*))' % directive,
+ re.IGNORECASE)
+ for line in open(self.apacheconf, 'r').readlines():
+ m = my_re.match(line)
+ if m:
+ res = m.groups(2)[0]
+ if res[:1] == '"':
+ return res[1:-1]
+ else:
+ return res
+ return None
+
+ def find_serverroot(self):
+ return self.snag_take1('serverroot')
+
+ def find_pidfile(self):
+ return self.snag_take1('serverroot') + '/' + self.snag_take1('pidfile')
+
+ def end_testsuite(self):
+ self.testend = time.time()
+ self.stop_server()
+ self.log_buf.seek(0)
+ self.log_real.write(self.generate_summary())
+ self.log_real.write(self.log_buf.read())
+
+ def begin_testsuite(self):
+ self.teststart = time.time()
+ self.apacheinfo = os.popen('%s -v' % self.apachebin, 'r').read() + '\n'
+ print self.apacheinfo
+
+ self.start_server()
+
+ def start_server(self):
+ pidfile = self.pidfile
+ try: os.unlink(pidfile)
+ except: pass
+
+ cmdline = "%s -f %s 2>>%s" % (self.apachebin, self.apacheconf,
+ self.errfile)
+ #print cmdline
+ if os.system(cmdline):
+ raise 'Error starting server'
+
+ for i in range(100):
+ try:
+ x = open(pidfile, 'r')
+ except:
+ x = None
+ time.sleep(1)
+ if not x: continue
+ else: break
+
+ if not x:
+ raise 'Error starting server'
+
+ def stop_server(self):
+ try:
+ pid = int(open(self.pidfile, 'r').read())
+ except:
+ return
+
+ while 1: # KILL IT TILL ITS DEAD!
+ try:
+ os.kill(pid, signal.SIGTERM)
+ except:
+ break
+
+ def create_nicedoc(self, docstr):
+ res = []
+ words = split(docstr)
+ linelen = 0
+ for word in words:
+ if not linelen:
+ linelen = linelen + 1
+
+ res.append(word + ' ')
+ linelen = linelen + 1 + len(word)
+ if linelen > self.maxline:
+ linelen = 0
+ res.append('\n')
+
+ return split(join(res, ''), '\n')
+
+ def generate_test_header(self, testname, success, nicedoc=None):
+ if success:
+ sucstring = 'Success'
+ else:
+ sucstring = 'FAILURE'
+
+ header = [ 'Test: ' + testname,
+ 'Time: ' + time.ctime(time.time()),
+ 'Result: ' + sucstring ]
+
+ if nicedoc:
+ header.append('Info: ' + nicedoc[0])
+ nicedoc = map(lambda x: '%-8s%s' % (' ', x), nicedoc)
+ header.extend(nicedoc[1:])
+
+ return self.boxulate(header) + '\n'
+
+ def run_test(self, testname, fn):
+ self.ntests = self.ntests + 1
+ test_buf = StringIO.StringIO()
+
+ sys.stdout.write('%-30s: ' % testname)
+ sys.stdout.flush()
+ nicedoc = None
+ if fn.__doc__:
+ nicedoc = self.create_nicedoc(fn.__doc__)
+
+ if Tester.run_test(self, testname, fn, self, test_buf):
+ print 'Failure'
+ success = 0
+ else:
+ print 'Success'
+ self.nsuccess = self.nsuccess + 1
+ success = 1
+
+ test_buf.seek(0)
+ self.write_log(self.generate_test_header(testname, success, nicedoc))
+ self.write_log(test_buf.read())
+
+
+ def generate_summary(self):
+ if not self.ntests:
+ percsucc = 'Unknown'
+ else:
+ percsucc = '%.2f' % (self.nsuccess * 100 / self.ntests,)
+
+ docinfo = ['Testsuite Summary','',
+ 'Start Time: ' + time.ctime(self.teststart),
+ 'End Time: ' + time.ctime(self.testend),
+ '# Tests: ' + `self.ntests`,
+ '# Success: ' + `self.nsuccess`,
+ '% Success: ' + percsucc]
+
+ return self.boxulate(docinfo)
+
+
+if __name__ == '__main__':
+ import sys, os
+
+ sys.path.append('tests')
+ for i in ('test.out', 'test.err'):
+ try:
+ os.unlink(i)
+ except:
+ pass
+
+ x = ApacheTester(open('test.out', 'w'), sys.argv[1], sys.argv[2],
+ 'test.err')
+ tests = os.listdir('tests')
+ tests.sort()
+ for fname in tests:
+ if fname[-3:] != '.py': continue
+ mod = __import__(fname[:-3], {}, {}, [])
+ x.run_test(fname[:-3], mod.test)
+
+ x.end_testsuite()
+
+ path = os.getcwd()
+ print '\nSee results in ' + os.path.join(path, 'test.out') + '\n'
Propchange: incubator/mod_ftp/trunk/tests/apachetest.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/conf/.cvsignore
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/conf/.cvsignore?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/conf/.cvsignore (added)
+++ incubator/mod_ftp/trunk/tests/conf/.cvsignore Thu Oct 6 06:16:28 2005
@@ -0,0 +1,4 @@
+httpd.conf
+httpd.conf.in
+loadmodules.conf
+mime.types
Propchange: incubator/mod_ftp/trunk/tests/conf/.cvsignore
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/conf/httpd.conf.in
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/conf/httpd.conf.in?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/conf/httpd.conf.in (added)
+++ incubator/mod_ftp/trunk/tests/conf/httpd.conf.in Thu Oct 6 06:16:28 2005
@@ -0,0 +1,83 @@
+ServerRoot "@PYTESTDIR@"
+PidFile logs/httpd.pid
+
+<IfModule !dexter.c>
+ScoreBoardFile logs/apache_scoreboard
+</IfModule>
+
+Timeout 300
+KeepAlive On
+MaxKeepAliveRequests 100
+KeepAliveTimeout 15
+
+<IfModule prefork.c>
+StartServers 5
+MinSpareServers 5
+MaxSpareServers 10
+MaxClients 20
+MaxRequestsPerChild 0
+</IfModule>
+
+<IfModule mpmt_pthread.c>
+StartServers 5
+MaxClients 8
+MinSpareThreads 5
+MaxSpareThreads 10
+ThreadsPerChild 20
+MaxRequestsPerChild 0
+</IfModule>
+
+<IfModule dexter.c>
+NumServers 5
+StartThreads 5
+MinSpareThreads 5
+MaxSpareThreads 10
+MaxThreadsPerChild 20
+MaxRequestsPerChild 0
+</IfModule>
+
+Include "@PYTESTDIR@/conf/loadmodules.conf"
+
+Listen 12345
+Listen 12346
+ServerAdmin you@your.address
+DocumentRoot "@PYTESTDIR@/htdocs"
+
+<Directory />
+ Options FollowSymLinks
+ AllowOverride None
+</Directory>
+
+<Directory "@PYTESTDIR@/htdocs">
+ Options Indexes FollowSymLinks
+ AllowOverride AuthConfig
+ Order allow,deny
+ Allow from all
+</Directory>
+
+DirectoryIndex index.html
+AccessFileName .htaccess
+<Files ~ "^\.ht">
+ Order allow,deny
+ Deny from all
+</Files>
+
+UseCanonicalName On
+TypesConfig conf/mime.types
+DefaultType text/plain
+
+<IfModule mod_mime_magic.c>
+ MIMEMagicFile conf/magic
+</IfModule>
+
+HostnameLookups Off
+ErrorLog logs/error_log
+LogLevel warn
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+CustomLog logs/access_log common
+ServerSignature On
+
+BrowserMatch "Mozilla/2" nokeepalive
+BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
+
+Include "@PYTESTDIR@/conf/mod_specs.conf"
Propchange: incubator/mod_ftp/trunk/tests/conf/httpd.conf.in
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/conf/loadmodules.conf.in
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/conf/loadmodules.conf.in?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/conf/loadmodules.conf.in (added)
+++ incubator/mod_ftp/trunk/tests/conf/loadmodules.conf.in Thu Oct 6 06:16:28 2005
@@ -0,0 +1 @@
+LoadModule ftp_module @FTPDIR@/src/.libs/libmod_ftp.so
Propchange: incubator/mod_ftp/trunk/tests/conf/loadmodules.conf.in
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/conf/mime.types
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/conf/mime.types?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/conf/mime.types (added)
+++ incubator/mod_ftp/trunk/tests/conf/mime.types Thu Oct 6 06:16:28 2005
@@ -0,0 +1,428 @@
+# This is a comment. I love comments.
+
+# This file controls what Internet media types are sent to the client for
+# given file extension(s). Sending the correct media type to the client
+# is important so they know how to handle the content of the file.
+# Extra types can either be added here or by using an AddType directive
+# in your config files. For more information about Internet media types,
+# please read RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type
+# registry is at <ftp://ftp.iana.org/in-notes/iana/assignments/media-types/>.
+
+# MIME type Extension
+application/EDI-Consent
+application/EDI-X12
+application/EDIFACT
+application/activemessage
+application/andrew-inset ez
+application/applefile
+application/atomicmail
+application/batch-SMTP
+application/cals-1840
+application/commonground
+application/cybercash
+application/dca-rft
+application/dec-dx
+application/eshop
+application/http
+application/hyperstudio
+application/iges
+application/index
+application/index.cmd
+application/index.obj
+application/index.response
+application/index.vnd
+application/iotp
+application/ipp
+application/mac-binhex40 hqx
+application/mac-compactpro cpt
+application/macwriteii
+application/marc
+application/mathematica
+application/mathematica-old
+application/msword doc
+application/news-message-id
+application/news-transmission
+application/ocsp-request
+application/ocsp-response
+application/octet-stream bin dms lha lzh exe class so dll
+application/oda oda
+application/pdf pdf
+application/pgp-encrypted
+application/pgp-keys
+application/pgp-signature
+application/pkcs10
+application/pkcs7-mime
+application/pkcs7-signature
+application/pkix-cert
+application/pkix-crl
+application/pkixcmp
+application/postscript ai eps ps
+application/prs.alvestrand.titrax-sheet
+application/prs.cww
+application/prs.nprend
+application/remote-printing
+application/riscos
+application/sdp
+application/set-payment
+application/set-payment-initiation
+application/set-registration
+application/set-registration-initiation
+application/sgml
+application/sgml-open-catalog
+application/slate
+application/smil smi smil
+application/vemmi
+application/vnd.3M.Post-it-Notes
+application/vnd.FloGraphIt
+application/vnd.accpac.simply.aso
+application/vnd.accpac.simply.imp
+application/vnd.acucobol
+application/vnd.anser-web-certificate-issue-initiation
+application/vnd.anser-web-funds-transfer-initiation
+application/vnd.audiograph
+application/vnd.businessobjects
+application/vnd.bmi
+application/vnd.canon-cpdl
+application/vnd.canon-lips
+application/vnd.claymore
+application/vnd.commerce-battelle
+application/vnd.commonspace
+application/vnd.comsocaller
+application/vnd.contact.cmsg
+application/vnd.cosmocaller
+application/vnd.cups-postscript
+application/vnd.cups-raster
+application/vnd.cups-raw
+application/vnd.ctc-posml
+application/vnd.cybank
+application/vnd.dna
+application/vnd.dpgraph
+application/vnd.dxr
+application/vnd.ecdis-update
+application/vnd.ecowin.chart
+application/vnd.ecowin.filerequest
+application/vnd.ecowin.fileupdate
+application/vnd.ecowin.series
+application/vnd.ecowin.seriesrequest
+application/vnd.ecowin.seriesupdate
+application/vnd.enliven
+application/vnd.epson.esf
+application/vnd.epson.msf
+application/vnd.epson.quickanime
+application/vnd.epson.salt
+application/vnd.epson.ssf
+application/vnd.ericsson.quickcall
+application/vnd.eudora.data
+application/vnd.fdf
+application/vnd.ffsns
+application/vnd.framemaker
+application/vnd.fujitsu.oasys
+application/vnd.fujitsu.oasys2
+application/vnd.fujitsu.oasys3
+application/vnd.fujitsu.oasysgp
+application/vnd.fujitsu.oasysprs
+application/vnd.fujixerox.ddd
+application/vnd.fujixerox.docuworks
+application/vnd.fujixerox.docuworks.binder
+application/vnd.fut-misnet
+application/vnd.grafeq
+application/vnd.groove-account
+application/vnd.groove-identity-message
+application/vnd.groove-injector
+application/vnd.groove-tool-message
+application/vnd.groove-tool-template
+application/vnd.groove-vcard
+application/vnd.hp-HPGL
+application/vnd.hp-PCL
+application/vnd.hp-PCLXL
+application/vnd.hp-hpid
+application/vnd.hp-hps
+application/vnd.httphone
+application/vnd.hzn-3d-crossword
+application/vnd.ibm.MiniPay
+application/vnd.ibm.modcap
+application/vnd.informix-visionary
+application/vnd.intercon.formnet
+application/vnd.intertrust.digibox
+application/vnd.intertrust.nncp
+application/vnd.intu.qbo
+application/vnd.intu.qfx
+application/vnd.is-xpr
+application/vnd.japannet-directory-service
+application/vnd.japannet-jpnstore-wakeup
+application/vnd.japannet-payment-wakeup
+application/vnd.japannet-registration
+application/vnd.japannet-registration-wakeup
+application/vnd.japannet-setstore-wakeup
+application/vnd.japannet-verification
+application/vnd.japannet-verification-wakeup
+application/vnd.koan
+application/vnd.lotus-1-2-3
+application/vnd.lotus-approach
+application/vnd.lotus-freelance
+application/vnd.lotus-notes
+application/vnd.lotus-organizer
+application/vnd.lotus-screencam
+application/vnd.lotus-wordpro
+application/vnd.mcd
+application/vnd.mediastation.cdkey
+application/vnd.meridian-slingshot
+application/vnd.mif mif
+application/vnd.minisoft-hp3000-save
+application/vnd.mitsubishi.misty-guard.trustweb
+application/vnd.mobius.daf
+application/vnd.mobius.dis
+application/vnd.mobius.msl
+application/vnd.mobius.plc
+application/vnd.mobius.txf
+application/vnd.motorola.flexsuite
+application/vnd.motorola.flexsuite.adsi
+application/vnd.motorola.flexsuite.fis
+application/vnd.motorola.flexsuite.gotap
+application/vnd.motorola.flexsuite.kmr
+application/vnd.motorola.flexsuite.ttc
+application/vnd.motorola.flexsuite.wem
+application/vnd.mozilla.xul+xml
+application/vnd.ms-artgalry
+application/vnd.ms-asf
+application/vnd.ms-excel xls
+application/vnd.ms-lrm
+application/vnd.ms-powerpoint ppt
+application/vnd.ms-project
+application/vnd.ms-tnef
+application/vnd.ms-works
+application/vnd.msign
+application/vnd.music-niff
+application/vnd.musician
+application/vnd.netfpx
+application/vnd.noblenet-directory
+application/vnd.noblenet-sealer
+application/vnd.noblenet-web
+application/vnd.novadigm.EDM
+application/vnd.novadigm.EDX
+application/vnd.novadigm.EXT
+application/vnd.osa.netdeploy
+application/vnd.pg.format
+application/vnd.pg.osasli
+application/vnd.powerbuilder6
+application/vnd.powerbuilder6-s
+application/vnd.powerbuilder7
+application/vnd.powerbuilder7-s
+application/vnd.powerbuilder75
+application/vnd.powerbuilder75-s
+application/vnd.previewsystems.box
+application/vnd.publishare-delta-tree
+application/vnd.rapid
+application/vnd.s3sms
+application/vnd.seemail
+application/vnd.shana.informed.formdata
+application/vnd.shana.informed.formtemplate
+application/vnd.shana.informed.interchange
+application/vnd.shana.informed.package
+application/vnd.street-stream
+application/vnd.svd
+application/vnd.swiftview-ics
+application/vnd.triscape.mxs
+application/vnd.trueapp
+application/vnd.truedoc
+application/vnd.ufdl
+application/vnd.uplanet.alert
+application/vnd.uplanet.alert-wbxml
+application/vnd.uplanet.bearer-choi-wbxml
+application/vnd.uplanet.bearer-choice
+application/vnd.uplanet.cacheop
+application/vnd.uplanet.cacheop-wbxml
+application/vnd.uplanet.channel
+application/vnd.uplanet.channel-wbxml
+application/vnd.uplanet.list
+application/vnd.uplanet.list-wbxml
+application/vnd.uplanet.listcmd
+application/vnd.uplanet.listcmd-wbxml
+application/vnd.uplanet.signal
+application/vnd.vcx
+application/vnd.vectorworks
+application/vnd.visio
+application/vnd.wap.sic
+application/vnd.wap.slc
+application/vnd.wap.wbxml wbxml
+application/vnd.wap.wmlc wmlc
+application/vnd.wap.wmlscriptc wmlsc
+application/vnd.webturbo
+application/vnd.wrq-hp3000-labelled
+application/vnd.wt.stf
+application/vnd.xara
+application/vnd.xfdl
+application/vnd.yellowriver-custom-menu
+application/whoispp-query
+application/whoispp-response
+application/wita
+application/wordperfect5.1
+application/x-bcpio bcpio
+application/x-cdlink vcd
+application/x-chess-pgn pgn
+application/x-compress
+application/x-cpio cpio
+application/x-csh csh
+application/x-director dcr dir dxr
+application/x-dvi dvi
+application/x-futuresplash spl
+application/x-gtar gtar
+application/x-gzip
+application/x-hdf hdf
+application/x-javascript js
+application/x-koan skp skd skt skm
+application/x-latex latex
+application/x-netcdf nc cdf
+application/x-sh sh
+application/x-shar shar
+application/x-shockwave-flash swf
+application/x-stuffit sit
+application/x-sv4cpio sv4cpio
+application/x-sv4crc sv4crc
+application/x-tar tar
+application/x-tcl tcl
+application/x-tex tex
+application/x-texinfo texinfo texi
+application/x-troff t tr roff
+application/x-troff-man man
+application/x-troff-me me
+application/x-troff-ms ms
+application/x-ustar ustar
+application/x-wais-source src
+application/x400-bp
+application/xml
+application/zip zip
+audio/32kadpcm
+audio/basic au snd
+audio/l16
+audio/midi mid midi kar
+audio/mpeg mpga mp2 mp3
+audio/prs.sid
+audio/telephone-event
+audio/tone
+audio/vnd.cns.anp1
+audio/vnd.cns.inf1
+audio/vnd.digital-winds
+audio/vnd.everad.plj
+audio/vnd.lucent.voice
+audio/vnd.nortel.vbk
+audio/vnd.nuera.ecelp4800
+audio/vnd.nuera.ecelp7470
+audio/vnd.octel.sbc
+audio/vnd.qcelp
+audio/vnd.rhetorex.32kadpcm
+audio/vnd.vmx.cvsd
+audio/x-aiff aif aiff aifc
+audio/x-pn-realaudio ram rm
+audio/x-pn-realaudio-plugin rpm
+audio/x-realaudio ra
+audio/x-wav wav
+chemical/x-pdb pdb
+chemical/x-xyz xyz
+image/bmp bmp
+image/cgm
+image/g3fax
+image/gif gif
+image/ief ief
+image/jpeg jpeg jpg jpe
+image/naplps
+image/png png
+image/prs.btif
+image/prs.pti
+image/tiff tiff tif
+image/vnd.cns.inf2
+image/vnd.dwg
+image/vnd.dxf
+image/vnd.fastbidsheet
+image/vnd.fpx
+image/vnd.fst
+image/vnd.fujixerox.edmics-mmr
+image/vnd.fujixerox.edmics-rlc
+image/vnd.mix
+image/vnd.net-fpx
+image/vnd.svf
+image/vnd.wap.wbmp wbmp
+image/vnd.xiff
+image/x-cmu-raster ras
+image/x-portable-anymap pnm
+image/x-portable-bitmap pbm
+image/x-portable-graymap pgm
+image/x-portable-pixmap ppm
+image/x-rgb rgb
+image/x-xbitmap xbm
+image/x-xpixmap xpm
+image/x-xwindowdump xwd
+message/delivery-status
+message/disposition-notification
+message/external-body
+message/http
+message/news
+message/partial
+message/rfc822
+message/s-http
+model/iges igs iges
+model/mesh msh mesh silo
+model/vnd.dwf
+model/vnd.flatland.3dml
+model/vnd.gdl
+model/vnd.gs-gdl
+model/vnd.gtw
+model/vnd.mts
+model/vnd.vtu
+model/vrml wrl vrml
+multipart/alternative
+multipart/appledouble
+multipart/byteranges
+multipart/digest
+multipart/encrypted
+multipart/form-data
+multipart/header-set
+multipart/mixed
+multipart/parallel
+multipart/related
+multipart/report
+multipart/signed
+multipart/voice-message
+text/calendar
+text/css css
+text/directory
+text/enriched
+text/html html htm
+text/plain asc txt
+text/prs.lines.tag
+text/rfc822-headers
+text/richtext rtx
+text/rtf rtf
+text/sgml sgml sgm
+text/tab-separated-values tsv
+text/t140
+text/uri-list
+text/vnd.DMClientScript
+text/vnd.IPTC.NITF
+text/vnd.IPTC.NewsML
+text/vnd.abc
+text/vnd.curl
+text/vnd.flatland.3dml
+text/vnd.fly
+text/vnd.fmi.flexstor
+text/vnd.in3d.3dml
+text/vnd.in3d.spot
+text/vnd.latex-z
+text/vnd.motorola.reflex
+text/vnd.ms-mediapackage
+text/vnd.wap.si
+text/vnd.wap.sl
+text/vnd.wap.wml wml
+text/vnd.wap.wmlscript wmls
+text/x-setext etx
+text/xml xml
+video/mpeg mpeg mpg mpe
+video/pointer
+video/quicktime qt mov
+video/vnd.fvt
+video/vnd.motorola.video
+video/vnd.motorola.videop
+video/vnd.vivo
+video/x-msvideo avi
+video/x-sgi-movie movie
+x-conference/x-cooltalk ice
Propchange: incubator/mod_ftp/trunk/tests/conf/mime.types
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/conf/mod_specs.conf
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/conf/mod_specs.conf?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/conf/mod_specs.conf (added)
+++ incubator/mod_ftp/trunk/tests/conf/mod_specs.conf Thu Oct 6 06:16:28 2005
@@ -0,0 +1,12 @@
+<VirtualHost _default_:12346>
+
+FTP on
+
+FTPMaxLoginAttempts 3
+FTPTimeoutLogin 120
+FTPTimeoutIdle 600
+FTPTimeoutData 300
+
+LogLevel debug
+
+</VirtualHost>
Propchange: incubator/mod_ftp/trunk/tests/conf/mod_specs.conf
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/logs/.cvsignore
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/logs/.cvsignore?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/logs/.cvsignore (added)
+++ incubator/mod_ftp/trunk/tests/logs/.cvsignore Thu Oct 6 06:16:28 2005
@@ -0,0 +1,3 @@
+access_log
+error_log
+apache_scoreboard
Propchange: incubator/mod_ftp/trunk/tests/logs/.cvsignore
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/pytest.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/pytest.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/pytest.py (added)
+++ incubator/mod_ftp/trunk/tests/pytest.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,53 @@
+import traceback, time, string
+
+class Tester:
+ def __init__(self, log_file):
+ self._log_file = log_file
+ self.begin_testsuite()
+
+ def write_log(self, data):
+ self._log_file.write(data)
+
+ def end_testsuite(self):
+ self._log_file.write('\nTest suite ended at: %s\n' %
+ (time.ctime(time.time())))
+
+ def begin_testsuite(self):
+ self._log_file.write('Test suite begun at: %s\n' %
+ (time.ctime(time.time())))
+
+ def boxulate(self, s):
+ pad = 3
+ mstrlen = 0
+ if type(s) == type(''):
+ s = [s]
+
+ mstrlen = max(map(lambda x: len(x), s))
+
+ # Fudge a few characters on each side
+ boxwidth = mstrlen + pad + pad
+
+ res = ['+' + '-' * boxwidth + '+']
+ for sub in s:
+ res.append('|' + ' ' *pad + string.ljust(sub, mstrlen + pad) + '|')
+
+ res.append('+' + '-' * boxwidth + '+')
+ return string.join(res, '\n') + '\n'
+
+ def generate_test_header(self, testname):
+ header = [ 'Test: ' + testname, 'Time: ' + time.ctime(time.time()) ]
+ return self.boxulate(header) + '\n'
+
+ def run_test(self, testname, fn, arg, logfile=None):
+ real_log = logfile or self._log_file
+ try:
+ data = fn(arg)
+ if data:
+ real_log.write(data)
+ real_log.write('Test completed successfully\n\n')
+ return 0
+ except:
+ traceback.print_exc(file=real_log)
+ real_log.write('Test failed\n\n')
+ return -1
+
Propchange: incubator/mod_ftp/trunk/tests/pytest.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/.cvsignore
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/.cvsignore?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/.cvsignore (added)
+++ incubator/mod_ftp/trunk/tests/tests/.cvsignore Thu Oct 6 06:16:28 2005
@@ -0,0 +1,2 @@
+*.pyc
+
Propchange: incubator/mod_ftp/trunk/tests/tests/.cvsignore
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/aasetup.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/aasetup.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/aasetup.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/aasetup.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,92 @@
+#
+# Setup the FTP test environment. This script must be run first.
+#
+# Naming conventions:
+# Directories are single letters, files are a number that corresponds to the
+# size of the file.
+#
+import string
+import basic
+import os
+import tempfile
+import random
+import time
+from stat import *
+
+# Max size at 20k for now.
+MAX_FILE_SIZE = 1024 * 20
+SETUP_COMPLETE = ".ftp_setup_complete"
+
+# Routine for directory creation
+def make_dirs(root):
+ dirs = string.letters
+ for i in range(26):
+ dir = os.path.join(root, dirs[i])
+ if not os.path.exists(dir):
+ os.mkdir(dir)
+
+# Routine for random file creation
+def make_files(root, num):
+ randfile = open("/dev/urandom")
+ for i in range(num):
+ size = random.random() * MAX_FILE_SIZE
+ buf = randfile.read(size)
+ filename = '%s/%s' %(root, int(size))
+ file = open(filename, 'w+')
+ file.write(buf)
+ file.close()
+
+# Create a named file
+def make_file(root, name):
+ randfile = open("/dev/urandom")
+ size = random.random() * MAX_FILE_SIZE
+ buf = randfile.read(size)
+ filename = '%s/%s' %(root, name)
+ file = open(filename, 'w+')
+ file.write(buf)
+ file.close()
+
+def file_remove(arg, top, names):
+ """Called from os.path.walk. Deletes all files in the directory"""
+ for file in names:
+ abspath = os.path.join(top, file)
+ if not os.path.isdir(abspath):
+ os.remove(abspath)
+
+def dir_remove(arg, top, names):
+ """Called from os.path.walk. Delete all directories in the directory"""
+ for dir in names:
+ abspath = os.path.join(top, dir)
+ os.rmdir(abspath)
+
+def test(arg):
+ """This is the setup script for all the FTP tests. This script creates
+ a file system layout that other scripts will depend on. Because of this
+ it is not recommended that you change the files or directories that are
+ created here without first looking at the other tests."""
+ x = arg.find_serverroot()
+ serverroot = x + '/htdocs'
+
+ if os.path.exists(serverroot):
+ os.path.walk(serverroot, file_remove, '')
+ os.path.walk(serverroot, dir_remove, '')
+ if not os.path.exists(serverroot):
+ os.mkdir(serverroot)
+
+ # Make the top level directories
+ make_dirs(serverroot)
+
+ # Create 40 files in the top level directory
+ make_files(serverroot, 40)
+
+ # Create a file we know the name of for ABOR test
+ make_file(serverroot, 'aborfile')
+
+ # Create 10 files in each of the toplevel directories
+ dirs = string.letters
+ for i in range(26):
+ dir = os.path.join(serverroot, dirs[i])
+ if os.path.exists(dir):
+ make_files(dir, 10)
+
+ return "FTP test environment created\n\n"
Propchange: incubator/mod_ftp/trunk/tests/tests/aasetup.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/abor.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/abor.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/abor.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/abor.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,38 @@
+import basic, string
+
+def send_abor(conn):
+ conn.send_command('ABOR')
+
+def send_retr(conn, file):
+ conn.send_command('RETR', file)
+
+def send_pasv(conn):
+ conn.send_command('PASV')
+
+def dotest():
+ x = basic.FTPControl()
+ x.login()
+
+ # Request a passive connection
+ send_pasv(x)
+
+ # Request a file we know exists
+ send_retr(x, 'aborfile')
+
+ # Immediately send an ABOR
+ send_abor(x)
+
+def test(arg):
+ """This is the test for the ABOR command. This test will
+ initiate a RETR, but then ABOR before opening a data
+ connection. This test is to demonstrate the errors seen
+ at Cisco"""
+
+ x = basic.FTPControl()
+ x.login()
+
+ for i in range(25):
+ dotest()
+
+ res = 'command: ABOR \nreturned: OK\n\n'
+ return string.replace(res, '\r\n', '\n')
Propchange: incubator/mod_ftp/trunk/tests/tests/abor.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/basic.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/basic.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/basic.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/basic.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,190 @@
+#
+# Login test -- Checks basic login functionality, and is used by all
+# the other testing modules to test login functionality.
+
+import string
+from socket import *
+
+CRLF = '\r\n'
+CR = '\r'
+LF = '\n'
+
+RFCvals = { "Connect" : ( {(120,) : (220,) }, 220, 421 ),
+ "USER" : (230,530,500,501,421,331,332),
+ "PASS" : (230,202,530,500,501,503,421,332),
+ "ACCT" : (230,202,540,500,501,503,421),
+ "CWD" : (250,500,501,502,421,530,550),
+ "CDUP" : (200,500,501,502,421,530,550),
+ "SMNT" : (202,250,500,501,502,421,530,550),
+ "REIN" : ( {(120,) : (220,) }, 220, 421, 500, 502),
+ "QUIT" : (221, 500),
+ "PORT" : (200, 500, 501, 421, 530),
+ "PASV" : (227, 500, 501, 502, 421, 530),
+ "MODE" : (200, 500, 501, 504, 421, 530),
+ "TYPE" : (200, 500, 501, 504, 421, 530),
+ "STRU" : (200, 500, 501, 504, 421, 530),
+ "ALLO" : (200, 202, 500, 501, 504, 421, 530),
+ "REST" : (500, 501, 502, 421, 530, 350),
+ "STOR" : ({(125, 150):(110, 226, 250, 425, 426, 451, 551,552)},
+ 532, 450, 452, 553, 500, 501, 421, 530),
+ "STOU" : ({(125, 150):(110, 226, 250, 425, 426, 451, 551,552)},
+ 532, 450, 452, 553, 500, 501, 421, 530),
+ "RETR" : ({(125, 150):(110, 226, 250, 425, 426, 451)},
+ 450, 550, 500, 501, 421, 530),
+ "LIST" : ({(125, 150):(226,250,425,426,451)},
+ 450, 500, 501, 502, 421, 530),
+ "NLST" : ({(125, 150):(226,250,425,426,451)},
+ 425, 450, 500, 501, 502, 421, 530),
+ "APPE" : ({(125, 150):(110,226,250,425,426,451,551,552)},
+ 450, 500, 501, 502, 421, 530),
+ "RNFR" : (450,550,500,501,502,421,530,350),
+ "RNTO" : (250,532,553,500,501,502,503,421,530),
+ "DELE" : (250,450,550,500,501,502,421,530),
+ "RMD" : (250,500,501,502,421,530,550),
+ "MKD" : (257,500,501,502,421,530,550),
+ "PWD" : (257,500,501,502,421,530,550),
+ "ABOR" : (225,226,426,500,501,502,421),
+ "SYST" : (215,500,501,502,421),
+ "STAT" : (211,212,213,450,500,501,502,421,530),
+ "HELP" : (211,214,500,501,502,421),
+ "SITE" : (200,202,500,501,530),
+ "NOOP" : (200,500,421),
+ }
+
+class FTPControl:
+ """FTPControl: Base class for dealing with the FTP control connection"""
+ def __init__(self, host='localhost', port=12346):
+ self.sock = socket(AF_INET, SOCK_STREAM)
+ self.sock.connect((host, port))
+ self.sockf = self.sock.makefile('wb+')
+ self.passive = 0
+ self.port = 0
+ self.host = ''
+
+ rescode, msg = self.get_result()
+ if not self.response_is_valid("Connect", (rescode,)):
+ raise 'Invalid response to connection'
+
+ def send_command(self, *args):
+ cmd = args[0]
+ if len(args) > 1:
+ argstr = ' ' + string.join(args[1:], ' ')
+ else:
+ argstr = ''
+
+ self.sockf.write('%s%s%s' % (cmd, argstr, CRLF))
+
+
+ def response_is_valid(self, cmd, rescodes):
+ """response_is_valid(cmd,rescodes): Return 1 if the response codes
+ are valid for a given command, 0 if not"""
+
+ if len(rescodes) == 1:
+ return rescodes[0] in RFCvals[cmd]
+
+ for val in filter(lambda x:type(x)==type({}), RFCvals[cmd]):
+ for key in val.keys():
+ if rescodes[0] in key:
+ return rescodes[1] in val[key]
+ return 0
+
+ def error_perm(self, code):
+ """error_perm(code): Check if a permanent error has occured"""
+ if (code >= 500 and code < 600):
+ return 1
+ else:
+ return 0
+
+ def error_temp(self, code):
+ """error_temp(code): Check if a temporary error has occured"""
+ if (code >= 400 and code < 500):
+ return 1
+ else:
+ return 0
+
+ def get_result(self):
+ """get_result(): Get the result from the previous sent
+ FTP command. See rfc959, section 4.2"""
+ line = self.sockf.readline()
+ if line[-2:] != CRLF:
+ raise 'No CRLF at the end of a response'
+ if len(line) < 4:
+ raise 'Malformed result'
+
+ resmsg = [line,]
+ rescode = line[:3]
+ if line[3] == '-':
+ while 1:
+ line = self.sockf.readline()
+ if line[-2:] != CRLF:
+ raise 'No CRLF at the end of a response line'
+ resmsg.append(line)
+ if line[:4] == rescode + ' ':
+ break
+
+ return int(rescode), resmsg
+
+ def login(self, user='anonymous', password='BLAH'):
+ self.send_command('USER', user)
+ code, msg = self.get_result()
+ if not self.response_is_valid("USER", (code,)):
+ raise "Invalid response from USER", code
+
+ self.send_command('PASS', password)
+ code, msg = self.get_result()
+ if not self.response_is_valid("PASS", (code,)):
+ raise "Invalid response from PASS", code
+
+ def logout(self):
+ self.send_command('QUIT')
+ code, msg = self.get_result()
+ if not self.response_is_valid("QUIT", (code,)):
+ raise 'Invalid response from QUIT'
+
+ def create_portstring(self, host, port):
+ res = string.replace(host, '.', ',')
+ low8 = port & 0x00ff
+ high8 = (port & 0xff00) >> 8
+ return '%s,%d,%d' % (res, high8, low8)
+
+ def parse_portstring(self, msg):
+ """Return an ip address and port based on a PASV response"""
+ if msg[:3] <> '227':
+ raise 'Invalid string passed to parse_portstring', msg
+ left = string.find(msg, '(')
+ right = string.find(msg, ')', left + 1)
+ numbers = string.split(msg[left+1:right], ',')
+ host = string.join(numbers[:4], '.')
+ port = (string.atoi(numbers[4]) << 8) + string.atoi(numbers[5])
+ return host, port
+
+ def setup_dataconn(self, passive=0):
+ x = socket(AF_INET, SOCK_STREAM)
+ if not passive:
+ x.bind(('', 0))
+ x.listen(10)
+ z, port = x.getsockname()
+ host, z = self.sock.getsockname()
+ portstr = self.create_portstring(host, port)
+ self.send_command('PORT', portstr)
+ code, msg = self.get_result()
+ if not self.response_is_valid('PORT', (code,)):
+ raise 'Invalid response from PORT'
+ else:
+ self.send_command('PASV')
+ code, msg = self.get_result()
+ if not self.response_is_valid('PASV', (code,)):
+ raise 'Invalid response from PASV'
+ self.host, self.port = self.parse_portstring(msg[0])
+
+ return x
+
+def test(arg):
+ """This is the base class for most of the FTP operations. The basic
+ class is used for setting up the control connection and logging in.
+ This class is also used for sending commands, reading responses and
+ setting up sockets."""
+ x = FTPControl()
+ x.login()
+ x.logout()
+ return None
Propchange: incubator/mod_ftp/trunk/tests/tests/basic.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/cd.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/cd.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/cd.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/cd.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,77 @@
+import basic, string, os
+
+# Note: CWD's outside of the document root will succeed as '/'.
+tests = ['../../../../../', 'a/../a/../', 'a/../b/../c/../d/..',
+ 'a/././././', 'a/./../b/.' '/../../../', 'abcd', '.']
+
+def send_pwd(conn, dir):
+ conn.send_command('PWD')
+ code, msg = conn.get_result()
+ if not conn.response_is_valid("PWD", (code,)):
+ raise 'Invalid response from PWD', code
+
+ newdir = string.split(msg[0], '"')
+ if newdir[1] != os.path.join('/', dir):
+ raise 'Incorrect response from PWD: ', newdir[1]
+ return code, msg
+
+def send_cdup(conn):
+ conn.send_command('CDUP')
+ code, msg = conn.get_result()
+ if not conn.response_is_valid("CDUP", (code,)):
+ #
+ # Many servers (e.g. wu-ftp) return 250 on a CDUP command.
+ # According to RFC959, this is not valid, but we let it
+ # slip by.
+ if code != 250:
+ raise 'Invalid response from CDUP', code
+ return code, msg
+
+def send_cwd(conn, dir):
+ conn.send_command('CWD', dir)
+ code, msg = conn.get_result()
+ if not conn.response_is_valid("CWD", (code,)):
+ raise 'Invalid response from CWD', code
+ return code, msg
+
+def test(arg):
+ """This is the change directory test. This tests change working
+ directory (CWD), change directory up (CDUP) and print working
+ directory (PWD). These tests are performed on a known file system
+ layout, so sucess or failure is easy to detect. If a failure is
+ found, an exception is raised, and the test will fail. Otherwise
+ all commands and responses are printed to the log file."""
+ x = basic.FTPControl()
+ x.login()
+
+ # Buffer to hold our results
+ buf = ''
+
+ # First test known directories
+ dirs = string.letters
+ for i in range(26):
+
+ code, msg = send_cwd(x, dirs[i])
+ buf = '%scommand: %s%s \nreturned: \n%s\n\n' %(buf, 'CWD ', dirs[i],
+ string.join(msg))
+ code, msg = send_pwd(x, dirs[i])
+ buf = '%scommand: %s \nreturned: \n%s\n\n' %(buf, 'PWD',
+ string.join(msg))
+ code, msg = send_cdup(x)
+ buf = '%scommand: %s \nreturned: \n%s\n\n' %(buf, 'CDUP',
+ string.join(msg))
+ code, msg = send_pwd(x, '')
+ buf = '%scommand: %s \nreturned: \n%s\n\n' %(buf, 'PWD',
+ string.join(msg))
+
+ # Other random tests
+ for test in tests:
+ code, msg = send_cwd(x, test)
+ buf = '%scommand: %s \nreturned: \n%s\n\n' %(buf, 'CWD',
+ string.join(msg))
+ code ,msg = send_cwd(x, '/')
+ buf = '%scommand: %s \nreturned: \n%s\n\n' %(buf, 'PWD',
+ string.join(msg))
+
+ x.logout()
+ return string.replace(buf, '\r\n', '\n')
Propchange: incubator/mod_ftp/trunk/tests/tests/cd.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/dele.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/dele.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/dele.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/dele.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,62 @@
+import basic, string
+
+def send_cwd(conn, dir):
+ conn.send_command('CWD', dir)
+ code, msg = conn.get_result()
+ if not conn.response_is_valid('CWD', (code,)):
+ raise 'Invalid response from CWD', code
+
+def send_nlst(conn, dataconn, args):
+ """Sends an NLST command with the given pattern. Returns a list
+ of files that were found."""
+
+ conn.send_command('NLST', args)
+ code1, msg = conn.get_result()
+ if conn.error_perm(code1):
+ return
+ code2, msg = conn.get_result()
+ if not conn.response_is_valid("NLST", (code1, code2)):
+ raise 'Invalid response from NLST'
+ if conn.error_perm(code2):
+ return
+
+ c, d = dataconn.accept()
+
+ list = string.split(c.recv(10240), '\r\n')
+
+ # We don't want to return any empty entries.
+ for item in list:
+ if item == '':
+ list.remove(item)
+ return list
+
+def test(arg):
+ """This is the test for the delete command. This test will change into
+ a directory and remove all files. If all files are not removed, an
+ exception is raised. All commands and results are printed to the log
+ file"""
+ x = basic.FTPControl()
+ x.login()
+
+ res = ''
+
+ send_cwd(x, 'a')
+
+ passive_sock = x.setup_dataconn(passive=0)
+ files = send_nlst(x, passive_sock, '*')
+
+ for file in files:
+ x.send_command('DELE', file)
+ code, msg = x.get_result()
+ if not x.response_is_valid('DELE', (code,)):
+ raise 'Invalid response from DELE', code
+
+ res = '%scommand: DELE %s \nreturned: \n%s\n\n' %(res, file,
+ string.join(msg))
+
+ passive_sock = x.setup_dataconn(passive=0)
+ files = send_nlst(x, passive_sock, '*')
+ if len(files) != 0:
+ raise 'Error, DELE did not remove all files.', files
+
+ return string.replace(res, '\r\n', '\n')
Propchange: incubator/mod_ftp/trunk/tests/tests/dele.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/help.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/help.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/help.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/help.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,30 @@
+import basic, string
+
+tests = ['STOR', 'REST', 'MKD', 'RMD', 'NOOP', 'INVALID_METHOD']
+
+def send_help(conn, command=''):
+ conn.send_command('HELP', command)
+ code, msg = conn.get_result()
+ if not conn.response_is_valid('HELP', (code,)):
+ raise 'Invalid response from HELP', code
+ return code, msg
+
+def test(arg):
+ """This is the test for the TYPE command. A few tests are sent
+ and the result code is checked."""
+
+ x = basic.FTPControl()
+ x.login()
+
+ res = ''
+
+ # First send a help message with no arguments.
+ code, msg = send_help(x)
+ res = '%scommand: HELP \nreturned: \n%s\n\n' %(res, string.join(msg))
+
+ # Run through our test cases.
+ for test in tests:
+ code, msg = send_help(x, test)
+ res = '%scommand: HELP %s\nreturned: \n%s\n\n' %(res, test, string.join(msg))
+
+ return string.replace(res, '\r\n', '\n')
Propchange: incubator/mod_ftp/trunk/tests/tests/help.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/list.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/list.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/list.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/list.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,44 @@
+import basic, string, os
+
+# Array of test cases to be passed to LIST
+tests = ['*', '*.html', '2*2', '3*', '*3', 'a*', '*i*', 'a/*',
+ '*.*', '9*', 'q', 'b', 'a*b', 'b*', 'q*', '*q', '12*']
+
+def send_valid_list(conn, dataconn, args):
+ conn.send_command('LIST', args)
+ code1, msg = conn.get_result() # get the intro message
+ # Return if we detect a permanent error.
+ if conn.error_perm(code1):
+ return
+ code2, msg = conn.get_result() # Get the real sending message
+ if not conn.response_is_valid("LIST", (code1, code2)):
+ raise 'Invalid response from LIST', (code1, code2)
+ if conn.error_perm(code2):
+ return
+
+ c, d = dataconn.accept()
+
+ return map(lambda x: string.replace(x, '\r\n', '\n'),
+ string.split(c.recv(10240), ' '))
+
+def test(arg):
+ """This is the file list test. This test runs LIST with a predefined
+ set of arguments. The command and its output are all printed to the
+ log file. Checking of the output is not done."""
+ x = basic.FTPControl()
+ x.login()
+
+ res = ''
+ for test in tests:
+ passive_sock = x.setup_dataconn(passive=0)
+
+ files = send_valid_list(x, passive_sock, test)
+
+ if files == None:
+ res = '%scommand: LIST %s \nreturned: \n%s\n\n' %(res, test, files)
+ else:
+ output = string.join(files)
+ res = '%scommand: LIST %s \nreturned: \n%s\n\n' %(res, test, output)
+
+ x.logout()
+ return res
Propchange: incubator/mod_ftp/trunk/tests/tests/list.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/mdtm.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/mdtm.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/mdtm.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/mdtm.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,54 @@
+import basic, string
+
+def send_mdtm(conn, file):
+ conn.send_command('MDTM', file)
+ code, msg = conn.get_result()
+ #
+ # MDTM is not in our RFC vals since it is not defined in 959.
+ #
+ #if not conn.response_is_valid('MDTM', (code,)):
+ # raise 'Invalid response from MDTM', code
+
+ return code, msg
+
+def get_filelist(conn, dataconn, args):
+ """Uses NLST to get a list of files to be checked."""
+
+ conn.send_command('NLST', args)
+ code1, msg = conn.get_result()
+ if conn.error_perm(code1):
+ return
+ code2, msg = conn.get_result()
+ if not conn.response_is_valid("NLST", (code1, code2)):
+ raise 'Invalid response from NLST'
+ if conn.error_perm(code2):
+ return
+
+ c, d = dataconn.accept()
+
+ list = string.split(c.recv(10240), '\r\n')
+
+ # We don't want to return any empty entries.
+ for item in list:
+ if item == '':
+ list.remove(item)
+ return list
+
+def test(arg):
+ """This is the test for the MDTM command."""
+ x = basic.FTPControl()
+ x.login()
+
+ res = ''
+
+ passive_sock = x.setup_dataconn(passive=0)
+ files = get_filelist(x, passive_sock, '*')
+
+ for file in files:
+ code, msg = send_mdtm(x, file)
+ res = '%scommand: MDTM %s \nreturned: \n%s\n\n' %(res, file,
+ string.join(msg))
+
+ # XXX: check results
+
+ return string.replace(res, '\r\n', '\n')
Propchange: incubator/mod_ftp/trunk/tests/tests/mdtm.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/mkd.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/mkd.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/mkd.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/mkd.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,34 @@
+import basic, string, os
+
+def send_mkd(conn, dir):
+ conn.send_command('MKD', dir)
+ code, msg = conn.get_result()
+ if not conn.response_is_valid('MKD', (code,)):
+ raise 'Invalid response from MKD', code
+
+ return code, msg
+
+def test(arg):
+ """This is the test for the mkdir command. This test creates
+ 26 new directories aa - az. The test also verifies that the
+ directories were actually created. These directories are
+ deleted by the rmd test."""
+
+ x = basic.FTPControl()
+ x.login()
+
+ res = ''
+
+ dirs = string.letters
+ for i in range(26):
+ dir = 'a' + dirs[i]
+ code, msg = send_mkd(x, dir)
+ res = '%scommand: MKD %s \nreturned: \n%s\n\n' %(res, dir, msg[0])
+
+ # Check the filesystem if the directory was actually created
+ documentroot = arg.find_serverroot() + '/htdocs'
+ path = os.path.join(documentroot, dir)
+ if not os.path.exists(path):
+ raise 'Directory not created', path
+
+ return string.replace(res, '\r\n', '\n')
Propchange: incubator/mod_ftp/trunk/tests/tests/mkd.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/nlst.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/nlst.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/nlst.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/nlst.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,73 @@
+import basic, string, os, glob
+
+# Array of test cases to be passed to NLST
+tests = ['*', '*.html', '2*2', '3*', '*3', 'a*', '*i*', 'a* b*',
+ '*.*', '9*', 'q', 'b', 'a*b', 'b*', 'q*', '*q', '12*']
+
+def send_bogus_nlst(conn):
+ # First send a request even without a port given
+ # should return a 425
+ conn.send_command('NLST')
+ code, msg = conn.get_result()
+ if not conn.response_is_valid("NLST", (code,)): # Verify RFC standard
+ raise 'Invalid response from NLST', code
+ if code != 425:
+ raise 'Expected return value not found'
+
+def send_valid_nlst(conn, dataconn, args):
+ conn.send_command('NLST', args)
+ code1, msg = conn.get_result() # get the intro message
+ # Return if we detect a permanent error.
+ if conn.error_perm(code1):
+ return
+ code2, msg = conn.get_result() # Get the real sending message
+ if not conn.response_is_valid("NLST", (code1, code2)):
+ raise 'Invalid response from NLST', (code1, code2)
+ if conn.error_perm(code2):
+ return
+
+ c, d = dataconn.accept()
+
+ return map(lambda x: string.replace(x, '\r\n', '\n'),
+ string.split(c.recv(10240), ' '))
+
+def test(arg):
+ """This is the file list test. The purpose of NLST is to return a list
+ of files to the client. The client usually issues NLST requests for
+ multiple gets. This test runs NLST with a predefined set of arguments.
+ The command and its output are all printed to the log file."""
+ x = basic.FTPControl()
+ x.login()
+ send_bogus_nlst(x)
+ res = ''
+ for test in tests:
+ passive_sock = x.setup_dataconn(passive=0)
+
+ files = send_valid_nlst(x, passive_sock, test)
+
+ # Find which files NLST should actually return
+ matches = []
+ path = arg.find_serverroot() + '/htdocs/' + test
+ list = glob.glob(path)
+ list.sort()
+ for item in list:
+ if not os.path.isdir(item):
+ matches.append(os.path.basename(item))
+
+ if files == None:
+ res = '%scommand: NLST %s \nreturned: \n%s\n\n' %(res, test, files)
+ else:
+ # First convert the output to a list
+ filelist = string.split(files[0], '\n')
+ for item in filelist:
+ if item == '':
+ filelist.remove(item)
+
+ # Check that the lists are identical.
+ if filelist != matches:
+ 'raise NLST returned unexpected values', filelist
+
+ res = '%scommand: NLST %s \nreturned: \n%s\n\n' %(res, test, files[0])
+
+ x.logout()
+ return res
Propchange: incubator/mod_ftp/trunk/tests/tests/nlst.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/noop.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/noop.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/noop.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/noop.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,21 @@
+import basic, string
+
+def send_noop(conn):
+ conn.send_command('NOOP')
+ code, msg = conn.get_result()
+ if not conn.response_is_valid('NOOP', (code,)):
+ raise 'Invalid response from NOOP', code
+ return code, msg
+
+def test(arg):
+ """This is the test for the NOOP command. All this does is send a
+ NOOP command and check the return code. Nothing too complicated."""
+
+ x = basic.FTPControl()
+ x.login()
+
+ code, msg = send_noop(x)
+
+ res = 'command: NOOP \nreturned: \n%s\n\n' %(string.join(msg))
+
+ return string.replace(res, '\r\n', '\n')
Propchange: incubator/mod_ftp/trunk/tests/tests/noop.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/rename.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/rename.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/rename.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/rename.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,73 @@
+import basic, string, os
+
+def send_rnfr(conn, file):
+ conn.send_command('RNFR', file)
+ code, msg = conn.get_result()
+ if not conn.response_is_valid("RNFR", (code,)):
+ raise 'Invalid response from RNFR', code
+
+ return code, msg
+
+def send_rnto(conn, file):
+ conn.send_command('RNTO', file)
+ code, msg = conn.get_result()
+ if not conn.response_is_valid("RNTO", (code,)):
+ raise 'Invalid response from RNTO', code
+
+ return code, msg
+
+def test(arg):
+ """This is the rename test. The rename operation is defined in
+ a sequence of commands in the FTP protocol. RNFR 'file' tells
+ the server we want to rename the file 'file'. This command must
+ be followed by a RNTO command that will tell the server what the
+ new file name should be. If these commands happen out of sequence,
+ a sequence error (503) should be returned."""
+
+ x = basic.FTPControl()
+ x.login()
+
+ # Buffer to hold our results
+ buf = ''
+
+ # Let's rename all the known directories
+ dirs = string.letters
+ for i in range(26):
+ newfile = 'renamed' + dirs[i]
+
+ # First let's rename
+ code, msg = send_rnfr(x, dirs[i])
+ buf = '%scommand: %s %s \nreturned: \n%s\n\n' %(buf, 'RNFR', dirs[i],
+ string.join(msg))
+
+ code, msg = send_rnto(x, newfile)
+
+ buf = '%scommand: %s %s \nreturned: \n%s\n\n' %(buf, 'RNTO', newfile,
+ string.join(msg))
+
+ # Now rename them back
+ code, msg = send_rnfr(x, newfile)
+ buf = '%scommand: %s %s \nreturned: \n%s\n\n' %(buf, 'RNFR', newfile,
+ string.join(msg))
+
+ code, msg = send_rnto(x, dirs[i])
+ buf = '%scommand: %s %s \nreturned: \n%s\n\n' %(buf, 'RNTO', dirs[i],
+ string.join(msg))
+ # Test out of sequence condition
+ newfile = 'sequence_test'
+ code, msg = send_rnto(x, newfile)
+ buf = '%scommand: %s %s\nreturned: \n%s\n\n' %(buf, 'RNTO', newfile,
+ string.join(msg))
+ if code != 503:
+ raise 'Incorrect response from RNTO', code
+
+ # Test rename of a non-existant file
+ newfile = 'foo'
+ code, msg = send_rnfr(x, newfile)
+ buf = '%scommand: %s %s\nreturned: \n%s\n\n' %(buf, 'RNFR', newfile,
+ string.join(msg))
+ if code != 550:
+ raise 'Incorrect response from RNFR', code
+
+ x.logout()
+ return string.replace(buf, '\r\n', '\n')
Propchange: incubator/mod_ftp/trunk/tests/tests/rename.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/rest.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/rest.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/rest.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/rest.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,26 @@
+import basic, string
+
+tests = ['0', '1000', '-1000', 'invalid', '100000000000000']
+
+def send_rest(conn, offset):
+ conn.send_command('REST', offset)
+ code, msg = conn.get_result()
+ if not conn.response_is_valid('REST', (code,)):
+ raise 'Invalid response from REST', code
+ return code, msg
+
+def test(arg):
+ """This is the tests for the REST command. For now only the result
+ code is checked."""
+
+ x = basic.FTPControl()
+ x.login()
+
+ res = ''
+
+ for test in tests:
+ code, msg = send_rest(x, test)
+ res = '%scommand: REST %s\nreturned: \n%s\n\n' %(res, test,
+ string.join(msg))
+
+ return string.replace(res, '\r\n', '\n')
Propchange: incubator/mod_ftp/trunk/tests/tests/rest.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/rmd.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/rmd.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/rmd.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/rmd.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,35 @@
+import basic, string, os
+
+def send_rmd(conn, dir):
+ conn.send_command('RMD', dir)
+ code, msg = conn.get_result()
+ if not conn.response_is_valid('RMD', (code,)):
+ raise 'Invalid response from RMD', code
+
+ return code, msg
+
+def test(arg):
+ """This is the test for the rmdir command. This test relies on the
+ mkdir test to create the directories to be deleted. The directories
+ aa - az are deleted. If we detect a bad response, or if a directory
+ is not deleted we raise an error."""
+
+ x = basic.FTPControl()
+ x.login()
+
+ res = ''
+
+ dirs = string.letters
+ for i in range(26):
+ dir = 'a' + dirs[i]
+ code, msg = send_rmd(x, dir)
+ res = '%scommand: RMD %s \nreturned: \n%s\n\n' %(res, dir,
+ string.join(msg))
+
+ # Check the filesystem if the directory was actually created
+ documentroot = arg.find_serverroot() + '/htdocs'
+ path = os.path.join(documentroot, dir)
+ if os.path.exists(path):
+ raise 'Directory not deleted', path
+
+ return string.replace(res, '\r\n', '\n')
Propchange: incubator/mod_ftp/trunk/tests/tests/rmd.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/size.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/size.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/size.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/size.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,60 @@
+import basic, string
+
+def send_size(conn, file):
+ conn.send_command('SIZE', file)
+ code, msg = conn.get_result()
+ #
+ # SIZE is not in our RFC vals since it is not defined in 959.
+ #
+ #if not conn.response_is_valid('SIZE', (code,)):
+ # raise 'Invalid response from SIZE', code
+
+ return code, msg
+
+def get_filelist(conn, dataconn, args):
+ """Uses NLST to get a list of files to be checked."""
+
+ conn.send_command('NLST', args)
+ code1, msg = conn.get_result()
+ if conn.error_perm(code1):
+ return
+ code2, msg = conn.get_result()
+ if not conn.response_is_valid("NLST", (code1, code2)):
+ raise 'Invalid response from NLST'
+ if conn.error_perm(code2):
+ return
+
+ c, d = dataconn.accept()
+
+ list = string.split(c.recv(10240), '\r\n')
+
+ # We don't want to return any empty entries.
+ for item in list:
+ if item == '':
+ list.remove(item)
+ return list
+
+def test(arg):
+ """This is the test for the SIZE command."""
+ x = basic.FTPControl()
+ x.login()
+
+ res = ''
+
+ passive_sock = x.setup_dataconn(passive=0)
+ files = get_filelist(x, passive_sock, '*')
+
+ for file in files:
+ if file == 'aborfile':
+ continue
+ code, msg = send_size(x, file)
+ size = string.split(string.replace(msg[0], '\r\n', ''), ' ')[-1:]
+
+ # Check to see if the size was what we expected.
+ if size[0] != file:
+ raise 'SIZE returned unexpected value', size[0]
+
+ res = '%scommand: SIZE %s \nreturned: \n%s\n\n' %(res, file,
+ string.join(msg))
+
+ return string.replace(res, '\r\n', '\n')
Propchange: incubator/mod_ftp/trunk/tests/tests/size.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/syst.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/syst.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/syst.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/syst.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,32 @@
+import basic, string
+
+def send_syst(conn):
+ conn.send_command('SYST')
+ code, msg = conn.get_result()
+ if not conn.response_is_valid('SYST', (code,)):
+ raise 'Invalid response from SYST', code
+ return code, msg
+
+def test(arg):
+ """This is the test for the SYST command. According to RFC 959 SYST
+ must return a name from the official names list defined in RFC 943,
+ but these seem rather worthless. These are not currently checked."""
+
+ x = basic.FTPControl()
+ x.login()
+
+ # Official system names from RFC 943... these sure seem worthless.
+ offical_names = ['ASP', 'AUGUST', 'BKY', 'CCP', 'DOS/360', 'ELF',
+ 'EPOS', 'EXEC-8', 'GCOS', 'ITS', 'INTERCOM',
+ 'INTERLISP', 'KRONOS', 'MCP', 'MOS', 'MPX-RT',
+ 'MULTICS', 'MVT', 'NOS', 'NOS/BE', 'OS/MVS',
+ 'OS/MVT', 'RIG', 'RSX-11M', 'RT11', 'SCOPE',
+ 'SIGNAL', 'SINTRAN', 'TAC', 'TENEX', 'TOPS-10',
+ 'TOPS-20', 'TSS', 'UNIX', 'VM/370', 'VM/CMS',
+ 'VMS', 'WAITS', 'XDE']
+
+ code, msg = send_syst(x)
+
+ res = 'command: SYST \nreturned: \n%s\n\n' %(string.join(msg))
+
+ return string.replace(res, '\r\n', '\n')
Propchange: incubator/mod_ftp/trunk/tests/tests/syst.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/tests/tests/type.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/tests/tests/type.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/tests/tests/type.py (added)
+++ incubator/mod_ftp/trunk/tests/tests/type.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,27 @@
+import basic, string
+
+# Different types we could come across. (and some we shouldn't)
+tests = ['A', 'B', 'I', 'E', 'ASCII', 'BINARY', 'FOO']
+
+def send_type(conn, type):
+ conn.send_command('TYPE', type)
+ code, msg = conn.get_result()
+ if not conn.response_is_valid('TYPE', (code,)):
+ raise 'Invalid response from TYPE', code
+ return code, msg
+
+def test(arg):
+ """This is the test for the TYPE command. A few tests are sent
+ and the result code is checked."""
+
+ x = basic.FTPControl()
+ x.login()
+
+ res = ''
+
+ for test in tests:
+ code, msg = send_type(x, test)
+ res = '%scommand: TYPE \nreturned: \n%s\n\n' %(res,
+ string.join(msg))
+
+ return string.replace(res, '\r\n', '\n')
Propchange: incubator/mod_ftp/trunk/tests/tests/type.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/utils/ftp_proxy/.cvsignore
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/utils/ftp_proxy/.cvsignore?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/utils/ftp_proxy/.cvsignore (added)
+++ incubator/mod_ftp/trunk/utils/ftp_proxy/.cvsignore Thu Oct 6 06:16:28 2005
@@ -0,0 +1 @@
+*.pyc
Propchange: incubator/mod_ftp/trunk/utils/ftp_proxy/.cvsignore
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/utils/ftp_proxy/ftp_proxy.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/utils/ftp_proxy/ftp_proxy.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/utils/ftp_proxy/ftp_proxy.py (added)
+++ incubator/mod_ftp/trunk/utils/ftp_proxy/ftp_proxy.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,121 @@
+# A wimpy FTP Proxy
+# JMT April-16-01 (Tax day)
+# Don't try to read this code, its a mess
+
+import string, re, thread, select, UserList
+from transfer_pair import TransferPair, TransferFilter
+from SocketServer import *
+from sys import *
+from socket import *
+
+PassiveCheck = re.compile('227 .*\(([0-9]+,[0-9]+,[0-9]+,[0-9]+),([0-9]+),([0-9]+)\)')
+
+BLOCKSIZE = 10240
+
+def dbg_msg(msg):
+ stderr.write('FTPProxy: %s\n' % msg)
+
+class PassiveFilter(TransferFilter):
+ def __init__(self, handler):
+ self.buf = ''
+ self.handler = handler
+
+ def filter(self, data, tosock, output, sockname):
+ res = ''
+ while 1:
+ idx = string.find(data, '\r\n')
+ if idx == -1:
+ self.buf = self.buf + data
+ break
+ self.buf = self.buf + data[:idx+2]
+ data = data[idx+2:]
+
+ match = PassiveCheck.match(self.buf)
+ if match:
+ ip, highport, lowport = map(
+ lambda (beg, end), s=self.buf: s[beg:end],
+ match.regs[1:])
+ ip = string.replace(ip, ',', '.')
+ port = (int(highport) << 8) + int(lowport)
+ server_sock = socket(AF_INET, SOCK_STREAM)
+ server_sock.connect((ip, port))
+
+ sock = socket(AF_INET, SOCK_STREAM)
+ sock.bind(('', 0))
+ sock.listen(10)
+ proxy_ip = string.replace(self.handler.conn_ip, ".", ",")
+ proxy_port = sock.getsockname()[1]
+ res = res + '227 Entering Passive Mode (%s,%d,%d)\r\n' % (
+ proxy_ip, proxy_port >> 8, proxy_port & 0x00ff)
+ output('Data sent to %s: "%s"' % (sockname, res))
+ tosock.send(res)
+ res = ''
+ sock, z = sock.accept()
+
+ tpair = TransferPair(server_sock, 'server->proxy(Passive)',
+ sock, 'proxy->client(Passive)',
+ output)
+ self.handler.add_tpair(server_sock, sock, tpair)
+ else:
+ res = res + self.buf
+
+ self.buf = ''
+
+ if len(res):
+ output('Data sent to %s: "%s"' % (sockname, res))
+ tosock.send(res)
+
+
+class FTPRequestHandler(StreamRequestHandler):
+ def add_tpair(self, sock1, sock2, tpair):
+ self.active_sockets.extend([sock1, sock2])
+ self.transfer_pairs.append(tpair)
+
+ def handle(self):
+ request = self.request
+ self.conn_ip = request.getsockname()[0]
+ dbg_msg('Client connected (%s)' % self.client_address[0])
+ svr = socket(AF_INET, SOCK_STREAM)
+ svr.connect((self.server.ftp_host, self.server.ftp_port))
+ dbg_msg('Connected to real server')
+
+ tpair = TransferPair(request, 'client->proxy', svr, 'proxy->server',
+ dbg_msg)
+ tpair.add_filter(PassiveFilter(self).filter)
+ self.transfer_pairs = [tpair]
+ self.active_sockets = [request, svr]
+ while len(self.active_sockets):
+ rfds, z, z = select.select(self.active_sockets, [], [])
+ for tpair in self.transfer_pairs:
+ if tpair.do_transfer(rfds, self.active_sockets):
+ del self.transfer_pairs[self.transfer_pairs.index(tpair)]
+
+ def finish(self):
+ dbg_msg('Client finished (%s)' % self.client_address[0])
+
+
+class FTPProxyServer(ThreadingMixIn, TCPServer):
+ def __init__(self, *args, **kwargs):
+ self.ftp_host = kwargs['ftp_host']
+ self.ftp_port = kwargs['ftp_port']
+ del kwargs['ftp_host']
+ del kwargs['ftp_port']
+ apply(TCPServer.__init__, (self,)+args, kwargs)
+
+ def server_bind(self):
+ TCPServer.server_bind(self)
+ # Make sure we can reuse this address
+ self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
+
+if __name__ == '__main__':
+ if len(argv) != 4:
+ sys.stderr.write('Syntax: %s <proxy_port> <real_host> <real_port>\n' %(
+ argv[0],))
+ sys.exit(1)
+
+ x = FTPProxyServer(('', int(argv[1])), FTPRequestHandler, ftp_host=argv[2],
+ ftp_port=int(argv[3]))
+
+ dbg_msg('Starting proxy on port %s' % (argv[1]))
+ dbg_msg('Real host is %s:%s' % (argv[2], argv[3]))
+ x.serve_forever()
Propchange: incubator/mod_ftp/trunk/utils/ftp_proxy/ftp_proxy.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/utils/ftp_proxy/transfer_pair.py
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/utils/ftp_proxy/transfer_pair.py?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/utils/ftp_proxy/transfer_pair.py (added)
+++ incubator/mod_ftp/trunk/utils/ftp_proxy/transfer_pair.py Thu Oct 6 06:16:28 2005
@@ -0,0 +1,55 @@
+from UserList import UserList
+
+BLOCKSIZE = 10240
+
+class TransferPair:
+ def __init__(self, sock1, sock1name, sock2, sock2name, output_routine):
+ self.__sock1 = sock1
+ self.__sock2 = sock2
+ self.__names = { sock1 : sock1name, sock2 : sock2name }
+ self.__output = output_routine
+ self.filters = []
+
+ def _send_data(self, data, tosock):
+ if not len(self.filters):
+ self.__output('Data sent to %s: "%s"' % (self.__names[tosock],
+ data))
+ tosock.send(data)
+ else:
+ for filter in self.filters:
+ filter(data, tosock, self.__output, self.__names[tosock])
+
+ def _do_transfer(self, fromsock, tosock):
+ data = fromsock.recv(BLOCKSIZE)
+ if not len(data):
+ self.__output('%s closed connection' % (self.__names[fromsock]))
+ fromsock.close()
+ self.__output('Closing connection %s' % (self.__names[tosock]))
+ tosock.close()
+ return -1
+ else:
+ self._send_data(data, tosock)
+
+ def do_transfer(self, selected, active_sockets):
+ deletion = 0
+ for sock in (self.__sock1, self.__sock2):
+ if sock in selected and sock in active_sockets and not deletion:
+ if sock == self.__sock1: othersock = self.__sock2
+ else: othersock = self.__sock1
+ if self._do_transfer(sock, othersock) == -1:
+ deletion = 1
+
+ if deletion:
+ del active_sockets[active_sockets.index(self.__sock1)]
+ del active_sockets[active_sockets.index(self.__sock2)]
+
+ return deletion
+
+ def add_filter(self, filterfunc):
+ self.filters.append(filterfunc)
+
+
+class TransferFilter:
+ def filter(self, data, tosock, output, sockname):
+ pass
+
Propchange: incubator/mod_ftp/trunk/utils/ftp_proxy/transfer_pair.py
------------------------------------------------------------------------------
svn:executable =
Added: incubator/mod_ftp/trunk/utils/static_build/Makefile.in
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/utils/static_build/Makefile.in?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/utils/static_build/Makefile.in (added)
+++ incubator/mod_ftp/trunk/utils/static_build/Makefile.in Thu Oct 6 06:16:28 2005
@@ -0,0 +1 @@
+include $(top_srcdir)/build/special.mk
Added: incubator/mod_ftp/trunk/utils/static_build/README
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/utils/static_build/README?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/utils/static_build/README (added)
+++ incubator/mod_ftp/trunk/utils/static_build/README Thu Oct 6 06:16:28 2005
@@ -0,0 +1,10 @@
+The files in this directory can be used to compile the FTP module statically
+into Apache. This procedure has not been automated, so you will need to do
+it by hand.
+
+Create the directory httpd-2.0/modules/ftp. Copy the config.m4 and
+Makefile.in files in this directory there. Then copy all .c files from
+mod_ftp/src and all .h files from mod_ftp/include into httpd-2.0/modules/ftp.
+
+Change into the toplevel Apache directory, rerun buildconf, then configure
+with --enable-ftp.
Added: incubator/mod_ftp/trunk/utils/static_build/config.m4
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/utils/static_build/config.m4?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/utils/static_build/config.m4 (added)
+++ incubator/mod_ftp/trunk/utils/static_build/config.m4 Thu Oct 6 06:16:28 2005
@@ -0,0 +1,21 @@
+APACHE_MODPATH_INIT(ftp)
+
+ftp_objs="dnl
+ftp_commands.lo dnl
+ftp_data_connection.lo dnl
+ftp_data_filters.lo dnl
+ftp_connection.lo dnl
+ftp_filters.lo dnl
+ftp_glob.lo dnl
+ftp_inet_pton.lo dnl
+ftp_limitlogin.lo dnl
+ftp_log.lo dnl
+ftp_message.lo dnl
+ftp_protocol.lo dnl
+ftp_request.lo dnl
+ftp_util.lo dnl
+mod_ftp.lo"
+
+APACHE_MODULE(ftp, FTP Server, $ftp_objs, , no)
+
+APACHE_MODPATH_FINISH
Added: incubator/mod_ftp/trunk/utils/stresstest/.cvsignore
URL: http://svn.apache.org/viewcvs/incubator/mod_ftp/trunk/utils/stresstest/.cvsignore?rev=306631&view=auto
==============================================================================
--- incubator/mod_ftp/trunk/utils/stresstest/.cvsignore (added)
+++ incubator/mod_ftp/trunk/utils/stresstest/.cvsignore Thu Oct 6 06:16:28 2005
@@ -0,0 +1 @@
+*~