[apt-proxy-devel] r639 - in trunk: apt_proxy apt_proxy/test debian

Chris Halls halls at alioth.debian.org
Tue Jan 9 12:08:37 CET 2007


Author: halls
Date: Tue Jan  9 12:08:37 2007
New Revision: 639

Added:
   trunk/apt_proxy/test/test_clients.py
Modified:
   trunk/apt_proxy/cache.py
   trunk/apt_proxy/clients.py
   trunk/apt_proxy/fetchers.py
   trunk/apt_proxy/test/test_apt_proxy.py
   trunk/debian/changelog
Log:
* Merge ftpFetcher fix from NMU
* Add unit test for invalid character detetion, and fix it in clients.py
* Add file transfer fail callback when serving a file from cache so errors can be logged


Modified: trunk/apt_proxy/cache.py
==============================================================================
--- trunk/apt_proxy/cache.py	(original)
+++ trunk/apt_proxy/cache.py	Tue Jan  9 12:08:37 2007
@@ -302,8 +302,12 @@
 
                 for request in self.requests:
                     if request.start_streaming(size, mtime):
-                        basic.FileSender().beginFileTransfer(self.streamfile, request) \
-                                        .addBoth(self.file_transfer_complete, request, self.file_path)
+                        log.debug("Streaming " + self.file_path)
+                        d = basic.FileSender().beginFileTransfer(self.streamfile, request)
+                        d.addCallback(self.file_transfer_complete, request, self.file_path)
+                        d.addErrback(self.file_transfer_fail, request, self.file_path)
+                    else:
+                        log.debug("No need to stream " + self.file_path)
             else:
                 log.debug("Sending empty file to clients:%s" % (self.file_path), 'CacheEntry')
                 for request in self.requests:
@@ -313,8 +317,15 @@
             log.debug("Unexpected error: %s" % (e), 'CacheEntry')
             raise
 
+    def file_transfer_fail(self, result, request, filename):
+        log.err("transfer FAILED: %s %s" % (result, filename), 'CacheEntry')
+        request.finish()
+        if len(self.requests)==0:
+            # Last file was sent
+            self.file_sent()
+
     def file_transfer_complete(self, result, request, filename):
-        log.debug("transfer complete: " + filename, 'CacheEntry')
+        log.debug("transfer complete: %s %s" % (result, filename), 'CacheEntry')
         request.finish()
         if len(self.requests)==0:
             # Last file was sent

