/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/transport/http/response.py

merge bzr.dev r3564

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
 
24
24
 
25
25
import httplib
 
26
from cStringIO import StringIO
 
27
import rfc822
26
28
 
27
29
from bzrlib import (
28
30
    errors,
29
31
    trace,
 
32
    osutils,
30
33
    )
31
34
 
32
35
 
61
64
    # 8k chunks should be fine.
62
65
    _discarded_buf_size = 8192
63
66
 
 
67
    # maximum size of read requests -- used to avoid MemoryError issues in recv
 
68
    _max_read_size = 512 * 1024
 
69
 
64
70
    def __init__(self, path, infile):
65
71
        """Constructor.
66
72
 
102
108
            # string entity.
103
109
            # To be on the safe side we allow it before any boundary line
104
110
            boundary_line = self._file.readline()
 
111
 
105
112
        if boundary_line != '--' + self._boundary + '\r\n':
106
 
            raise errors.InvalidHttpResponse(
107
 
                self._path,
108
 
                "Expected a boundary (%s) line, got '%s'" % (self._boundary,
109
 
                                                             boundary_line))
 
113
            # rfc822.unquote() incorrectly unquotes strings enclosed in <>
 
114
            # IIS 6 and 7 incorrectly wrap boundary strings in <>
 
115
            # together they make a beautiful bug, which we will be gracious
 
116
            # about here
 
117
            if (self._unquote_boundary(boundary_line) != 
 
118
                '--' + self._boundary + '\r\n'):
 
119
                raise errors.InvalidHttpResponse(
 
120
                    self._path,
 
121
                    "Expected a boundary (%s) line, got '%s'"
 
122
                    % (self._boundary, boundary_line))
 
123
 
 
124
    def _unquote_boundary(self, b):
 
125
        return b[:2] + rfc822.unquote(b[2:-2]) + b[-2:]
110
126
 
111
127
    def read_range_definition(self):
112
128
        """Read a new range definition in a multi parts message.
182
198
        client to clean the socket if we leave bytes unread. This may occur for
183
199
        the final boundary line of a multipart response or for any range
184
200
        request not entirely consumed by the client (due to offset coalescing)
 
201
 
 
202
        :param size:  The number of bytes to read.  Leave unspecified or pass
 
203
            -1 to read to EOF.
185
204
        """
186
205
        if (self._size > 0
187
206
            and self._pos == self._start + self._size):
201
220
                    "Can't read %s bytes across range (%s, %s)"
202
221
                    % (size, self._start, self._size))
203
222
 
 
223
        # read data from file
 
224
        buffer = StringIO()
 
225
        limited = size
204
226
        if self._size > 0:
205
227
            # Don't read past the range definition
206
228
            limited = self._start + self._size - self._pos
207
229
            if size >= 0:
208
230
                limited = min(limited, size)
209
 
            data = self._file.read(limited)
210
 
        else:
211
 
            # Size of file unknown, the user may have specified a size or not,
212
 
            # we delegate that to the filesocket object (-1 means read until
213
 
            # EOF)
214
 
            data = self._file.read(size)
 
231
        osutils.pumpfile(self._file, buffer, limited, self._max_read_size)
 
232
        data = buffer.getvalue()
 
233
 
215
234
        # Update _pos respecting the data effectively read
216
235
        self._pos += len(data)
217
236
        return data