Skip to content

Instantly share code, notes, and snippets.

@tjvr
Created June 21, 2016 13:57
Show Gist options
  • Save tjvr/0b4a4b277e9cc53db052782dd190f76d to your computer and use it in GitHub Desktop.
Save tjvr/0b4a4b277e9cc53db052782dd190f76d to your computer and use it in GitHub Desktop.
s2forums mitmproxy
import os
from mitmproxy.models import HTTPResponse, decoded
from mitmproxy.script import concurrent
from netlib.http import Headers
target = 'scratch.mit.edu'
target_cdn = 'cdn.scratch.mit.edu'
cdn_path = '/scratchr2/static/__c0f55e53b5d38e8912c777ed5b9c0030__/'
static_url = "//cdn.scratch.mit.edu/scratchr2/static/__c0f55e53b5d38e8912c777ed5b9c0030__/"
affected = {
'djangobb_forum/scratchblocks2/block_images/arrows.png',
'djangobb_forum/scratchblocks2/block_images/flag.png',
'djangobb_forum/scratchblocks2/menu.js',
'djangobb_forum/scratchblocks2/scratchblocks2.css',
'djangobb_forum/scratchblocks2/scratchblocks2.js',
'djangobb_forum/scratchblocks2/translations.js',
'djangobb_forum/js/markitup/sets/bbcode/set.js',
'djangobb_forum/scratchblocks/backpack.js',
'djangobb_forum/scratchblocks/menu.js',
'djangobb_forum/scratchblocks/scratchblocks.js',
'djangobb_forum/scratchblocks/translations.js',
}
patches = [
('/discuss/preview/', '.../templates/djangobb_forum/post_preview.html'),
('/discuss/', 'djangobb_forum/templates/djangobb_forum/base.html'),
]
@concurrent
def request(context, flow):
host = flow.request.pretty_host
path = flow.request.path
if host == target_cdn and path.startswith(cdn_path):
path = path[len(cdn_path):].lstrip('/')
if path not in affected:
return
file_path = 'djangobb_forum/static/' + path
if not os.path.exists(file_path):
flow.reply(HTTPResponse(
"HTTP/1.1", 404, "Not Found",
Headers(Content_Type="text/html"),
"Not found"
))
return
body = open(file_path).read()
resp = HTTPResponse(
"HTTP/1.1", 200, "OK",
Headers(Content_Type="text/html"),
body
)
flow.reply(resp)
@concurrent
def response(context, flow):
host = flow.request.pretty_host
path = flow.request.path
if host.endswith(target):
if 'discuss' not in path: return
if 'preview' in path:
with decoded(flow.response): # automatically decode gzipped responses.
flow.response.content = (flow.response.content
.replace('''<script type="text/javascript" src="{{ STATIC_URL }}/djangobb_forum/scratchblocks2/scratchblocks2.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}/djangobb_forum/scratchblocks2/translations.js" charset="utf-8"></script>'''.replace('{{ STATIC_URL }}', static_url),
'''<script type="text/javascript" src="{{ STATIC_URL }}/djangobb_forum/scratchblocks/scratchblocks.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}/djangobb_forum/scratchblocks/translations.js" charset="utf-8"></script>'''.replace('{{ STATIC_URL }}', static_url))
.replace('''<script type="text/javascript">
(function ($) {
var forum_langs = {13: "de", 14: "es", 15: "fr", 16: "zh_CN", 17: "pl",
18: "ja", 19: "nl", 20: "pt", 21: "it", 22: "he", 23: "ko", 24: "nb",
25: "tr", 26: "el", 27: "ru", 33: "ca", 36: "id"};
function match_path(path) {
return new RegExp("^/discuss/([0-9]+)/").exec(path);
}
var match = match_path(window.location.pathname);
if (!match) {
var links = $(".linkst ul a");
for (var i=0; i<links.length; i++) {
match = match_path($(links[i]).attr("href"));
if (match) break;
}
}
if (!match) return;
var forum_id = parseInt(match[1]);
var code = forum_langs[forum_id];
if (code in scratchblocks2._translations) {
scratchblocks2.load_language(scratchblocks2._translations[code]);
}
})(jQuery);
scratchblocks2.parse('pre.blocks');
</script>''', '''<script type="text/javascript">
(function ($) {
scratchblocks.renderMatching('pre.blocks', {
languages: ['en', 'de', 'es', 'fr', 'zh_CN', 'pl', 'ja', 'nl' , 'pt', 'it',
'he', 'ko', 'nb', 'tr', 'el', 'ru', 'ca', 'id'],
});
})(jQuery);
</script>''')
)
return
with decoded(flow.response): # automatically decode gzipped responses.
body = flow.response.content
# TODO apply diff
body = (body
.replace('<link href="{}/djangobb_forum/scratchblocks2/scratchblocks2.css" rel="stylesheet" />'.format(static_url), '')
.replace('<script type="text/javascript" src="{}/djangobb_forum/scratchblocks2/scratchblocks2.js"></script>'.format(static_url),
'<script type="text/javascript" src="{}/djangobb_forum/scratchblocks/scratchblocks.js"></script>'.format(static_url))
.replace('<script type="text/javascript" src="{}/djangobb_forum/scratchblocks2/translations.js" charset="utf-8"></script>'.format(static_url), '''
<script type="text/javascript" src="{}/djangobb_forum/scratchblocks/translations.js" charset="utf-8"></script>
<script type="text/javascript" src="{}/djangobb_forum/scratchblocks/backpack.js"></script>'''.format(static_url, static_url))
.replace('''<script type="text/javascript">
(function ($) {
scratchblocks2._currentLanguage = 'en';
var forum_langs = {13: "de", 14: "es", 15: "fr", 16: "zh_CN", 17: "pl",
18: "ja", 19: "nl", 20: "pt", 21: "it", 22: "he", 23: "ko", 24: "nb",
25: "tr", 26: "el", 27: "ru", 33: "ca", 36: "id"};
function match_path(path) {
return new RegExp("^/discuss/([0-9]+)/").exec(path);
}
var match = match_path(window.location.pathname);
if (!match) {
var links = $(".linkst ul a");
for (var i=0; i<links.length; i++) {
match = match_path($(links[i]).attr("href"));
if (match) break;
}
}
if (!match) return;
var forum_id = parseInt(match[1]);
var code = forum_langs[forum_id];
if (code in scratchblocks2._translations) {
scratchblocks2._currentLanguage = code;
scratchblocks2.load_language(scratchblocks2._translations[code]);
}
})(jQuery);
</script>''', '''<script type="text/javascript">
(function ($) {
scratchblocks._currentLanguage = 'en';
var forum_langs = {13: "de", 14: "es", 15: "fr", 16: "zh_CN", 17: "pl",
18: "ja", 19: "nl", 20: "pt", 21: "it", 22: "he", 23: "ko", 24: "nb",
25: "tr", 26: "el", 27: "ru", 33: "ca", 36: "id"};
function match_path(path) {
return new RegExp("^/discuss/([0-9]+)/").exec(path);
}
var match = match_path(window.location.pathname);
if (!match) {
var links = $(".linkst ul a");
for (var i=0; i<links.length; i++) {
match = match_path($(links[i]).attr("href"));
if (match) break;
}
}
scratchblocks._currentLanguages = ['en'];
if (match) {
var forum_id = parseInt(match[1]);
var code = forum_langs[forum_id];
if (code in scratchblocks.allLanguages) {
scratchblocks._currentLanguages = ['en', code];
}
}
})(jQuery);
</script>''')
.replace('<script type="text/javascript" src="{}/djangobb_forum/scratchblocks2/menu.js"></script>'.format(static_url),
'<script type="text/javascript" src="{}/djangobb_forum/scratchblocks/menu.js"></script>'.format(static_url))
.replace('''<script type="text/javascript">
$(document).ready(function() {
$(".markup").markItUp(mySettings);
scratchblocks2.parse('.scratchblocks-button ul a', {inline: true})
});
</script>''', '''<script type="text/javascript">
$(document).ready(function() {
$(".markup").markItUp(mySettings);
scratchblocks.renderMatching('.scratchblocks-button ul a', {
languages: ['en', 'de', 'es', 'fr', 'zh_CN', 'pl', 'ja', 'nl' , 'pt', 'it', 'he', 'ko', 'nb', 'tr', 'el', 'ru', 'ca', 'id'],
});
});
</script>''')
.replace("scratchblocks2.parse('pre.blocks');", """
scratchblocks.renderMatching('pre.blocks', {
languages: scratchblocks._currentLanguages,
replace: function(el, svg, doc, options) {
// add scratchblocks to `el`
scratchblocks.replace(el, svg, doc, options);
// backpack plugin
if (doc.scripts.length >= 1 && doc.scripts[0].blocks.length >= 2) {
var btn = scratchblocks.backpackButton(doc);
if (btn) {
btn.style.float = 'right';
el.insertBefore(btn, el.children[0]);
}
}
},
});""")
)
flow.response.content = body
@tjvr
Copy link
Author

tjvr commented Jun 21, 2016

Inside the s2forums repo, run:

$ mitmdump -p 3182 -s redirect.py

Set your computer's HTTPS proxy to localhost:3182

Once the proxy is working, visit the magic domain mitm.it and trust the special cert

Visit http://scratch.mit.edu/discuss/topic/14778/, and the proxy should magically give you new scratchblocks & the backpack plugin!

Thanks to @Hardmath123 for helping with this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment