Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sqlmapproject
GitHub Repository: sqlmapproject/sqlmap
Path: blob/master/thirdparty/multipart/multipartpost.py
2992 views
1
#!/usr/bin/env python
2
3
"""
4
02/2006 Will Holcomb <[email protected]>
5
6
Reference: http://odin.himinbi.org/MultipartPostHandler.py
7
8
This library is free software; you can redistribute it and/or
9
modify it under the terms of the GNU Lesser General Public
10
License as published by the Free Software Foundation; either
11
version 2.1 of the License, or (at your option) any later version.
12
13
This library is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
Lesser General Public License for more details.
17
18
You should have received a copy of the GNU Lesser General Public
19
License along with this library; if not, write to the Free Software
20
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
"""
22
23
import io
24
import mimetypes
25
import os
26
import re
27
import stat
28
import sys
29
30
from lib.core.compat import choose_boundary
31
from lib.core.convert import getBytes
32
from lib.core.exception import SqlmapDataException
33
from thirdparty.six.moves import urllib as _urllib
34
35
# Controls how sequences are uncoded. If true, elements may be given
36
# multiple values by assigning a sequence.
37
doseq = True
38
39
40
class MultipartPostHandler(_urllib.request.BaseHandler):
41
handler_order = _urllib.request.HTTPHandler.handler_order - 10 # needs to run first
42
43
def http_request(self, request):
44
data = request.data
45
46
if isinstance(data, dict):
47
v_files = []
48
v_vars = []
49
50
try:
51
for(key, value) in data.items():
52
if hasattr(value, "fileno") or hasattr(value, "file") or isinstance(value, io.IOBase):
53
v_files.append((key, value))
54
else:
55
v_vars.append((key, value))
56
except TypeError:
57
systype, value, traceback = sys.exc_info()
58
raise SqlmapDataException("not a valid non-string sequence or mapping object '%s'" % traceback)
59
60
if len(v_files) == 0:
61
data = _urllib.parse.urlencode(v_vars, doseq)
62
else:
63
boundary, data = self.multipart_encode(v_vars, v_files)
64
contenttype = "multipart/form-data; boundary=%s" % boundary
65
#if (request.has_header("Content-Type") and request.get_header("Content-Type").find("multipart/form-data") != 0):
66
# print "Replacing %s with %s" % (request.get_header("content-type"), "multipart/form-data")
67
request.add_unredirected_header("Content-Type", contenttype)
68
69
request.data = data
70
71
# NOTE: https://github.com/sqlmapproject/sqlmap/issues/4235
72
if request.data:
73
for match in re.finditer(b"(?i)\\s*-{20,}\\w+(\\s+Content-Disposition[^\\n]+\\s+|\\-\\-\\s*)", request.data):
74
part = match.group(0)
75
if b'\r' not in part:
76
request.data = request.data.replace(part, part.replace(b'\n', b"\r\n"))
77
78
return request
79
80
def multipart_encode(self, vars, files, boundary=None, buf=None):
81
if boundary is None:
82
boundary = choose_boundary()
83
84
if buf is None:
85
buf = b""
86
87
for (key, value) in vars:
88
if key is not None and value is not None:
89
buf += b"--%s\r\n" % getBytes(boundary)
90
buf += b"Content-Disposition: form-data; name=\"%s\"" % getBytes(key)
91
buf += b"\r\n\r\n" + getBytes(value) + b"\r\n"
92
93
for (key, fd) in files:
94
file_size = fd.len if hasattr(fd, "len") else os.fstat(fd.fileno())[stat.ST_SIZE]
95
filename = fd.name.split("/")[-1] if "/" in fd.name else fd.name.split("\\")[-1]
96
try:
97
contenttype = mimetypes.guess_type(filename)[0] or b"application/octet-stream"
98
except:
99
# Reference: http://bugs.python.org/issue9291
100
contenttype = b"application/octet-stream"
101
buf += b"--%s\r\n" % getBytes(boundary)
102
buf += b"Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n" % (getBytes(key), getBytes(filename))
103
buf += b"Content-Type: %s\r\n" % getBytes(contenttype)
104
# buf += b"Content-Length: %s\r\n" % file_size
105
fd.seek(0)
106
107
buf += b"\r\n%s\r\n" % fd.read()
108
109
buf += b"--%s--\r\n\r\n" % getBytes(boundary)
110
buf = getBytes(buf)
111
112
return boundary, buf
113
114
https_request = http_request
115
116