bug 563745 - Make automationutils.py's minidump processing able to send minidumps to minidump-stackwalk-cgi. r=catlee
authorTed Mielczarek <ted.mielczarek@gmail.com>
Thu, 06 May 2010 08:06:09 -0400
changeset 41990 8b482a58dd47a0c51c52d018ee0d0b8fccb5c657
parent 41989 ee0ba861b40953358d7b74782291927049a9e526
child 41991 dd9dc6d4bdb06341760d466aae45fc19b9bcd738
push idunknown
push userunknown
push dateunknown
reviewerscatlee
bugs563745
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
bug 563745 - Make automationutils.py's minidump processing able to send minidumps to minidump-stackwalk-cgi. r=catlee
build/automationutils.py
build/poster.zip
layout/tools/reftest/Makefile.in
layout/tools/reftest/runreftest.py
testing/mochitest/Makefile.in
testing/mochitest/runtests.py.in
testing/xpcshell/Makefile.in
--- a/build/automationutils.py
+++ b/build/automationutils.py
@@ -33,21 +33,23 @@
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK ***** */
 
 import glob, logging, os, shutil, subprocess, sys
 import re
+from urlparse import urlparse
 
 __all__ = [
   "addCommonOptions",
   "checkForCrashes",
   "dumpLeakLog",
+  "isURL",
   "processLeakLog",
   "getDebuggerInfo",
   "DEBUGGER_INFO",
   "replaceBackSlashes",
   ]
 
 # Map of debugging programs to information about them, like default arguments
 # and whether or not they are interactive.
@@ -64,66 +66,91 @@ DEBUGGER_INFO = {
   "valgrind": {
     "interactive": False,
     "args": "--leak-check=full"
   }
 }
 
 log = logging.getLogger()
 
+def isURL(thing):
+  """Return True if |thing| looks like a URL."""
+  return urlparse(thing).scheme != ''
+
 def addCommonOptions(parser, defaults={}):
   parser.add_option("--xre-path",
                     action = "store", type = "string", dest = "xrePath",
                     # individual scripts will set a sane default
                     default = None,
                     help = "absolute path to directory containing XRE (probably xulrunner)")
   if 'SYMBOLS_PATH' not in defaults:
     defaults['SYMBOLS_PATH'] = None
   parser.add_option("--symbols-path",
                     action = "store", type = "string", dest = "symbolsPath",
                     default = defaults['SYMBOLS_PATH'],
-                    help = "absolute path to directory containing breakpad symbols")
+                    help = "absolute path to directory containing breakpad symbols, or the URL of a zip file containing symbols")
   parser.add_option("--debugger",
                     action = "store", dest = "debugger",
                     help = "use the given debugger to launch the application")
   parser.add_option("--debugger-args",
                     action = "store", dest = "debuggerArgs",
                     help = "pass the given args to the debugger _before_ "
                            "the application on the command line")
   parser.add_option("--debugger-interactive",
                     action = "store_true", dest = "debuggerInteractive",
                     help = "prevents the test harness from redirecting "
                         "stdout and stderr for interactive debuggers")
 
 def checkForCrashes(dumpDir, symbolsPath, testName=None):
   stackwalkPath = os.environ.get('MINIDUMP_STACKWALK', None)
+  stackwalkCGI = os.environ.get('MINIDUMP_STACKWALK_CGI', None)
   # try to get the caller's filename if no test name is given
   if testName is None:
     try:
       testName = os.path.basename(sys._getframe(1).f_code.co_filename)
     except:
       testName = "unknown"
 
   foundCrash = False
   dumps = glob.glob(os.path.join(dumpDir, '*.dmp'))
   for d in dumps:
     log.info("PROCESS-CRASH | %s | application crashed (minidump found)", testName)
     if symbolsPath and stackwalkPath and os.path.exists(stackwalkPath):
       nullfd = open(os.devnull, 'w')
       # eat minidump_stackwalk errors
       subprocess.call([stackwalkPath, d, symbolsPath], stderr=nullfd)
       nullfd.close()
+    elif stackwalkCGI and symbolsPath and isURL(symbolsPath):
+      f = None
+      try:
+        f = open(d, "rb")
+        sys.path.append(os.path.join(os.path.dirname(__file__), "poster.zip"))
+        from poster.encode import multipart_encode
+        from poster.streaminghttp import register_openers
+        import urllib2
+        register_openers()
+        datagen, headers = multipart_encode({"minidump": f,
+                                             "symbols": symbolsPath})
+        request = urllib2.Request(stackwalkCGI, datagen, headers)
+        print urllib2.urlopen(request).read()
+      finally:
+        if f:
+          f.close()
     else:
       if not symbolsPath:
         print "No symbols path given, can't process dump."
-      if not stackwalkPath:
-        print "MINIDUMP_STACKWALK not set, can't process dump."
+      if not stackwalkPath and not stackwalkCGI:
+        print "Neither MINIDUMP_STACKWALK nor MINIDUMP_STACKWALK_CGI is set, can't process dump."
       else:
-        if not os.path.exists(stackwalkPath):
+        if stackwalkPath and not os.path.exists(stackwalkPath):
           print "MINIDUMP_STACKWALK binary not found: %s" % stackwalkPath
+        elif stackwalkCGI and not isURL(stackwalkCGI):
+          print "MINIDUMP_STACKWALK_CGI is not a URL: %s" % stackwalkCGI
+        elif symbolsPath and not isURL(symbolsPath):
+          print "symbolsPath is not a URL: %s" % symbolsPath
     dumpSavePath = os.environ.get('MINIDUMP_SAVE_PATH', None)
     if dumpSavePath:
       shutil.move(d, dumpSavePath)
       print "Saved dump as %s" % os.path.join(dumpSavePath,
                                               os.path.basename(d))
     else:
       os.remove(d)
     extra = os.path.splitext(d)[0] + ".extra"