Modified: trunk/apt_proxy/clients.py
==============================================================================
--- trunk/apt_proxy/clients.py	(original)
+++ trunk/apt_proxy/clients.py	Tue Jan  9 12:08:37 2007
@@ -55,9 +55,10 @@
         """
         self.uri = self.clean_path(self.uri)
 
-        if re.search(self.uri, '[^a-zA-Z0-9~,.+%:;@#?{}[]()$-]'):
-            log.err("Invalid characters found in filename")
-            self.finishCode(http.FORBIDDEN, "Invalid characters in filename")
+        match = re.search('[^][a-zA-Z0-9~,.+%:;@#?{}()$/_-]', self.uri)
+        if match:
+            log.err("Invalid characters found in filename at position %s" % (match.start()))
+            self.finishCode(http.FORBIDDEN, "Invalid character in filename at position %s" % (match.start()))
             return
 
         if_modified_since = self.getHeader('if-modified-since')
@@ -235,6 +236,9 @@
         self.remove_from_cache_entry()
 
     def finish(self):
+        self.disconnect()
+        
+    def disconnect(self):
         self.dest.download_data_end()
         self.remove_from_cache_entry()
         
@@ -250,7 +254,7 @@
         if self.dest.file_mtime is not None and mtime < self.dest.file_mtime:
             log.debug("Skipping decompression of file (%s mtime=%s), destination file (%s, mtime=%s) is newer" 
                                 % (self.source.path, mtime, self.dest.filename, self.dest.file_mtime), self.logname)
-            self.finish()
+            self.disconnect()
             return False
         
         log.debug("Decompressing %s -> %s" % (self.source.path, self.dest.filename), self.logname)
@@ -266,7 +270,7 @@
             return False
 
     def write(self, data):
-        log.debug("Decompressing %s bytes" % (len(data)), self.logname)
+        log.debug("Decompressing %s bytes (%s)" % (len(data), self.source.cache_path), self.logname)
         uncompressed = self.uncompress(data)
         self.dest.download_data_received(uncompressed)
         

Modified: trunk/apt_proxy/fetchers.py
==============================================================================
--- trunk/apt_proxy/fetchers.py	(original)
+++ trunk/apt_proxy/fetchers.py	Tue Jan  9 12:08:37 2007
@@ -657,11 +657,11 @@
 
     def ftpListResult(self, msg):
         __pychecker__ = 'unusednames=msg'
-        if len(filelist.files)== 0:
+        if len(self.filelist.files)== 0:
             log.debug("Not found on backend server",'ftp_client')
             self.parent.file_not_found()
             return
-        file = filelist.files[0]
+        file = self.filelist.files[0]
         self.parent.server_size(file['size'])
         fetcher.ftpFetchFile()
 

Modified: trunk/apt_proxy/test/test_apt_proxy.py
==============================================================================
--- trunk/apt_proxy/test/test_apt_proxy.py	(original)
+++ trunk/apt_proxy/test/test_apt_proxy.py	Tue Jan  9 12:08:37 2007
@@ -329,14 +329,3 @@
         backend = self.factory.getBackend('test_usernames')
         self.assertEquals(self.backend2.uris[0].password,'thePassword')
         self.assertEquals(self.backend2.uris[1].password,'theFtpPassword')
-
-class testRequests(unittest.TestCase):
-    def setUp(self):
-        class DummyChannel:
-            factory = None
-            transport = None
-        self.req = HttpRequestClient(DummyChannel(), None)
-    def testSimplifyPath(self):
-        self.assertEquals(self.req.clean_path('/foo/bar/../baz'), '/foo/baz')
-    def testRemoveHost(self):
-        self.assertEquals(self.req.clean_path('http://test:1234/foo/bar'), '/foo/bar')

Added: trunk/apt_proxy/test/test_clients.py
==============================================================================
--- (empty file)
+++ trunk/apt_proxy/test/test_clients.py	Tue Jan  9 12:08:37 2007
@@ -0,0 +1,89 @@
+#
+# Copyright (C) 2007 Chris Halls <halls at debian.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""Unit test for clients.py"""
+
+import exceptions
+
+from twisted.trial import unittest
+from twisted.internet import reactor
+from twisted.web import http
+
+from apt_proxy.clients import HttpRequestClient
+from apt_proxy.misc import log
+
+class DummyFileType:
+    contype = None
+
+class DummyCacheEntry:
+    filetype = DummyFileType()
+
+class DummyBackend:
+    base = 'dummy'
+    uris = ['dummy']
+    def get_cache_entry(self, path):
+        return DummyCacheEntry()
+
+class DummyFactory:
+    def getBackend(self, name):
+        return DummyBackend()
+
+class DummyChannel:
+    factory = DummyFactory()
+    transport = None
+
+class testRequests(unittest.TestCase):
+    def setUp(self):
+        self.req = HttpRequestClient(DummyChannel(), None)
+    def testSimplifyPath(self):
+        self.assertEquals(self.req.clean_path('/foo/bar/../baz'), '/foo/baz')
+    def testRemoveHost(self):
+        self.assertEquals(self.req.clean_path('http://test:1234/foo/bar'), '/foo/bar')
+
+def dummyFinishCode(responseCode, message=None):
+        global FinishCode
+        log.debug("finishCode: %s, %s" % (responseCode, message))
+        FinishCode = responseCode
+
+class testErrors(unittest.TestCase):
+    def setUp(self):
+        global FinishCode
+        self.req = HttpRequestClient(DummyChannel(), None)
+        self.req.finishCode = dummyFinishCode # Hijack finishCode
+        self.req.method = 'GET'
+        FinishCode = None
+    def testInvalidChars(self):
+        global FinishCode
+        for c in '!' '"' '*' '\n' '\0' '\001':
+            log.debug("testing invalid character [%s]" % (c))
+            self.req.uri = 'http://host/backend/test' + c + 'ing'
+            self.req.process()
+            self.assertEquals(FinishCode, http.FORBIDDEN)
+    def testValidRequests(self):
+        global FinishCode
+        for uri in [
+                        'http://aptproxy:9999/debian/dists/testing/main/binary-i386/Packages.gz',
+                        'http://aptproxy:9999/debian/pool/main/i/imagemagick/libmagick++9c2a_6.2.4.5.dfsg1-0.13_i386.deb',
+                        'http://aptproxy:9999/debian/pool/main/u/utf8-migration-tool/utf8-migration-tool_0.4.3_all.deb'
+                        ]:
+            log.debug("testing valid uri [%s]" % (uri))
+            self.req.uri = uri
+            try:
+                self.req.process()
+            except exceptions.AttributeError, e:
+                log.debug("AttributeError exception caught - URI was validated")
+            self.assertEquals(FinishCode, None)
+            
\ No newline at end of file

Modified: trunk/debian/changelog
==============================================================================
--- trunk/debian/changelog	(original)
+++ trunk/debian/changelog	Tue Jan  9 12:08:37 2007
@@ -15,6 +15,7 @@
     Thanks Jason Thomas for the patch (Closes: #348985)
   * Uncompress Packages.gz and Packages.bz2 on the fly, and
     update databases from these files (Closes: #TODO)
+  * Acknowledge NMU by Steinar H. Gunderson, thanks! (Closes: #386344)
 
   [ Mark Sheppard ]
   * Generate an error if a client attempts to retrieve



More information about the apt-proxy-devel mailing list