[Twisted-Python] WebConduit
Donovan Preston
twisted-python@twistedmatrix.com
Wed, 31 Jul 2002 22:34:57 -0700
> This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.
--B_3110999713_642980
Content-type: text/plain; charset="US-ASCII"
Content-transfer-encoding: 7bit
I developed this as a proof of concept and several people have expressed
interest in seeing the implementation, so I thought I'd clean it up a little
and send it to the list.
The WebConduit is a project that I have been thinking about doing for
several years now. Basically, it allows users to interact with a MUD server
from a web page without any silly Java applets or frames that reload every 5
seconds.
It does rely heavily on JavaScript to work, specifically it relies on the
later browser's ability to have JavaScript affect the contents of the page
after it has loaded. It also uses a trick pioneered by KnowNow,
www.knownow.com, of opening a frame to a page on the server which the server
never finishes sending to the browser. Using this technique, the Twisted
server can push new JavaScript commands to this iframe in response to events
on the remote server, and these JavaScript commands can in turn affect the
DOM of the main page.
It also uses another iframe to send commands to the twisted server.
JavaScript can set the src attribute of the iframe and use GET parameters to
send arbitrary variables to Twisted. Since all three iframes are coming from
the same browser, the browser sends the same cookie with all three requests.
Each request on the server then has access to the same Session object, and
the three frames can communicate using this session object.
That's about it, I'm pretty proud of the result. Enhoy.
Donovan
P.s. Put the rpy, js, and html files in a directory served by twisted.web,
and put the py file on your PYTHONPATH somewhere.
--B_3110999713_642980
Content-type: multipart/appledouble; boundary="B_3110999697_630578"
--B_3110999697_630578
Content-type: application/applefile; name="WebConduit.rpy"
Content-transfer-encoding: base64
Content-disposition: attachment
AAUWBwACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAJAAAAPgAAACAAAAADAAAAXgAAAA4AAAAC
AAAAbAAAAX5URVhUUipjaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFdlYkNvbmR1aXQucnB5
AAABAAAAAUwAAABMAAAAMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgADFZlcmRhbmEA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYABABaAU4C9gPIAFoBTgL2A8i5Z6/mAAAASQAA
AEkAAAAAAQAAAAEAAAABTAAAAEwAAAAyACbAkBHzAAAAHAAyAABNUFNSAAAACgPt//8AAAAA
AiCgvA==
--B_3110999697_630578
Content-type: text/plain; name="WebConduit.rpy";
x-mac-creator="522A6368";
x-mac-type="54455854"
Content-disposition: attachment
Content-transfer-encoding: base64
IyBXZWJDb25kdWl0LnJweQoKaW1wb3J0IHdlYmNvbmR1aXQKCnJlc291cmNlID0gd2ViY29u
ZHVpdC5NV2ViQ29uZHVpdCgpCg==
--B_3110999697_630578--
--B_3110999713_642980
Content-type: multipart/appledouble; boundary="B_3110999700_687440"
--B_3110999700_687440
Content-type: application/applefile; name="conduit.html"
Content-transfer-encoding: base64
Content-disposition: attachment
AAUWBwACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAJAAAAPgAAACAAAAADAAAAXgAAAAwAAAAC
AAAAagAAAX5URVhUUipjaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGNvbmR1aXQuaHRtbAAA
AQAAAAFMAAAATAAAADIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAxWZXJkYW5hAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAQAVQDZArYDjgBVANkCtgOOuW4OWAAAAPwAAAD8
AAAAAAEAAAABAAAAAUwAAABMAAAAMgAmwJAC3gAAABwAMgAATVBTUgAAAAoD7f//AAAAAAH6
WBQ=
--B_3110999700_687440
Content-type: text/plain; name="conduit.html";
x-mac-creator="522A6368";
x-mac-type="54455854"
Content-disposition: attachment
Content-transfer-encoding: base64
PGh0bWw+CjxoZWFkPgo8bWV0YSBodHRwLWVxdWl2PSJDb250ZW50LVR5cGUiIGNvbnRlbnQ9
InRleHQvaHRtbDsgIGNoYXJzZXQ9SVNPLTg4NTktMSIgLz4KPHRpdGxlPkNvbnRyb2xsZXI8
L3RpdGxlPgoKPHNjcmlwdCBsYW5ndWFnZT0iSmF2YVNjcmlwdDEuMiIgc3JjPSIvY29uZHVp
dC5qcyI+Cjwvc2NyaXB0PgoKPC9oZWFkPgo8Ym9keSBiZ2NvbG9yPSIjRkZGRkZGIiBvbmxv
YWQ9ImZvY3VzSW5wdXQoKSI+Cgo8ZGl2IGlkPSJjb250ZW50IiBzdHlsZT0iYm9yZGVyOiBn
cmVlbiBzb2xpZCAxcHg7IHdpZHRoOiAxMDAlOyI+CjwvZGl2PgoKPGlucHV0IHR5cGU9InRl
eHQiIGlkPSJpbnB1dFRleHQiIC8+CjxpbnB1dCB0eXBlPSJidXR0b24iIHZhbHVlPSJTZW5k
IiBvbmNsaWNrPSJzZW5kKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdpbnB1dFRleHQnKS52
YWx1ZSkiIC8+Cgo8YnIgLz4KPHNwYW4gc3R5bGU9IndpZHRoOiA0NSUiPklucHV0PC9zcGFu
Pgo8c3BhbiBzdHlsZT0id2lkdGg6IDQ1JSI+T3V0cHV0PC9zcGFuPgo8YnIgLz4KPGlmcmFt
ZSBpZD0iaW5wdXQiIHNyYz0iL2lucHV0Lmh0bWwiIHN0eWxlPSJ3aWR0aDogNDUlOyBoZWln
aHQ6IDQ4cHQiPgo8L2lmcmFtZT4KPGlmcmFtZSBpZD0ib3V0cHV0IiBzcmM9Ij9vdXRwdXQ9
MSIgc3R5bGU9IndpZHRoOiA0NSU7IGhlaWdodDogNDhwdCI+CjwvaWZyYW1lPgoKPC9ib2R5
Pgo8L2h0bWw+Cg==
--B_3110999700_687440--
--B_3110999713_642980
Content-type: multipart/appledouble; boundary="B_3110999703_648571"
--B_3110999703_648571
Content-type: application/applefile; name="conduit.js"
Content-transfer-encoding: base64
Content-disposition: attachment
AAUWBwACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAJAAAAPgAAACAAAAADAAAAXgAAAAoAAAAC
AAAAaAAAAX5URVhUUipjaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGNvbmR1aXQuanMAAAEA
AAABTAAAAEwAAAAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAMVmVyZGFuYQAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAABgAEAC8BWQLLA9MALwFZAssD07luDnMAAAIpAAACKQAA
AAABAAAAAQAAAAFMAAAATAAAADIAJsCQAwEAAAAcADIAAE1QU1IAAAAKA+3//wAAAAAB+lnc
--B_3110999703_648571
Content-type: text/plain; name="conduit.js";
x-mac-creator="522A6368";
x-mac-type="54455854"
Content-disposition: attachment
Content-transfer-encoding: base64
ZnVuY3Rpb24gb25rZXlldmVudCh0aGVFdmVudCkKeyAJCiAgICBpZiAoIXRoZUV2ZW50KSB7
CiAgICAgICAgdGhlRXZlbnQgPSBldmVudAogICAgfQoJY29kZSA9IHRoZUV2ZW50LmtleUNv
ZGU7CglpZiAoY29kZT09MTMpIHsKCQl2YXIgaW5wdXRUZXh0ID0gZG9jdW1lbnQuZ2V0RWxl
bWVudEJ5SWQoJ2lucHV0VGV4dCcpCgkJc2VuZChpbnB1dFRleHQudmFsdWUpCgl9Cn0KCmZ1
bmN0aW9uIHNlbmQoc3R1ZmYpIHsKICAgIGlmIChzdHVmZikgewogICAgICAgIGRvY3VtZW50
LmdldEVsZW1lbnRCeUlkKCJpbnB1dCIpLnNyYyA9ICI/aW5wdXQ9IiArIGVzY2FwZShzdHVm
ZikKICAgICAgICB3cml0ZSgiLT4gIiArIHN0dWZmKQogICAgICAgIHZhciBpbnB1dFRleHQg
PSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiaW5wdXRUZXh0IikKICAgICAgICBpbnB1dFRl
eHQudmFsdWUgPSAiIgogICAgICAgIGlucHV0VGV4dC5mb2N1cygpCiAgICB9Cn0KCmZ1bmN0
aW9uIHJlY3Yoc3R1ZmYpIHsKICAgIHZhciBvdXRwdXQgPSBkb2N1bWVudC5nZXRFbGVtZW50
QnlJZCgiY29udGVudCIpCi8vIFdvcmtzIG9uIGllIG1hYyBhbmQgbW96aWxsYSBidXQgbm90
IGFzIHdlbGwgb24gaWUgd2luCi8vICAgIG91dHB1dC5hcHBlbmRDaGlsZChkb2N1bWVudC5j
cmVhdGVUZXh0Tm9kZSh1bmVzY2FwZShzdHVmZikpKQovLyAgICBvdXRwdXQuYXBwZW5kQ2hp
bGQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiYnIiKSkKLy8gV29ya3Mgb24gaWUgd2luICYg
bWFjLCBhbmQgbW96aWxsYSwgYnV0IGlzIGEgYml0IHNsb3dlcgogICAgb3V0cHV0LmlubmVy
SFRNTCA9IG91dHB1dC5pbm5lckhUTUwgKyB1bmVzY2FwZShzdHVmZikgKyAnPGJyIFw+Jwog
ICAgd2luZG93LnNjcm9sbEJ5KDAsIHdpbmRvdy5pbm5lckhlaWdodCkKfQoKZnVuY3Rpb24g
Zm9jdXNJbnB1dCgpIHsKICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdpbnB1dFRleHQn
KS5mb2N1cygpCn0KCmRvY3VtZW50Lm9ua2V5cHJlc3MgPSBvbmtleWV2ZW50Cg==
--B_3110999703_648571--
--B_3110999713_642980
Content-type: multipart/appledouble; boundary="B_3110999706_627974"
--B_3110999706_627974
Content-type: application/applefile; name="input.html"
Content-transfer-encoding: base64
Content-disposition: attachment
AAUWBwACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAJAAAAPgAAACAAAAADAAAAXgAAAAoAAAAC
AAAAaAAAAX5URVhUUipjaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGlucHV0Lmh0bWwAAAEA
AAABTAAAAEwAAAAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAMVmVyZGFuYQAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAABgAEAC8AtQL9Ay8ALwC1Av0DL7lsyiEAAAAoAAAAKAAA
AAABAAAAAQAAAAFMAAAATAAAADIAJsCQAeEAAAAcADIAAE1QU1IAAAAKA+3//wAAAAAB6j78
--B_3110999706_627974
Content-type: text/plain; name="input.html";
x-mac-creator="522A6368";
x-mac-type="54455854"
Content-disposition: attachment
Content-transfer-encoding: base64
PGh0bWw+CndlbGNvbWUuIHRoaXMgaXMgdGhlIGlucHV0IGlmcmFtZQo8L2h0bWw+
--B_3110999706_627974--
--B_3110999713_642980
Content-type: multipart/appledouble; boundary="B_3110999709_669768"
--B_3110999709_669768
Content-type: application/applefile; name="webconduit.py"
Content-transfer-encoding: base64
Content-disposition: attachment
AAUWBwACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAJAAAAPgAAACAAAAADAAAAXgAAAA0AAAAC
AAAAawAAAX5URVhUUipjaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHdlYmNvbmR1aXQucHkA
AAEAAAABTAAAAEwAAAAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAMVmVyZGFuYQAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAEAC8AXwL0A7kALwBfAvQDublsyuwAAABwAAAA
cAAAAAABAAAAAQAAAAFMAAAATAAAADIAJsCQAfsAAAAcADIAAE1QU1IAAAAKA+3//wAAAAAB
6jLI
--B_3110999709_669768
Content-type: text/plain; name="webconduit.py";
x-mac-creator="522A6368";
x-mac-type="54455854"
Content-disposition: attachment
Content-transfer-encoding: base64
IyBXZWJDb25kdWl0Cgpmcm9tIHR3aXN0ZWQud2ViIGltcG9ydCB3bXZjCmZyb20gdHdpc3Rl
ZC53ZWIgaW1wb3J0IHNlcnZlcgpmcm9tIHR3aXN0ZWQucHl0aG9uIGltcG9ydCBjb21wb25l
bnRzCmZyb20gdHdpc3RlZC5pbnRlcm5ldCBpbXBvcnQgcHJvdG9jb2wKZnJvbSB0d2lzdGVk
LmludGVybmV0IGltcG9ydCByZWFjdG9yCgoKUkVNT1RFX0FERFJFU1MgPSAibGFtYmRhLm1v
by5tdWQub3JnIgpSRU1PVEVfUE9SVCA9IDg4ODgKCgpjbGFzcyBJQ29uZHVpdFNlc3Npb24o
Y29tcG9uZW50cy5JbnRlcmZhY2UpOgogICAgIiIiCiAgICBBIHVuaXF1ZSBzZXNzaW9uIG5h
bWVzcGFjZSBmb3IgdGhlIGNvbmR1aXQuCiAgICAiIiIKICAgIGRlZiBzZXRSZXF1ZXN0KHJl
cXVlc3QpOgogICAgICAgICIiIlNldCB0aGUgd2ViIHJlcXVlc3Qgb2JqZWN0IHRvIHdoaWNo
IG91dHB1dCB3cml0dGVuIHRvIHRoaXMgY29uZHVpdCB3aWxsIGJlIHNlbnQuCiAgICAgICAg
VW50aWwgdGhpcyBpcyBjYWxsZWQsIG91dHB1dCB3aWxsIGJlIGNhY2hlZDsgYWZ0ZXIgdGhp
cyBpcyBjYWxsZWQsIHRoZSBiZWhhdmlvciBvZiBjYWxsaW5nCiAgICAgICAgaXQgYWdhaW4g
aXMgdW5kZWZpbmVkLgogICAgICAgICIiIgogICAgCiAgICBkZWYgaW5wdXQoYXJnKToKICAg
ICAgICAiIiJTZW5kIGlucHV0IHRvIHRoZSBjb25kdWl0LgogICAgICAgICIiIgogICAgCiAg
ICBkZWYgb3V0cHV0KGFyZyk6CiAgICAgICAgIiIiU2VuZCBvdXRwdXQgZnJvbSB0aGUgY29u
ZHVpdCB0byB0aGUgd2ViIGJyb3dzZXIuCiAgICAgICAgIiIiCgoKY2xhc3MgQ29uZHVpdFNl
c3Npb24ocHJvdG9jb2wuUHJvdG9jb2wpOgogICAgX19pbXBsZW1lbnRzX18gPSBJQ29uZHVp
dFNlc3Npb24KICAgIGRlZiBfX2luaXRfXyhzZWxmLCBzZXNzaW9uKToKICAgICAgICBzZWxm
LmNhY2hlZCA9IFtdCiAgICAgICAgc2VsZi5yZXF1ZXN0ID0gTm9uZQogICAgICAgIHJlYWN0
b3IuY2xpZW50VENQKFJFTU9URV9BRERSRVNTLCBSRU1PVEVfUE9SVCwgc2VsZikKCiAgICBk
ZWYgc2V0UmVxdWVzdChzZWxmLCByZXF1ZXN0KToKICAgICAgICBzZWxmLnJlcXVlc3QgPSBy
ZXF1ZXN0CiAgICAgICAgZm9yIGl0ZW0gaW4gc2VsZi5jYWNoZWQ6CiAgICAgICAgICAgIHNl
bGYub3V0cHV0KGl0ZW0pCgogICAgZGVmIGlucHV0KHNlbGYsIGFyZyk6CiAgICAgICAgc2Vs
Zi53cml0ZShhcmcpCgogICAgZGVmIG91dHB1dChzZWxmLCBhcmcpOgogICAgICAgIGlmIHNl
bGYucmVxdWVzdCBpcyBOb25lOgogICAgICAgICAgICBzZWxmLmNhY2hlZC5hcHBlbmQoYXJn
KQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIGFyZyA9IGFyZy5yZXBsYWNlKCInIiwgIlxc
JyIpCiAgICAgICAgICAgIHNlbGYucmVxdWVzdC53cml0ZShhcmcrJzxzY3JpcHQgbGFuZ3Vh
Z2U9IkphdmFTY3JpcHQxLjIiPicgKyAidG9wLnJlY3YoJyIgKyBhcmcgKyAiJyk8L3Njcmlw
dD5cclxuIikKCiAgICBkZWYgZGF0YVJlY2VpdmVkKHNlbGYsIGRhdGEpOgogICAgICAgIGxp
bmVzID0gZGF0YS5zcGxpdCgnXG4nKQogICAgICAgIGZvciBsaW5lIGluIGxpbmVzOgogICAg
ICAgICAgICBzZWxmLm91dHB1dChsaW5lLnN0cmlwKCkpCgogICAgZGVmIHdyaXRlKHNlbGYs
IGRhdGEpOgogICAgICAgIHNlbGYudHJhbnNwb3J0LndyaXRlKGRhdGEgKyAnXG4nKQoKCmNv
bXBvbmVudHMucmVnaXN0ZXJBZGFwdGVyKENvbmR1aXRTZXNzaW9uLCBzZXJ2ZXIuU2Vzc2lv
biwgSUNvbmR1aXRTZXNzaW9uKQoKCmNsYXNzIE1XZWJDb25kdWl0KHdtdmMuV01vZGVsKToK
ICAgIHBhc3MKCgpjbGFzcyBWV2ViQ29uZHVpdCh3bXZjLldWaWV3KToKICAgIHRlbXBsYXRl
RmlsZSA9ICJjb25kdWl0Lmh0bWwiCgoKY2xhc3MgQ1dlYkNvbmR1aXQod212Yy5XQ29udHJv
bGxlcik6CiAgICBkZWYgcmVuZGVyKHNlbGYsIHJlcXVlc3QpOgogICAgICAgIHNlc3Npb24g
PSByZXF1ZXN0LmdldFNlc3Npb24oSUNvbmR1aXRTZXNzaW9uKQogICAgICAgIGlucHV0ID0g
cmVxdWVzdC5hcmdzLmdldCgiaW5wdXQiLCBbTm9uZV0pWzBdCiAgICAgICAgaWYgaW5wdXQ6
CiAgICAgICAgICAgIHNlc3Npb24uaW5wdXQoaW5wdXQpCiAgICAgICAgICAgIHJldHVybiAi
PGh0bWw+JXMgc2VudC48L2h0bWw+IiAlIGlucHV0CiAgICAgICAgb3V0cHV0ID0gcmVxdWVz
dC5hcmdzLmdldCgib3V0cHV0IiwgW05vbmVdKVswXQogICAgICAgIGlmIG91dHB1dDoKICAg
ICAgICAgICAgc2Vzc2lvbi5zZXRSZXF1ZXN0KHJlcXVlc3QpCiAgICAgICAgICAgIHNlc3Np
b24ub3V0cHV0KCI8aHRtbD5PdXRwdXQgY29ubmVjdGVkIikKICAgICAgICAgICAgIyBXZSds
bCBuZXZlciBiZSBkb25lIQogICAgICAgICAgICByZXR1cm4gc2VydmVyLk5PVF9ET05FX1lF
VAogICAgICAgIHJldHVybiB3bXZjLldDb250cm9sbGVyLnJlbmRlcihzZWxmLCByZXF1ZXN0
KQoKCndtdmMucmVnaXN0ZXJWaWV3Rm9yTW9kZWwoVldlYkNvbmR1aXQsIE1XZWJDb25kdWl0
KQp3bXZjLnJlZ2lzdGVyQ29udHJvbGxlckZvck1vZGVsKENXZWJDb25kdWl0LCBNV2ViQ29u
ZHVpdCkK
--B_3110999709_669768--
--B_3110999713_642980--