new file mode 100644
index 0000000000000000000000000000000000000000..122b4acd4698a52d208293a904130c5310851ab9
GIT binary patch
literal 14900
zc$|%!V~}r6vakPb+qP}nwvFAkZQHiJ+qP})ws(8C-F@Ggxp8Jr%$$2}MbxTQ5i6d^
z_|^K5S(&LQ0|E*S_}kbvE#(FL%YXpj0vzm}U4A$*sHs8$K#24AWsLrst{yM|Akg0+
z0KnfLihlu6|N0yfKqw-?BjR%1t_1}EP~rgq82<z~yEy$YvbD4`w{UTBpm*^6J1{$9
zTAKLZfwfw;_J{3AU)KggoRqW>`g-gGwwnO00{83-@ZaR&oEin1w7A+uw(N}+B$cFg
z3*S5DlG16W8x!E=2$8h#;rDOTF|4@o<?1lKX|GAXy<P9AsbXawR_ofOKgbUT_Uy>2
z4P<$B5=|EBKv~jGsn)1;v~*0JX8$Coat~cmsoeWV4`Z95T6Ew^(y-<Si?k&C$(aG8
ziIvQp#vAI8=8&c9#?=1Mhc<x&ZJ%`PZdf-CG2)%dm~{M*PQ`*hjStcqQ63?6965h2
znohp=rb}DgThF8xrEiWLeFi~PkKa!0@Cd?B{VIXPJh23KdTLIZh~krSX#NnY7nUh4
z4ULEwMzC<FM(>`s>G^RW8<3h~t9qsy;%6iA9M&6*?;9Wg^DzJ5(Bz4MQ7e6Z3zaxA
z8t(AYJaq`<X<I<Fx0$9DnKzW$DKJ<PBxjw=HsCa};J%p<<~WM)Hnu4PK=y!6il9K?
zSum7!jKy*%F!(x~ZAcG}L)EBS(vqeZrj2Qo3&}NMm>R~MKIfxndSuaydKx@17EiDt
zT+Jr3E_6_hL%tTe*!p!vIoO0KhoVmDq@~*x#e3}OdD<AQpX9*-{y`rMH^j4^O-C9c
z({U`qfQ?QqMT}ChkHZT;INY|QvXCIp`Mn=5OLVTz`S~%HoSeKLLPvhtSKL}GeoBkN
zh52RAiwPedETqU-GHY60sWcH>4`N<K-2i;s(zus3R7s2nYsNDCW&=LZ8+VRcrU=cd
zd|V7=&9EJ%YE|R=1jLgCtJ(g`<&hi5m5%cbd>;eSbEtMjskT4jNlxO>d5jqn!@E0z
z8(ALbV-p5$qi^6vYBbiU34I3RmDbrG`Ys;pz+M!*Sm3S(RS3{&_?t?7<FiMnqpzIM
zb)1Y<nX?Y+BAf0<0EPT-!N}uesKOiI6FqW*D$si_<H;Z&Q!Dixq8AVB*bVLVRN+<1
z?c}_x?Pi+r8N@O)f<7KQYPDU0hJ4Qb@=2`*Agx*XLj)3)5xK3nu=Px<DXpa2Mlo3=
ziAWzf)otvbQUfy8Ip3R8E*+1<`3rk;>Eki$+XWq<r0gP@PEOTGP-i)!TpNy<P!FW*
zNs3`JEna|m^hQLK_ztPE7>jx*9zE`n=Bvol)gjdc49Ivr@!HU8UI*4m7|0w*pNSv6
zZ0}0JH;*&h$6SsdF2O|w&<Wb{Il|VZQrK$r8YrNOgOz{))Y}vqPVCAYTkP(j!t{<s
zICMwcE&|nAfE|1QfzzWXc>jGYi~?QF&M?ol>`1q+*@2SjB?*ru4}c7o9WyED6hKV}
zjrUqpInm$LV-D}*U102RoBr(2cQq;z3KBPEDoP}P-K5uclUPT!fVRSLk{rft+CCH_
zd@z`M<Xnwz+bt4xfal<=f!=vO?yd#IA|cu}b;=Wmwo%7NnJIDDmTeM^(Y2}xP}EH-
z@aa0-sk8L2y1u>~j`ENfHLAvi8Tf7wCW<#u=xvCGadY#!&If91o#=v4rcCDvI4CHl
zhW3`$Usj<d_XaS%gieZbJ?k#SZa<^!dY6>#C`_ropug;hocjt|j>Q3nhhEVye9bSq
z1T?<9U4Ad0R9JC%tv*5e8A{|o#6fhLDsaNUS(L(@3GI=)v_iqrS6e7K`SoP(tngKj
z*>g~MSUQMU6Utj7*3c}+S19rk7X@SV`XDP>HK@nqBUQ_v+o?cO7xmE9-x}hR21)fW
z2uH`ys-|)a6=tNjvRTjbb-tBOFWiM~_g1$k8nh3hRQ+_u-41c{FLOEPo&#}<-)z2F
z_nte5_!NfAYlDh%8!6spb!}R5Rk!f@1EXioWE3e~c=(H!B2|mLL?EMWvq;BCCbld;
zR6lK6`Z&J;R2qYt!>;1sG4i%moJSyBEBd3$QM{xklM6B<H<ve@5L$o#aVH87*~&X1
zI!#ovk<~;adbC0G6r#sA(5XptbRxTRF*rx}OxVdBE9!>?X|)x8gjK=mFDQNM@pU*j
zHU&VYl!eMTM*47oA+5%ZVG-R65KA=?s#tOyoTc%EU_BQnxQO>AeO0A{sWm-nJnleP
zuvRLhb>x0&-=Pl4*4`B+-TZWR`}VvTD$vo$@5`glklfsy#e9~x`_qQ(%~d<sm**)S
zR>06)y8k<?O)+iCmAUd2L=pnkXLxR>+YxyAFfapg9%+P!RgO{Grh%VXIl+!UCQA0R
z3qX@yq;_Z&EDt1up>H4I7u^X_2_A+*(i<&|<$dU~wLAh(&K9be{HWaw@sT&5c?Z^(
zSOby?G><CD%m9|-%04ly;f^%u%4m<TBy;3$m_C>4UGw?^VtC%qAu_mHT7&5JrVt?z
zX;S9o<)S40%eGA#5d^wUMUHhA6~ZGO9A7gM;t#kilyvlkhy}yP@}=a3b{T`fV=$Th
zN=mN`-Z(vyK%ASz-9tf?Vy{}c<y~Z32GDJh7#oohY@TJ8{Z!DHSzK|I5;X-{MV}Yo
zCHakKu4TNwp2cL5oFH-xoe_kjcW%LT?qbKUBI)MYdkdcgnatwx$<UHPf5&p2&qev{
zW1})HLEJ6Tm4#?z6V^0GGlq7CC`Wsig*DOcUQY`SxN$s#^yg;Xm||Q_0oO*;_x0O2
z12r~-iZs<X+>9mI&RS2n4=APsZ!3Xnaqr<r9iABXbIagoq<3Mmu@vrZ1ZNdW@!X!9
zt#RVsX3jb|`DHiRK^-<G;ou<_!%+Vo3MJXi9yyc^Ju@ek;uF4e!k^i|t)T<SE?o|j
zGgjP0(9d>ba@L?1xv3z|(KoZ*jQsG$Z$Hu%o_k|A4ZkU75cww&iu(U(yXy4R=0Y}V
zZ@Yphb9*erFocNznW))6U+bPfpJ+IHmc?7jZ761d!r>{i$K?C%wer%SP|Uxc(dt;N
zaLIp1?=jyp=krq(u@k;<`~eKpu@aei=W;Ab9QJA~*;1gOIi53w+U3)6{Gg);N$<B8
zkWr34Ly@fELpY&a@Y?45Xvb|AVt5@#aU72whG!Xr&|LqV>-HR~YhtghU)`_gN@^cP
zZ8NJlrq(xb41NVJ`F)nic;a3EP60o`TcOkdu9+u}xTj=m8?~NtY>{&jhV`}HJQJrs
zEu(Eh4wvvd@VOmXB4Vz})6qfwbr{vc2P^r3)Q592nWY1H3yveyiW;KK9BKTjpv>P4
z^PuK$=E2_}|Mb-U=IXJ!;yEQE0|3Je007cIJ+&WpCibR3{&LYw{>$n6Pd=LVwll7V
zdf)baDVF8K4+*ye(`}12QSwDjm`WQ>9-?elXm6Ud8Oe1mvR_Kpo#tg%nb(fH_?tx~
zwZNHVo+18#FW@hbii60Y1F$a;kK@29-#uHH*_*BS>qH8zid37H&YQ80)4Ut!>(4a<
zb{v1tHwJ+-=uZ}fK7ys6A835QL{GoZBKpyUq(FZlsfsG13CV#v7YR^2;W|EaLY@;_
zL{QYN7aQFlkj+p>O5A!E;iioohDoxAhzNLTie0Krr&O(zSipEmUqYWcZ>ykqv#~_2
zX0qJ4HfV6%z%{HP3MHG*febhZJwR@VHRnLzF7=c_rnP$`q5SdJ>L%q)7pot<q9N8i
zPFK6`A=KwKz5(8GXQvN>{T7Q~FwGD%5ty-iNOEaLd&#^Bb>x65YQKq1GGvCuiQN_=
zeGKQ2Pc~OVl>W&P*`<{-yf_8!ck=jQ#~SlNJ6%5ZMcI8jO(1WPMo`+gkCK9QF(H-m
z8V;JB#k<?p)b-x)?ci^|Ry+sc-+fWKza&N3q+ZNq?FI@etYGGc`(nAr_Z;6%drN+3
zbO52xfQ?)?(Zu+peFONagJ3jw$TVnQVuP8DanvXr;F2ewL_3XMd7Gzo5t#p0T$34}
ztR=lUrGAfIvxpVqhgim2Phi$8?691;kRP(qZKni6%3$ffs6<%wU6^l6Qw9I|g~<!t
zEE_Qnv_z7w8BXsRjeo_MT_WnYD+6_JdPLRjanJnVBZkqWB)6qRS-OkBAswJoHfD+p
zrX|+bonGjR*t-rueiixR=d*)FJ~&M<Ea!lySYT{tiaMaoh#A!p{kTp({rWSZ-bS#E
zNx@vqWMxu&tAs-+sC;%XbCrdcHciiQNiRjDfafTjUl$=Qc&k|u`XzxjZ)iTmhX5?<
zAKatXK#va{u#egcUo6YaMk>YeHM;Nom|Lo)r$iO;Mw&j2R7Q4^L$g2+kj;#2J#xuy
zGJOxh7sYQhj6W4sMuP9T;>-*dFWRl7NrD+HL?|jDv$=!}uP3vjp1iK7m6VF_;=9=c
zNV_@!TC#?b5;jP|Knr`MxN*h9>C_WvGoG3Q8|XssM&C#;Y<=tfKD~yD^Ft)_`Qszt
zcDY|WO&5lyZAaiP-FPC0YJ?aPV~i=?IHs*I%Mp#^D%D=q0#Bg8{-n`po^G`RSJ(q!
z)lo{zR2<WDVdB(u_wJ!&pd3*D5dUGVYgl;dBhgQ4qYU<}UqC}rH##w3Ru~u9YqH@#
z-OFLDfyW3<4|7wkKf8Cpw$Meq%7q)R?^X%(idj+&a|DMY5`Hr3F`5$om4q>(7>4zv
zs<R2+bh`%-*Np^8filovEOxi5@7K0sj7He>W)lkAD8u;C95vlNgs4dgMkcmg^N=(&
zX2g-Lt_42YF8HI*lS*?Nm#+!Chd*3|I03mXV7J_`n~skqHBhYa*mIMVGju>m*p5V=
z*?vy|2Izv(6!>M^<^bW!XD&Xz+h}n`&b(nNZuF<I1P)w`<C`P0`EX&a9yX_Q8}=3{
zIUs`|gfBmXJaEwqy?5L$CfpBo_n{L+pp=OqiT*E*!Qng#Em@B^FU5N(RW;}J-!=qq
z*^Xj=M-Jx(2eb6I+p>Ev^svR`9oc~K9h>sXFUm4!s7uQ`9Cnf~Q<#!NGmDtHTOozP
zk|Vn4(@7HYGvDS(3=xS)`mST{dP5@Smr>btleUPPI;G((Wt>JI9}Q@Su?~<|AhAG-
zpeNzNo*W0N0>~53AdxIe2#1h>6EAHGv@{=VTRh8XN94CzvCXBb93s5P1ERv5l8Hk0
zQLe`79VCOHYc^Eh;k%?JmC%26C9{$--Hq#tt#=?X5LT-Xs7KW!OiZ4EVeS~M#~);*
zvKUB58eo*QmD%FF=SEFkzh&q_dnUs3>8*3M7m{}nxyj%~dF`4Th~%Og_v6(j@(_>d
zuUt#UYnLgp#Wc!|m1+#kM0zL$(qK8<Ahs*R!!y8=R$XM|fuB`sT+Q2KI_mnlPK0d>
zb+iZHJ-}nTK^%9VWqewj>*H#?{t&VdkhNYGJD}?8HtYo|fTB?Vd`%ls$f3BN8Z1bR
z7(Sm4a&=NuipHh^c(lb;L-1;UgAwq#ZZV6MZ-6a0b4hfJaZN6C@qQJ}I$5x25_`ej
z(^XYv_jASPeL*(`tmKSFY4cO;&7KM}2-1cLTJSvY<9<++>=H3Oj~Ri7cgzOvre8Qk
ze{IEwOW<>PKxRq9OPaTod5|=&E4md2Bl%bjBkg7<^qMlmYRc4}c!~#etRf<7|3tXh
z5|5Z2pkr7T=Ufp#U-E;CCwrJ(7}9ixXI@O8r3S+-17Y9tbKo^tA_!rG!0Wi02%rju
z)og?i>A!^vR`AH0=0+d>#AAa<yp3lj{<TlKWLOVmLEUG%@6fKq@}9I`zt#)<Ae8W=
z<Dok;G<4WD%VcvZ=g!T_dEvs(F2q5+P_|T3VLsE_bLcl#$|2FRlG}N~HFb?+H_>sf
z>mt3}dsH*OOFzz1?!S?Q8>z+R(MK(>yMR&Tqa38w-qS}epR&_bf#3A2j{mdn#ZxLr
zb$Q&%(Nt}dg5@sng=?S&YIw9HgZ7h0cKOOcM7Ci1vZy=YCDRFh9xs-oKKzO2cjz?P
zv@>kNblEJ%?(QjkK1F<7lwM!goKvF1W=BKy=q2$ockWmKIB2Nz#w*_28r@m9(SYJt
z;3Qrg*RgU3##v_Lz%cwTGgbC{vRm$3afGUjRcK|3^-t;w&+`;Cq2qUXCbr_{iEQ~&
zIfr>U%2ox6ZP*=_(uY_Pq+#Vtx0)f+UCo%sW(|#nv*vgDb`vMpNSoMCn|b2V2470x
z4nK5B{7N|xEHRSn<XV2Qk;dR>OG$(7E`RiORYhn9YelXHGWWcJk?C2mge!geP#cX!
zkuv-Du2EC~DNQBNlxO8ghOJ6m3zBiGKt^87kmd@IW=VKbx%1`3=zZ;dGZ_Gm+_}=!
zX2f|PnoOa(!zhE};B|K}1oKZ5J&)v@qH6-mF`?AeglzW<MNDVUH$qSh7*bRXD6&qL
zlM)yXu3UdH-?p+}3u&*55!twtVI*`oC@a5eT`zE8xxHozbq;~<AF^|j8%+_EkUm;{
z3TNcCafI1{`ro0TC-_ZxLtE6caIe2iQs^hKA;#kPPF6HM+fNr7s(q_IIFwY2j6@sA
zUZ*mnNK>B_-9o2hoqk|jib3aWJwS`K&ol|jhRN}{q4PEdaovrX;GqGdp5npEoe1~I
zcvb(Z`947u#GbQ5v~5U?X>=%|C2|5{?~~qgzK6-&HG`Q_=J`V=`{P~WcQA_iy;O#h
z#g@42KwR&q2(O*6;Rd_EDR`r#jM^y_%U}uy1a_0ncSqz$H<D+|S3dB;GoY<icBkQd
zSu~Z`WT}!1<^j&YYofL@JvaIqN18~mrco)vAWC@JchE}c#@ZKx+hMwl%QKipa158J
zk{lYaCP{Z7c20Gc$9Akr;?`aQYn{OFlFId<W?zC&yM^XfZsmdoY%QUoI2vH3%Z>~u
zbPA7;VnEewUKI@@1t#?9F!UgyDB)1&6H{l_t)U3c38f~<mKjyc(Wjigx45yo%0^|x
zVjFo#9(@;nv3B$(mpyS`-u(i1ctrL`h~lD+#1grdzzg)lwcgB)y7w_qmws9_YfeQS
zCN|&kNp41IR2gEG17{P5aTj-vdc#zyhYzo?2Kz$J+mOj@!cSJ~PJASc;*v<VBYQ<^
ztx#x_aChoeTA+Sy<yI)+iw#f*Qq#4^z6}l*N%P<yx|2ovK!Yl(UlxG0Pa5r4N%<y0
ztx7~91RRYjiNU62CBFeR47V~&P}Lb(ABMtK%4|JW6)fDBB;9u6LS3;$S4-fUyxLjA
z%Ofi(uN#G20i(4`>{ZV$5Pa#Y-~|Tm!Pi~zRu+MRsS|m-cEo1M^<CCtT_1L(V1ro@
zmB;+BbS;=Fd@p;Uk0WZg3xOgd4*V-0%i~lXT<q)N8PL?vtLH}F?)uy|5hE6Klv_NL
zWkw`jd?(<9zPfHvgN;sYCE#+<$C7HbBn(R`gT}bYilD#=7vHWNg^}#^bKfK`*G;TD
zA!so6C^BdbaiP1Fe6lcJN>wrrpBur2QP5T(K&pliPor>f+NC?BM5mTRq4m$*3QFGl
zyr;AbUy<)s{cd7k!I(m^1LnAaNnQ;|&*pu?YKttojkIc&g$U6tO5_Fv#JS!`SGWWg
zm#%<V=r)4lQNy3OdN0i8U+$s&0)`|J>G?v0siBD)W|O7V%89Rs&EDQ7mfDyGEO(`{
zOCX2ET@x0vESsEd7B`qG&DqMoY>(SMB|PdwzCeRCvy&9#kgni20$_cmGde0A<S~xI
z-C;uUTm~^r;ut(WI=mdA(Ug7VpXXMi)6;X++!q273`h|4k=dY4t>r_%*eYx{JZBop
zrt{W6jOrlhFNB&5+uEa!&bb$;c-%fMQTI|lzsQhJW!~1yoL3nOd9g;cxo1)PY`5>Y
zKxI^xq-X9aaTsI#9$=ly&wedBDQ4brPYaTvv&6tPDTjuPch5#+C^F!d0RQfTNft?=
zjBrZdx{58kb<2gvbuS-cUOuZxwtiE^a!PRF!E1?><J}o!t?!UIAeUl+kedI(<a4j7
zX<GIV9Q#Va;zQ7Zz7sCue5uf{OtRPQ)c;9eOY2+i*V0?>FhPE!9;0}^2nH{&M?8jq
za(nw{7rkT<f4?HAt+EB@`EY9ERFD>Z?t^u3!Ura^7AfL`bsQVv3jWoU1gB)8L_m@p
zE4W@l;Y~Mk?uT%M3A*-6<A^IdIoOi+1j;)dPEkJ20MNTYC|6va3(>|)i&~|1QG!p=
z;DA=?<fVMBa^NrB#7*~dR|m-_%%ge<%_f9jUiFL8VqK`v%D**v$@(X%xPssPRs7Ib
zuvTFwoxAkM$-kTAKklR$8Ew?=vay;bnO5=95Yo!n)oIfn?y7!f+9+&Dni-}n2a1uR
zooSErl8CU(CwU>OrblA;Ow8xxCj{)hL0}qL@tkatN)`K|V$9x`RVdZK%=BOHY<uT>
z{cg+S6JW8-=x%q=uQ(EdZx5TH&}L$)3LnzUt8K!TcB@Q>Wqd<p{o!^G%eIEr+Jjb2
z<8NsD&{5uG8^N8V=t{6}JkX`~VDJi3%HdD+Qk6vFH!z}<8k5wyrH+3YG8L23>N8TC
z9<-J1>p7Y|lDtqT{ZRIy#i^1nTTpsU@DRf(W1RowP1h@IH2=j{=$wS15wQ0qR<csT
z1Qm-V=B9QVF~^1L78vIW&_x?9exx7UHd%Szc%9cC^xZiRX9{IKlYoh1S92BZZ3YlP
zGxm^^kb%3$NT|Ert6YR{@M~e%IDWv10m1&{5l59?GXv$W7=cw~9}SIYa)tS!W?%Vo
zk|E<W<^$;vZEYCytR#f(!w~V(i4}t{L9HTj`p0(ZwOO6Q7XQWcb92N@+f+NJWd_rK
z>DLYdRmq8y7Z6eh<t+JA6qyfaC^0a~4Q%$W=UEjcA`+Rno+4$}v>Y*AC7}38F#ZXA
zzFw#4N1`ZEmbyB>s|?AM!TFyV_6E-MpJ)gYNyq1`vS$-(C3o=FJ=HB=qAR+gvqdd#
zeR6XOSTjX-v%RPmdLek}IJ1^om?4#&S+}ITK@yAU`p_DB?GBZ3GmlE`R2szI&?LHQ
z)UX=9*<~JD-SdR81aw;rJS+{RmtWN^ugt-{Fh+GknmMe<bgruHj(E`o2Tr0eV*wAb
zLUjC4-TK|DjCfc_QYI-tJqL0qPwMPt&)x4QL1}S|%W#}dd5k=eNI|^gjFupK3(H*%
z18o;m4l3J*^J|c^!(<f;Z<VS*Lp04vOBfsv%&$Fhg7$12z#FE#rv6iF%aAL<ayNq3
z+&$Dr^}Yp>(58=N>#zwh`>C8V^d)OHaP8hlD7)l`yuNE%%KF<2YZB9w-Saf)Q8zGB
znWB0L$wVInvFgz`$ylL3Bp!)ySI|-aJbkfk9eUrE&61`f@9gBSeMN7r>KrUAVRz6&
z<XR)V>K7~y=nXs@urW>J>4!*1;WpWaSmxd_u?vv?MuQxz#H@nV(Wx+OD1ROFl3wS<
z-`r`soiZN<&0E_juktF{b(htu8b)(_v*q5bTJ4w0&uAS}!;#%)nthD<VfS3?=~nLL
zFCqe$LJy+D3D>ZA#OgMo<)m@?66E$S`1?S*{172LrFj<XgUg_YCy35y+w!n$yO~Es
zD+~d8r4VvAYLCR6UEHdROeV4MRwfFQ&2g5Bp5nMo75fVbgCX%oeY>-1Z+RP;FS}Ii
zw6RIkbFG$R^{YX@xV6QrMgQC2zu#>cN<!D({Iyd70sv6{dADU?U}<ORVqoyU-EN5`
zG{_G#!iFv3b1RP6@(K<w2kPSkLNJYlBzw-%D3|x?trkTiNrtO$(QSAkXh7Qeerw%P
z$b5ZLJdLeYd3}HR{9ZSprM#hBA_KzQM1}z;yMSq>`@R@aO|Pky@U?;(pjb}iLD)F2
zvT}yxC-%Qhq=?bxV!3?zG`k;muGbgpJg@>>H;SRCiV8`u1qhEk&U+GeycT-YD2(GN
zKq&{^lnh6|c0AhjNWiw|;IwmFk@M)qZ{j7^K^foVqO()rjX1NTgKA-o)3ZXUt@TlF
za%|5=1ScmX{h~bP?%v0m*~M+`$&F+5bJohi==-O3Ca$5}Khd`B&Hma&|22{SqjrCn
zuJe6e>OV-QH_Ze;$Os#{&sSd0i_s2FqU;R>(}hSCM>p0Xpq7Z4vHQ(0>ViWBWW}4E
z(kSm99kLB99+t5B74+W9XXwRp&;W1+&!wwYIl7{J983XS%paAAizq#x@OivY@G^hf
zb?Yth0sQyV=BugJYKH*;qzM23%>Oy({Qo@iV=V(`94VxHy@{lrRumpLdjD}pk#^k_
z#HqRv#n1^XdVfh_$Jv!hT}}-5J87PzQT;2*E|PDccQUT3f++93!1Cf3fa)#W3uLzg
zL8u0PL6^B3-Gn@K$pM9K>Eq?Btb&5V^H2Yt_c?z#Z-eh^0s(90cMkZz{C<X>YesbD
zR(Or@Q2I@$_0HrLz1C~9D_|W4#jXI8B4Ql|W(wLyhnP?@^fWCT{8%O>V_@*uCJcI&
z(+rZ)4B94#piq44uFKG&98AA`QkYXs&XHczOE8oC+IW@(vQfvz978%yH}0Ez2c&&w
zt_f|zchw!HP#KdkR@a<a9(lNnTM^Cqsgiv1GnUtNtY!Gn>7;~>?n77-xw*aIM=n<3
zTIP863pC8?Gf_}IthU$UmKFt%K8#92Sx=47Pf1li`&yDF9(uQyh(Z;2Pz6`Sa3SQo
zxYZs>cFwIkKV+eMa*bHIg=H!Qv>3Q%iWbQraLIA*ETL(fpl1~%C#>ZDFzDxYD=aqT
z+ZqPt+#uk16HWdVMlv)igrbOQ%(R;dKhS81%^>R$kr6WK(4Av-0Xuqo(jqz)&DJ_E
zVst6(j@JEw{!1o0tZ2M-iB|tDNXVEW$gum|I2*T@IM7J$b>!}J$y7-=YP;y+p^ZWd
zuusWT6}tqe0*VvwDg~X8&s!32g7u&7(|$h<3~G03_4{T8K!~>aFL|#b%WST019nxI
zasu>UIwCeZhj@q~jc6LdVD{k+M-o?fJ$6vr^@-<&8xD8|@U>+7CD+>oeS;i$>JJMP
zAdnP}e}d)aG6{)zcq@w*Lf-4eLCcC#vsNM&!)ue(XF_xdwPEZFLD)82deYF)bf;F(
zL$ra!5(w-!ZmLAi-dKkCn)RH4-%#;3TKTDZD2u0Y>3;1uh*U}V_D@S24IZ=AbJ$BM
z(!;tqY*c{bWs;{Z$AvWoj;Uu>*~?csVQFaU>&BpZ=s~C(^!7A2yS#$iZ}0VWaQi4~
zq<fMYBYHT@B!36?tw0x`EvYzYsbPbUIj9papRNlE7MZNmLmkk^KD`pBK)LWUf0ds~
zK$zmO%rjX*^MNBcD$3>K<!Vfk=Lsyb6wKketcH6Dq;>7tVlf}W-w;nu4~j7gn}{PG
zG53jsTXZ@IiAn$I3O4~t+~7A!B1*H3V{r}T@<3R3pKOMXu$*n$oL&&K;dh7JuD6CY
z@@*Pl#x2O5!aqmebVsZt;2$LN-X%OCXqQdD<?3e@K7SkEg391AGw-M5ntg)0LV&h;
zrfD@WJnu3C7x4*y$B=;Fe`j&d8+BD&s8KCSRgcrEw9)w06A5zT{{=5kkotAGduhqb
z(@uQ_ou+9fc4fr9@sRO`@0<fN{^MOtcOSSUW=5n*E^))5@-$|I-q{ZdyiSdm^^L=0
z8gS`jV!{*gW^4j-m?@}F8sMfDzuDLA$hk=D86X&iY3cx>7-Vcsl%#`&j>ReU&IfzV
zih<@3u|!y-d#G2)0}T)-8zbEKW0Qj>!W|Sbdz7&e-YM-eh}uIF+CwKZN^}r~3Z1Zb
za&<ojnY~3BP`v<|k~0ez$Ehme1p8}}wP{g#WvghEx`d1mD7N4yS}0Zy|4Vx$CPB-B
z#kC^q+m)nE^tjcMjD;bEBuFg^f!I8VE-rEw{f1gdSpk|9FnYf_i*jW}%yCvkh1lGg
zg=8vt!4kSK7o1?u5~lkm+Hx2@RZ{s#+<DXpWTRT+`tK=9-H?PdqrOd@0M^~DUr<H0
zp=LVt*eQCr;u|}8di?ML{oewF`s{}uvsCV#yob|VVC6^CoGdnjTvw=?SierMd^1yX
z?yq@cGF|1lQh~3*sPua9A@r1fCXbxE4hfvQe(PlJ*n2|o(|duH5|O6n6jQocA&$Tk
z(Z(`*yv3TKmQXFG!%c-(4gKjc`oNeFAr>*>Tn7II8xi@a=cE_GdvO$wWLS|{h+s-W
zkR14JcS7~(Rgv}h7KsVY(UFBSIs<oT7S_RSjHzVUXkm2Ci)blm4El+zT_cF@EKZwN
zx@wa2%h8O41*ne&<RXpxhqx%n6Eb8U>93~c7;}?A8^61f*0d(Ncu}MwwqJrE?}iSL
z1*@<LeSzNYs?+xB_6BmVOw_>7sNgfkrAA&Fwm8J8jsYz_d4jS$Y28E%po11{z+E^L
z^+%|jspk}Oj=>ynUJ+y_I4>4Dqk^lKHbY~qHU@|eI*chPRtpN`HUpxSPd5$&-C|;c
zLRiUgsQB4rWo1M^QW_cqvUkMVsSMcy`3lddRLne~ImpN>IRj0Bsjdr#o1?)N)5Tdm
zfhGICgOFDTI6-`p5>g9ivrOL)H97X%nc;)Dp@hFfRVuhRqZ)G_>LFIcb6N$&q1<3u
z_*3LtCb70gb`70-=RZLuY1_77V`D91rqN{=R2-$ngcEp#SEiOgb9-y?{wzO_H~;>0
z75?>BTdH@V{Ztd=V@D2u@a{l#S6G%{;Xg~z2A($JSmrPxmhp=i`cF)<4S~nQhQ8tr
zr7}-3wPorQz`(w;L?-H#=ja0}=>adZ=m_wYc+W2gq{%dF1tgm?g{YK;p~g)lY#%I9
z97rfCRK(WYU`tc&RClfm?PUp|hlIJO<?TeSHzlNF=#QMB)<?f}f}zKD+}{son<R<H
z_i@R`#;i)I^N9M?u%l<Yh2KoE|Kkop-_@4L<g5Rq4;aBEVei-u&d0uKdfC$0VvkRe
z(f^#6hUtT^l)F8{$a_iLTy!B*9*%brvA-JanN0%QD&7-QUXGN!eE;Yi`O0jn@8!ve
zdt|<M3EZl0Q$`&bRi`8%-vPFR(Xd!SWV0XqzzpvKy-N6viLk~-N|vMAH05wM(q^wO
z9K%$oxh2stbt2}pIkYajod_=Av>+Xam^cv8Hz5;hQJ15Xi5*FC^GzTXi_%KfI;AO1
zGcVbj-4;B&?M+D)!V~TCY1e3V!jL;xtXcv%3wqMfXGd;RoQPBh(T_11zFI~n5MnjJ
zKASUh(S|eGH*hgApV@x0<F_ttzT*y!EKq2c)9ALeC*|k+?&uV-6~Flvqc%FRO3P2m
z{)l=g|IA#(NaANfON$ZZj-y%BxVzBOwPP5>?sZBMM@G=(o*+(G6!7)ni3x_vGEYDO
z!Vl1%drN$N@(s02jPg1#+{p|N%`$M1-F|FXppX|NFz^mriwc1SauoXC-e0wC_O?zw
z($MXD&Sq5D&RLm@9S6Sb3Fj*evOVXDJMKu?PiM!JHs;d41X1eu{iQ{ZzAWtl<v>*3
z93rk9tF!Rr2j&KVG<I1dOD7)Ed*3u2h(qsGY3$vpKleL~ent0nRZ4EAJDyVG<8;#+
z!Lsc^s9{y0l$qzM%Q2f3V>tfoB7~Rhjxufe##*A3M!;r^;IinH$tN#1sH<=bvkG&4
z4!{zesd$BY4{e#Tnnu`zpFE0WXgN*rS1;`a&$k}FvO!<a`uI7jrWi37O{i>C9f%v(
zqWh20B|8>J@TgKP9F$2r1&YMQxe>OEm*3<1N<=+e2ev)Xw^j^+-6ZuIJX%}#0>d(|
zM?iB;3rWZazMuYK9$)ddL1CmJ_X2}c+ptiO(%?OVeRH%TJVvnDvkD_Y>jqyMh~62&
z>k7Abze|A8v?lW7z#53$zcFW|dUwKtg2ub(HQkk-*ldt0t)Ji&&H4X8gn>cs#F^h%
z>>JFa!1s;y!1?)lZKPAY`&Qspf-gU9P_VtXL=tcLJu(WKOVe~_yiNC;p@ba5#8a?7
z@hb_Z&fPA^!EumdII^@cuLKF16AuX?fQFcMiAa##Zz@1x$7_!|fcCe~kcfoKhOuW8
zE4AL!<x>M68z^B@kB*l0Z<}o|T{l~!XU+LuIbJ(Rrp~}<-9N#y{mi~9&O2eD=s_--
zfm4wva{G#Rs@|T8ksMip+(D+rhM<5!R~T=bSa+YcUPP;5Sduw9yy0P?M}@zRah}cX
za;x;%e+zxZI#s^iZu$oMXCz=RD8WN%>XP*n763q^0{{^JLrufqBY?!<|5$d~qiq|%
z)r$00XCOq$rVevMC65SN84LES49JSGF7`;fpgx!HI;v|bNBvhs%G_GfcMr>udt{sY
z>mta31)0;%=|1d4Bdvl-^>HS`+mx?BP91g~7s_^>y{Wrlc`ufZ66%^n<t2g}{+mK0
zQq<L$UHOk)s<L?9CcfPXbtk&Phq(OV^n4GVL0WnUHHU(v{c`cjS9FUZn$eBjx}UoZ
z?)Lt@W`FLt1?n~k{cu7TU6qc^WKabeOFh^A6dJjI<elZkp0=LCZBC(^UI|17{!aU$
zg_;d#zc~|DyYW6E<dSVGaIpM75=AHJ(Ey~Ky*sK8<MTY~=sO1Cr(FYW_Pu3M3Ng=-
z6{pJ~F@VFgw;4R&U(&Hl`D(wfpD{;Ge!8-W$sHXpRv7-C&MKTY`&qETIT_~1VLWGi
zR(&j^0JZ!f_1h6}>cAer{27TwG{Gv(XjgMWuCtUMqWnQPFCDim=n`QY`|YDbcTxPJ
z8!^Y@xO&MZ^*F@%AVOSb)M<P^{++*QSE|0JAyNX)a){Df)BE-`;#7qSso{Q52W*B0
zubpHS%PZKdHdW+6PVh_JPJ_{U#H+=a!V~%Ji&j;sKzk{nl99I7i*WOTud8D~gM$OJ
z+JwUKWfCVXVvW_=*-k=i$y%hDTB4`#txgwv!JBc=fntCVgMuMf>?p4T_0@YfGF|2K
z_Q$@sG#QU<QLd8VF=;HW*zhVXg(1?Iw0>35dW$YqTA9j<y+0Zc-sNL5CxURKya{W7
zECeVXE)^?j!{z)f7G^!6(Q-$J&?OW2SpR@Q&F&CO_n%=amJD1`#vkOAg&ML}dqu39
z&?$qUB%rx1P%Ogb`&u3-Mjrgr&;vvfr|koWcn6dTsu6|{IrEy7CuP|Am05u>K#oIu
zWf095UNdnY$%5KCLg0Hme0QsJ=G|T9wtY=M%NC6s=1M@saMB}opL4+x^z?@MYg*H`
z)`5U>5IhG5ETP4yTV87Vc-wT{ey(4SLtr+AF}~I1L<Cx7MitH)Q#>nUQVFI9^JDix
zD-X+q-fV5jMl5u7d*9xx(bxy;EaX}7nmo}Es~`ld2Ka>iHXuYQ&Ip`V$Uywz0<1`3
zCl|k8?BzzWxoQeMMtgFZFBvqCB3nHi0CT>KQ+X7q#fWg{RA#Ae5gRAT*(7+hXJ{NR
z%=Wt^`4Y4)9wciYe@&rBkcp%WrkGa?J?&$gaITXe2G;3j)prA!oEVJAj?Rq41Sptz
zt%g?k@+~k5#HSA@9B42i*PBeq8AG44W<RKExVg>8-5LwAr<QZPuJ{PH#tMSW?|8$;
zl;Y7$g=*ni0~CTr{91<uyw1m1RDcO;S|Q$lN#Hcp0)0K!Ppl%6*Lt$^(Wkcm*+>t#
zILpg2Y&|dGwU>SUsy9MiZnP{wKG`WEk4)}+4)|l}!%WmcuJlxt2SE^l=6CpqJl=M<
z#7Yci`&eb;SDVlm+%UfYjE4YZKb>JKWkbySpF&;U4aW3!{?M7_7|i_mjKr|%X-*ED
zIPY;A731sMftQSILup`<p-)}(CM8fc>wMjNpahdA9$qrHNaFcH;&XY)r0F>RvLb9<
z_zK-r`>v-vqQsqJa>JHl=b%(<p&cW8F88GnyorOB>CPJ%H#jo-xO+}K^!8!mm(%y)
znvq&MZ?zkwJsO%ssL|e_AdRz`n6lcd>NbI7B=yTVY+x52E0Yvi;~%B{0%M3k-ChmG
z1`JI@PP1c{+Re79`AN!o@l4W3rCD9C?|wEocgl>N$zz@?HKbij8w{krrqJ;0%F8Oo
zRwg^j?R&vf?$0rSH+gz87At{ib4a|~-bwT0drila>8(J6#+czDT%R`5{*K+X>q6y|
zjXGM`>ZbxqGw^EL4G6ZUe!mr#57l{e-z%?K<}X-%E4qU1td+mJvaHuYh~W<9O_YEi
z<U+&As>(&70Av!n!fQnPWok;Q$AVx$R1PO^5qw1OmBz$VREdg!a#5dC4T6FVMI0Y_
zsviGaM`_y1#|96_BAbq)coZ$-Av6|=ma54NZ$6SUJf@%eK90#NqY9vMcg~dunOXNp
zewyfy<_lugE?hPZKYd9jCAH8-GQB99wV^_316<g<QzEG>j_c(@ToJ^*n3cFJ*sIi4
zi0xWJ7>HKDCGLmk%yoi@sjQqLvY@}Z!YtTtK8l2_d!42tQJUl0SPbE~oWwkBQXmQv
zv~!k?g9c7$j(R*REEQX14<Ob_7(<RE6#D}sV9a((-=HPx7y&GQ>?_s`Au8T1k8tCO
z23jshT}mV6`pAvSkU2kXp}P9TZL0Xbd<Xn4-*rYR;tw07nt&{6n8K6dxC<Y2pQMhn
ze&QM5wJv(H4xLo1w+7@Sz`e8I8k~cQLI;IGDZhYrkDKC63a9s$W%x^XWMd3>dU9=s
zvJ4F&TYHz79Io=TU8T?Y=u%AUS6u*of<M@dQEX7VWJhM!O*_M?w{Es%2pzAiu&6bf
z=M9f}BArj?XqP8WK6hGc-fv&8&`5{4LYW$XY3$E|)mQpJWV&k){!u3S0(}~vYs$8~
z@zL&tE9e7{V#s8Y9yZNvgBew$*4)A!E~fvDEazz<a(3Qz=LqKjGZl%Sl~l7;XF6B@
zEduLTqDO5=Bx9~4ahdcpPaNJyKeWu8D_%oD;C!Arzl=-E50l^J$EP(z*Cf1wJj=tx
zhGm;Vep*@+y`7z9-w0xhi(Bw@kWjML1Ig_jVL|fV(6wf2pP}D3&<qTNoB}@Lz#!)J
z?wWmCylebI<VZxeS#FD-No*3!C(EO3;;ZkuL<DCl$sKe}-Vpf(wnvckTN-qmz5d7T
z=Cay%QjzU4$@m#X_s*QQ<*#&B9@k-T^W80vG{twj8#YvapZ;K&9YgzzvuzUh1=*=Q
zABy~}?6SsjVI(^NT!<#EO1<O;#nf{+svt%c^4%H|js@-mj4&7&Y1zS^?T9&Z-WKG?
zI)U7VpVa=DVtXkDWsB@ephlTK9X!T#E_^YWrN7SD707OSZP-M+HaUq6sxfhJ5GUZ*
zf#Wwf(#N;v*24VaJZ;$1n~ki>*h#y1i8yA&IcOt}b<apq2jibLAO~1>b$vgb^f$4p
zF<X3A50n^P6&1u)v_rYGRg#^F`$qi3&n!mnQm#w*kz<2DLN=^Ce>mUVg3UFvnDvoo
z-eE#+awWG|gNJ;1)61n_a=l}J-Ge4KX@b<L_4l;{V&$=8)jll?xpW-IxZx{1CJDIE
z#S4WFwnMSIe8(7YdEYRbtO@ao&JO3}!%YOTR)_PQev!y>1Ec<yr{ncq!az^-Bp<72
z2y^C)iAB+qkDz7UP-B!}JZq3_L^_O@IC)|<cg{ga_Q%f>XxUbgRzx)MheXr$ISM(Q
zz7~9T-()w}C`xUh>uHPWCUP1ZGeRySJl1Q^H9jfNR^&H1RGAcQ@QAh`XieHS-E|jM
zHT;#e#84S?X0@f2Fl%NZ^RjrD#-?c^(0a`%9|`oczkp;bE{!MT0>U#v&xJEblVk^O
zO7i*SF`EE0b-&IS62jqO&eiM1=0FI~vMn`Eg2!PQU*XBJ)%K|1Ec_=x>4gvXR1fl7
z_N9)+G3Un5T<?b202>v){__WZA05lUl@z<np{4cP5@?GUJB2Qict}MGvur;Y`Zk{-
z&ja27pv6F{oA&62Mcm4&mU~CLsmp2t4!-C;2ayxed$t!2y<Tnr<>7Q5X;F+xR!uuF
zX%i%(!_xln4FzS{rDLzLP?^N@FeL6%;JXw<sg%91C`sMI?fPAe_TqqK)dNdP-*fT8
z#e`5{szPcRAF6DfVwU<S=uEC*V;PF|Td?>*adLO$zT#*sR96nq6E&DCtrP7TGU#bh
z-bF3^Nm#CEqu8enBq}x_!6TCj+pf2E%g@4xNQCQm+;xx~`6{^83CkICSkKhJ0X@=>
zM&Xx3M$_JrDZCR^OR3;XB2^zc61^DVZxXgBjNKHXfQL|Y6Z>s6`mTrUY^#7Zhy^I!
z)GWlZx-=0l#z)uFqisj90&xyTQS1#js^Qr@k>5+$Y)z@s40)RD<g4}4b~RN*!H*tx
zPzPtkI1ye=#vJT~`wO7K-(l=bD~W1RPMC=CoMLK>u2CtI53j=m_J>?9MXfH62Q=QF
zBaY<aEFOjL^3sn^;U}cf3ZgmOot&p~+?zoWhNL|Un$y-h6vDHhKk0#O7@^>Oao0tv
zjkK?foF189#<zcu6b*P#`7g|tagR0RA$u^tP}xyhz%`arZkT}M8e-FM6vVYLGvg(`
zN8?mI;JF@XXxQP596G{Q?BLSG*Z!@T8weO5<bUei!~DN*h=41hzpek(#|QS049LIr
z@cj+;KXvi_0|xZhED03)C+y#Q`oR9t)A#>?|9jy%=6_jT5_kax_)lf%|GUlqp7Z-x
z>=-WKKW6~{cksU_#Qs$b5d8lH{yX<?>9POC;QyYs`d5Qn@c&1V|G%vM_fYs>t?r}#
eca{H6{aaxCZ&WbwfBaDp05f0!pq=AyyZ-|OP<N^T
--- a/layout/tools/reftest/Makefile.in
+++ b/layout/tools/reftest/Makefile.in
@@ -73,16 +73,17 @@ libs:: copy-harness
 endif
 
 _HARNESS_FILES = \
   $(srcdir)/runreftest.py \
   $(srcdir)/remotereftest.py \
   automation.py \
   $(topsrcdir)/build/mobile/devicemanager.py \
   $(topsrcdir)/build/automationutils.py \
+  $(topsrcdir)/build/poster.zip \
   $(NULL)
 
 $(_DEST_DIR):
 	$(NSINSTALL) -D $@
 
 $(_HARNESS_FILES): $(_DEST_DIR)
 
 # copy harness and the reftest extension bits to $(_DEST_DIR)
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -243,17 +243,17 @@ Are you executing $objdir/_tests/reftest
     sys.exit(1)
 
   if options.xrePath is None:
     options.xrePath = os.path.dirname(options.app)
   else:
     # allow relative paths
     options.xrePath = reftest.getFullPath(options.xrePath)
 
-  if options.symbolsPath:
+  if options.symbolsPath and not isURL(options.symbolsPath):
     options.symbolsPath = reftest.getFullPath(options.symbolsPath)
   options.utilityPath = reftest.getFullPath(options.utilityPath)
 
   if options.totalChunks is not None and options.thisChunk is None:
     print "thisChunk must be specified when totalChunks is specified"
     sys.exit(1)
 
   if options.totalChunks:
--- a/testing/mochitest/Makefile.in
+++ b/testing/mochitest/Makefile.in
@@ -59,16 +59,17 @@ include $(topsrcdir)/build/automation-bu
 
 # files that get copied into $objdir/_tests/
 _SERV_FILES = 	\
 		runtests.py \
 		automation.py \
 		runtestsremote.py \
 		$(topsrcdir)/build/mobile/devicemanager.py \
 		$(topsrcdir)/build/automationutils.py \
+		$(topsrcdir)/build/poster.zip \
 		gen_template.pl \
 		server.js \
 		harness-a11y.xul \
 		harness-overlay.xul \
 		harness.xul \
 		browser-test-overlay.xul \
 		browser-test.js \
 		browser-harness.xul \
--- a/testing/mochitest/runtests.py.in
+++ b/testing/mochitest/runtests.py.in
@@ -220,17 +220,16 @@ class MochitestOptions(optparse.OptionPa
     usage = """\
 Usage instructions for runtests.py.
 All arguments are optional.
 If --chrome is specified, chrome tests will be run instead of web content tests.
 If --browser-chrome is specified, browser-chrome tests will be run instead of web content tests.
 See <http://mochikit.com/doc/html/MochiKit/Logging.html> for details on the logging levels."""
     self.set_usage(usage)
 
-
   def verifyOptions(self, options, mochitest):
     """ verify correct options and cleanup paths """
 
     if options.totalChunks is not None and options.thisChunk is None:
       self.error("thisChunk must be specified when totalChunks is specified")
 
     if options.totalChunks:
       if not 1 <= options.thisChunk <= options.totalChunks:
@@ -255,17 +254,17 @@ See <http://mochikit.com/doc/html/MochiK
       msg = """\
       Error: Path %(app)s doesn't exist.
       Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
       print msg % {"app": options.app}
       return None
 
     options.utilityPath = mochitest.getFullPath(options.utilityPath)
     options.certPath = mochitest.getFullPath(options.certPath)
-    if options.symbolsPath:
+    if options.symbolsPath and not isURL(options.symbolsPath):
       options.symbolsPath = mochitest.getFullPath(options.symbolsPath)
 
     options.webServer = self._automation.DEFAULT_WEB_SERVER
     options.httpPort = self._automation.DEFAULT_HTTP_PORT
     options.sslPort = self._automation.DEFAULT_SSL_PORT
 
     if options.vmwareRecording:
       if not self._automation.IS_WIN32:
@@ -683,16 +682,16 @@ def main():
   options, args = parser.parse_args()
 
   options = parser.verifyOptions(options, mochitest)
   if options == None:
     sys.exit(1)
 
   options.utilityPath = mochitest.getFullPath(options.utilityPath)
   options.certPath = mochitest.getFullPath(options.certPath)
-  if options.symbolsPath:
+  if options.symbolsPath and not isURL(options.symbolsPath):
     options.symbolsPath = mochitest.getFullPath(options.symbolsPath)
 
   automation.setServerInfo(options.webServer, options.httpPort, options.sslPort)
   sys.exit(mochitest.runTests(options))
 
 if __name__ == "__main__":
   main()
--- a/testing/xpcshell/Makefile.in
+++ b/testing/xpcshell/Makefile.in
@@ -58,16 +58,17 @@ TEST_HARNESS_FILES := \
   runxpcshelltests.py \
   remotexpcshelltests.py \
   head.js \
   $(NULL)
 
 # Extra files needed from $(topsrcdir)/build
 EXTRA_BUILD_FILES := \
   automationutils.py \
+  poster.zip \
   $(NULL)
 
 # And files for running xpcshell remotely from $(topsrcdir)/build/mobile
 MOBILE_BUILD_FILES := \
   devicemanager.py \
   $(NULL)
 
 # Components / typelibs that don't get packaged with