1 import cherrypy
2
3
5 """Wraps a file-like object, returning '' when Content-Length is reached.
6
7 The cgi module's logic for reading multipart MIME messages doesn't
8 allow the parts to know when the Content-Length for the entire message
9 has been reached, and doesn't allow for multipart-MIME messages that
10 omit the trailing CRLF (Flash 8's FileReference.upload(url), for example,
11 does this). The read_lines_to_outerboundary function gets stuck in a loop
12 until the socket times out.
13
14 This rfile wrapper simply monitors the incoming stream. When a read is
15 attempted past the Content-Length, it returns an empty string rather
16 than timing out (of course, if the last read *overlaps* the C-L, you'll
17 get the last bit of data up to C-L, and then the next read will return
18 an empty string).
19 """
20
22 self.rfile = rfile
23 self.clen = clen
24 self.bytes_read = 0
25
26 - def read(self, size = None):
27 if self.clen:
28
29 if self.bytes_read >= self.clen:
30 return ''
31
32
33 new_bytes_read = self.bytes_read + size
34 if new_bytes_read > self.clen:
35 size = self.clen - self.bytes_read
36
37 data = self.rfile.read(size)
38 self.bytes_read += len(data)
39 return data
40
42 if size is not None:
43 if self.clen:
44
45 if self.bytes_read >= self.clen:
46 return ''
47
48
49 new_bytes_read = self.bytes_read + size
50 if new_bytes_read > self.clen:
51 size = self.clen - self.bytes_read
52
53 data = self.rfile.readline(size)
54 self.bytes_read += len(data)
55 return data
56
57
58
59 res = []
60 size = 256
61 while True:
62 if self.clen:
63
64 if self.bytes_read >= self.clen:
65 return ''.join(res)
66
67
68 new_bytes_read = self.bytes_read + size
69 if new_bytes_read > self.clen:
70 size = self.clen - self.bytes_read
71
72 data = self.rfile.readline(size)
73 self.bytes_read += len(data)
74 res.append(data)
75
76 if len(data) < size or data[-1:] == "\n":
77 return ''.join(res)
78
80
81 total = 0
82 lines = []
83 line = self.readline()
84 while line:
85 lines.append(line)
86 total += len(line)
87 if 0 < sizehint <= total:
88 break
89 line = self.readline()
90 return lines
91
94
97
99 if self.clen:
100
101 if self.bytes_read >= self.clen:
102 return ''
103
104 data = self.rfile.next()
105 self.bytes_read += len(data)
106 return data
107
108
110 """Wrap request.rfile in a reader that won't crash on no trailing CRLF."""
111 h = cherrypy.request.headers
112 if not h.get('Content-Type','').startswith('multipart/'):
113 return
114 if flash_only and not 'Shockwave Flash' in h.get('User-Agent', ''):
115 return
116
117 clen = h.get('Content-Length', '0')
118 try:
119 clen = int(clen)
120 except ValueError:
121 return
122 cherrypy.request.rfile = MultipartWrapper(cherrypy.request.rfile, clen)
123
128