Skip to content

Commit f2d2492

Browse files
committed
issue2551243: Update schema-dump add anti-csrf headers
Also flake8 fixes and verified python2 support.
1 parent c8d3eba commit f2d2492

File tree

2 files changed

+76
-6
lines changed

2 files changed

+76
-6
lines changed

CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ Features:
7676
line processing of the mailgw script to ``argparse``. Note that the
7777
command line options of the mailgw have changed, see upgrading.txt for
7878
details. (Ralf Schlatterbeck)
79+
- issue2551243: schema-dump.py enhanced with anti-CSRF headers. Flake8
80+
cleanup and python2 support. (John Rouillard)
7981

8082
2022-07-13 2.2.0
8183

scripts/schema-dump.py

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,38 @@
44
Use recently documented XML-RPC API to dump
55
Roundup data schema in human readable form.
66
7+
Works with demo tracker using:
8+
9+
http://admin:admin@localhost:8917/demo/xmlrpc
10+
711
Future development may cover:
812
[ ] unreadable dump formats
913
[ ] access to local database
1014
[ ] lossless dump/restore cycle
11-
[ ] data dump and filtering with preserved
15+
[ ] data dump and filtering with preserved
16+
17+
Works in Python 2 as well.
1218
"""
1319
from __future__ import print_function
1420

1521
__license__ = "Public Domain"
16-
__version__ = "1.0"
22+
__version__ = "1.1"
1723
__authors__ = [
1824
"anatoly techtonik <[email protected]>"
25+
"John Rouillard <[email protected]>"
1926
]
2027

2128
import os
22-
import sys
23-
from roundup.anypy import xmlrpc_
2429
import pprint
30+
import sys
2531
import textwrap
32+
try:
33+
import urllib.parse as url_parser # python 3
34+
except ImportError:
35+
import urlparse as url_parser # python 2
36+
2637
from argparse import ArgumentParser
38+
from roundup.anypy import xmlrpc_
2739

2840
sname = os.path.basename(sys.argv[0])
2941
usage = """\
@@ -43,16 +55,19 @@
4355
--version
4456
""" % sname
4557

58+
4659
def format_pprint(var):
4760
return pprint.pformat(var)
4861

62+
4963
def format_json(var):
5064
jout = pprint.pformat(var)
5165
jout = jout.replace('"', "\\'") # " to \'
5266
jout = jout.replace("'", '"') # ' to "
5367
jout = jout.replace('\\"', "'") # \" to '
5468
return jout
5569

70+
5671
def format_yaml(var):
5772
out = pprint.pformat(var)
5873
out = out.replace('{', ' ')
@@ -80,7 +95,50 @@ def format_yaml(var):
8095
out2.append(line)
8196
out = '\n'.join(out2)
8297
return out
83-
98+
99+
100+
class SpecialTransport():
101+
"""Mixin for http/https transports to implement new send_content with
102+
CSRF prevention headers to both of them.
103+
"""
104+
def send_content(self, connection, request_body):
105+
connection.putheader("Referer", "%s://%s%s%s/" % (
106+
self.components.scheme,
107+
self.components.hostname,
108+
':' + str(self.components.port) if self.components.port else '',
109+
self.components.path))
110+
connection.putheader("Origin", "%s://%s%s" % (
111+
self.components.scheme, self.components.hostname,
112+
':' + str(self.components.port) if self.components.port else ''))
113+
connection.putheader("X-Requested-With", "XMLHttpRequest")
114+
115+
connection.putheader("Content-Type", "text/xml")
116+
connection.putheader("Content-Length", str(len(request_body)))
117+
connection.endheaders()
118+
if request_body:
119+
connection.send(request_body)
120+
121+
122+
class SpecialHttpTransport(SpecialTransport, xmlrpc_.client.Transport,
123+
object):
124+
"""SpecialTransport must be first to use its send_content. Explicit
125+
object inheritance required for python2 apparently."""
126+
def __init__(self, url):
127+
self.components = url_parser.urlparse(url)
128+
# works both python2 (with object inheritance) and python3
129+
super(SpecialHttpTransport, self).__init__(self)
130+
131+
132+
class SpecialHttpsTransport(SpecialTransport, xmlrpc_.client.SafeTransport,
133+
object):
134+
"""SpecialTransport must be first to use its send_content. Explicit
135+
object inheritance required for python2 apparently."""
136+
def __init__(self, url):
137+
self.components = url_parser.urlparse(url)
138+
# works both python2 (with object inheritance) and python3
139+
super(SpecialHttpsTransport, self).__init__(self)
140+
141+
84142
if __name__ == "__main__":
85143
parser = ArgumentParser()
86144
parser.add_argument("url", nargs=1)
@@ -92,7 +150,17 @@ def format_yaml(var):
92150
if args.version:
93151
sys.exit(sname + " " + __version__)
94152

95-
roundup_server = xmlrpc_.client.ServerProxy(args.url[0], allow_none=True)
153+
if args.url[0].lower().startswith('https:'):
154+
transport = SpecialHttpsTransport
155+
else:
156+
transport = SpecialHttpTransport
157+
158+
roundup_server = xmlrpc_.client.ServerProxy(
159+
args.url[0],
160+
transport=transport(args.url[0]),
161+
verbose=False,
162+
allow_none=True)
163+
96164
schema = roundup_server.schema()
97165
if args.raw:
98166
print(str(schema))

0 commit comments

Comments
 (0)