function pyVisHandler($options, $the_content)
{
    $width = getSoft($options, "width", 400);
    $res = ' ';
    if (!array_key_exists("code", $options)) {
        return "pyVis error: code='...' not found";
    }
    $content = $options["code"];
    $content = softSafeDereference($content);
    $content = html_entity_decode(str_replace(" ", ' ', str_replace('<br/>', "\n", $content)));
    $content = trim($content);
    $content = trim($content);
    //  for ($i =0; $i<strlen($content); $i++)
    //  $res .= ' ' . ord($content[$i]);
    //return $res;
    $tag = 'iframe';
    $urlname = 'src';
    //$tag = 'object'; $urlname = 'data'; // doesn't seem to be different
    $url = content_url('plugins/pybox/') . 'OnlinePythonTutor3-cemc/iframe-embed.html#' . 'code=' . urlencode($content) . '&cumulative=false&heapPrimitives=false&drawParentPointers=false&textReferences=false&showOnlyOutputs=false&py=3&curInstr=0&resizeContainer=true&highlightLines&width=' . $width . '&rightStdout=1';
    return "<{$tag} width='100%' height='480' frameborder='0' scrolling='no' {$urlname}='{$url}'></{$tag}>";
}
function postprocesscallback($m)
{
    return softSafeDereference($m[1]);
}
<?php

require_once "include-to-load-wp.php";
$get = softSafeDereference("@file:" . $_GET["file"]);
if (!array_key_exists("file", $_GET) || $get == "@file:" . $_GET["file"]) {
    echo '<html>';
    echo 'Not a valid <code>@file</code> reference, or does not exist: <code>' . htmlspecialchars($_GET["file"]) . '</code>';
    echo '</html>';
    return;
}
?>
<html>
Here are the contents of <code>wp-content/lesson_files/<?php 
echo $_GET["file"];
?>
</code>
<br>
<?php 
echo open_source_preamble();
?>
<hr>
<pre style="white-space:pre-wrap"><?php 
echo htmlspecialchars(softSafeDereference("@file:" . $_GET["file"]));
?>
</pre>
</html>
function softDump($s, $target)
{
    // writes/copies $s to $target, where $s is a string or a @file:filename
    //pyboxlog($s .';' . $target, FALSE);
    if (substr($s, 0, 6) == "@file:") {
        $s = softSafeDereference($s);
    }
    //pyboxlog($s .';' . $target, FALSE);
    $file = fopen($target, "w");
    if ($file === FALSE) {
        return FALSE;
    }
    if (fwrite($file, $s) === FALSE) {
        return FALSE;
    }
    return fclose($file);
}
function pyBoxHandler($options, $content)
{
    //echo "PB[[[".$content."]]]";
    // given a shortcode, print out the html for the user,
    // and save the relevant grader options in a hash file.
    $id = generateId();
    if ($options == FALSE) {
        $options = array();
    }
    // wordpress does a weird thing where valueless
    for ($i = 0; array_key_exists($i, $options); $i++) {
        // attributes map like [0]=>'attname'.
        $options[$options[$i]] = "Y";
        // these lines change it to
        unset($options[$i]);
        // 'attname'=>'Y'
    }
    $shortcodeOptions = json_encode($options);
    // this will be put into DB.
    /// do some cleaning-up and preprocessing of options, and create the problem info for grader
    if (array_key_exists('translate', $options)) {
        $GLOBALS['pb_translation'] = $options['translate'];
    }
    if (array_key_exists('pyexample', $options)) {
        setSoft($options, 'grader', '*nograder*');
        setSoft($options, 'readonly', 'Y');
        setSoft($options, 'hideemptyinput', 'Y');
        unset($options['pyexample']);
    }
    if (array_key_exists('code', $options)) {
        // sugar: code is an alias for defaultcode
        $options["defaultcode"] = $options["code"];
        unset($options['code']);
    }
    $richreadonly = array_key_exists('richreadonly', $options);
    // sugar
    if ($richreadonly) {
        $options['readonly'] = "Y";
        unset($options['richreadonly']);
    }
    if (array_key_exists('nograder', $options)) {
        // syntactic sugar for nograder option
        if (array_key_exists('grader', $options)) {
            pyboxlog('Warning: grader overwritten with *nograder*');
        }
        $options["grader"] = "*nograder*";
        unset($options['nograder']);
    }
    foreach ($options as $optname => $optvalue) {
        // syntactic sugar for inplace grader
        if (preg_match('|tests|', $optname) > 0 || preg_match('|precode|', $optname) > 0) {
            $options["inplace"] = "Y";
        }
    }
    global $post, $lesson_reg_info;
    // $lessonNumber is numeric (major) part of lesson number
    // if lesson_reg_info is set we don't really care about displaying the pybox,
    // but we'll do things for consistency anyway. NB: when displaying a problem
    // in a place other than its original page (e.g., mail) this needs ot be fixed
    $post_title = isset($lesson_reg_info) ? get_the_title($lesson_reg_info['id']) : $post->post_name;
    if (preg_match('|^(\\d+).*|', $post_title, $matches) == 0) {
        $lessonNumber = -1;
    } else {
        $lessonNumber = $matches[1];
    }
    $inplace = booleanize(getSoft($options, 'inplace', 'N'));
    $scramble = booleanize(getSoft($options, 'scramble', 'N'));
    // important booleans used to determine
    $readonly = booleanize(getSoft($options, 'readonly', 'N'));
    // other options... get them first
    $showEditorToggle = booleanize(getSoft($options, 'showeditortoggle', 'N'));
    unset($options['scramble']);
    unset($options['readonly']);
    // don't extract() these!
    unset($options['inplace']);
    if ($inplace) {
        setSoft($options, 'hideemptyoutput', 'Y');
    }
    $defaultValues = array('defaultcode' => FALSE, 'autocommentline' => $lessonNumber > 3 && !($scramble || $readonly), 'console' => 'N', 'rows' => 10, 'allowinput' => $lessonNumber > 5 && !$scramble && !$readonly, 'disablericheditor' => ($lessonNumber > -1 && $lessonNumber < 7 || $scramble || $readonly) && !$richreadonly, 'usertni' => $inplace);
    foreach ($defaultValues as $key => $value) {
        if (!array_key_exists($key, $options)) {
            $options[$key] = $defaultValues[$key];
        }
    }
    extract($options);
    $allowinput = booleanize($allowinput);
    $disablericheditor = booleanize($disablericheditor);
    $console = booleanize($console);
    $autocommentline = booleanize($autocommentline);
    $usertni = booleanize($usertni);
    $facultative = isset($grader) && $grader == '*nograder*' || $console || $readonly;
    if ($scramble || $readonly) {
        $options['nolog'] = 'Y';
    }
    // for grader. note that if they are absent, their default values are 'N'
    if ($facultative) {
        $options['facultative'] = 'Y';
    } else {
        unset($options['facultative']);
    }
    if ($allowinput) {
        $options['allowinput'] = 'Y';
    } else {
        unset($options['allowinput']);
    }
    if ($scramble) {
        $options['scramble'] = 'Y';
    }
    // already unset
    if ($readonly) {
        $options['readonly'] = 'Y';
    }
    if ($inplace) {
        $options['inplace'] = 'Y';
    }
    if ($usertni) {
        $options['usertni'] = 'Y';
    } else {
        unset($options['usertni']);
    }
    $cosmeticOptions = array('defaultcode', 'autocommentline', 'console', 'rows', 'disablericheditor', 'scramble', 'readonly', 'showeditortoggle', 'title', 'placeholder');
    $copyForGrader = array();
    foreach ($options as $optname => $optvalue) {
        if (!in_array($optname, $cosmeticOptions)) {
            $copyForGrader[$optname] = $optvalue;
        }
    }
    if (array_key_exists('maxeditdistance', $options)) {
        $copyForGrader['originalcode'] = $defaultcode;
    }
    $optionsJson = json_encode($copyForGrader);
    $hash = md5($shortcodeOptions . $optionsJson);
    $slug = getSoft($options, 'slug', 'NULL');
    registerPybox($id, $slug, $scramble ? "scramble" : "code", $facultative, getSoft($options, 'title', NULL), $content, $shortcodeOptions, $hash, $optionsJson);
    if (isMakingDatabases()) {
        $res = do_short_and_sweetcode($content);
        // faster db generation with accurate count
        $GLOBALS['pb_translation'] = NULL;
        return $res;
    }
    /// we've delivered options to the grader. get on with producing html
    if ($defaultcode === FALSE && $scramble && $solver !== FALSE) {
        $lines = explode("\n", trim(softSafeDereference($solver)));
        shuffle($lines);
        $defaultcode = implode("\n", $lines);
    }
    if ($defaultcode !== FALSE) {
        try {
            $defaultcode = softSafeDereference($defaultcode);
        } catch (PyboxException $e) {
            $GLOBALS['pb_translation'] = NULL;
            return pberror("PyBox error: defaultcode file " . $defaultcode . " not found.");
        }
        $defaultcode = ensureNewlineTerminated($defaultcode);
    }
    /// actually start outputting here. part 1: headers and description
    $r = '';
    $readyScripts = '';
    $r .= '<form class="pbform" action="#" id="pbform' . $id . '" method="POST">' . "\n";
    if ($scramble) {
        $c = "scramble";
    } else {
        if (debugEnabled()) {
            $c = "debug";
        } else {
            $c = "";
        }
    }
    if ($facultative) {
        $c .= " facultative";
    }
    $r .= "<div class='pybox modeNeutral {$c}' id='pybox{$id}'>\n";
    if (!$facultative && !array_key_exists("slug", $options)) {
        pyboxlog("Hash " . $hash . " not read-only, but needs a slug", TRUE);
        $r .= slugwarn();
    }
    if ($facultative) {
        if ($console) {
            unset($options["title"]);
            $r .= heading("Console", $options);
        } else {
            $r .= heading(__t('Example'), $options);
        }
    } else {
        $r .= checkbox($slug);
        $r .= heading($scramble ? __t('Scramble Exercise') : __t('Coding Exercise'), $options);
        //if ($scramble)
        //  $r .= "<b>Note (Dec 13)</b>: scramble exercises are temporarily broken &mdash; sorry!<br>";
    }
    $r .= do_short_and_sweetcode($content);
    //instructions, problem description. process any shortcodes inside.
    // part 1.5: help box
    if (!$facultative && !$scramble) {
        $r .= '<div class="helpOuter" style="display: none;"><div class="helpInner">';
        if (!is_user_logged_in()) {
            $r .= '<div style="text-align: center">' . __t('You need to create an account and log in to ask a question.') . '</div>';
        } else {
            global $wpdb;
            $guru_login = get_the_author_meta('pbguru', get_current_user_id());
            if ($guru_login != '') {
                $guruid = $wpdb->get_var($wpdb->prepare('SELECT ID from ' . $wpdb->prefix . 'users WHERE user_login = %s', $guru_login));
            }
            $r .= '<div style="text-align: center">';
            if ($guru_login != '' and $guruid !== NULL) {
                $r .= __t('Send a question by e-mail to: ');
                $r .= "<select class='recipient'>\n<option value='1'>" . __t("My guru") . " ({$guru_login})</option>\n<option value='-1'>" . __t("CS Circles Assistant") . "</option>\n</select></div>";
            } else {
                $r .= __t('Send a question by e-mail to: ');
                $r .= "<select class='recipient'>\n<option value='-1'>" . __t("CS Circles Assistant") . "</option>\n<option value='0'>" . __t("(No guru specified in your profile)") . "</option>\n</select>";
                $r .= '<br/></div>';
            }
            $r .= __t("Enter text for the message below. <i>Be sure to explain where you're stuck and what you've tried so far. Your partial solution code will be automatically included with the message.</i>");
            $r .= "<textarea style='font-family: serif'></textarea>";
            $r .= "<table class='helpControls'><tr class='wp-core-ui'><td style='width: 50%'><a class='button' onclick='sendMessage({$id},\"{$slug}\")'>" . __t("Send this message") . "</a></td><td style='width: 50%'>\n           <a class='button' onclick='helpClick({$id})'>" . __t("Cancel") . "</a></td></tr></table>";
        }
        $r .= '</div></div>';
    }
    /// part 2: code input
    if ($readonly) {
        $thecode = trim($defaultcode);
        $rows = count(explode("\n", $thecode));
    } elseif ($console == "Y" && array_key_exists("consolecode", $_GET)) {
        $thecode = htmlspecialchars(html_entity_decode(stripslashes($_GET["consolecode"])));
        $rows = count(explode("\n", $thecode)) + 1;
    } else {
        $thecode = $defaultcode;
        if ($autocommentline) {
            $thecode .= __t('# delete this comment and enter your code here') . "\n";
        }
        if (array_key_exists('slug', $options) && $scramble === FALSE) {
            $savedCode = loadMostRecent($options['slug']);
            if ($savedCode !== NULL) {
                $thecode = $savedCode;
            }
        }
    }
    if ($scramble) {
        $r .= '<ul class="pyscramble" name="pyscramble" id="pyscramble' . $id . '">' . "\n";
        foreach (explode("\n", rtrim($thecode)) as $s) {
            if (strpos($s, 'delete this comment') === FALSE) {
                // fix an old bug -- got stuck in database
                $r .= ' <li class="pyscramble">' . (trim($s) == '' ? '&nbsp;' : htmlspecialchars(html_entity_decode($s))) . "</li>\n";
            }
        }
        $r .= "</ul>\n";
        $r .= "<input type='hidden' id='usercode{$id}' name='usercode{$id}'/>\n";
    } else {
        //    $r .= "<div class='acecontain ace_hide' id='acecontain$id' ><div class='aceinner' id='ace$id'></div></div>";
        $px = $rows * 26 + 6;
        //+6 for border, padding in weird box model
        $h = $px;
        if (!$readonly) {
            $h = max(50, $h);
        }
        $h = " style='height: {$h}px;'";
        $ro = $readonly ? "readonly='readonly'" : "";
        $c = $readonly ? "RO" : "RW";
        $p = $readonly ? " style = 'height : {$px}px;' " : "";
        $s = $readonly ? "" : "resizy";
        //cols=... required for valid html but width actually set by css
        //height is set explicitly since it's the only way for IE to render the textarea at the correct height
        $pl = array_key_exists("placeholder", $options) ? "placeholder='" . $options['placeholder'] . "'" : "";
        $r .= "<div class='pyboxTextwrap pyboxCodewrap {$c} {$s}' {$h}><textarea wrap='off' name='usercode{$id}' id='usercode{$id}' {$pl} cols=10 rows={$rows} {$ro} {$p} class='pyboxCode {$c}'>\n";
        $r .= $thecode;
        $r .= '</textarea></div>' . "\n";
    }
    // part 2.5 history container
    $r .= "<div id='pbhistory{$id}' class='flexcontain' style='display:none;'></div>\n";
    /// part 3: stdin
    if ($allowinput) {
        if ($usertni === TRUE) {
            $description = __t('Enter testing statements like <tt>print(myfunction("test argument"))</tt> below.');
        } else {
            $description = __t("You may enter input for the program in the box below.");
        }
        $r .= '<div name="pyinput" id="pyinput' . $id . '">';
        $r .= $description;
        $r .= '<div class="pyboxTextwrap resizy" style="height: 102px;" ><textarea wrap="off" name="userinput" class="pyboxInput" cols=10 rows=4></textarea></div>';
        $r .= '</div>' . "\n";
        //cols=10 required for valid html but width actually set by css
    }
    /// part 4: controls
    $tni = $usertni ? 'Y' : 'N';
    $actions = array();
    if ($allowinput) {
        $actions['switch'] = array('id' => "switch{$id}", 'value' => 'Input Switch', 'onclick' => "pbInputSwitch({$id},'{$tni}')");
    }
    if (!$disablericheditor) {
        //    $userLikesRich = (!is_user_logged_in()) || ("true"!==get_the_author_meta( 'pbplain', get_current_user_id()));
        $userLikesRich = TRUE;
        if ($showEditorToggle || $richreadonly) {
            $actions['CMtoggle'] = array('value' => __t('Rich editor'), 'id' => "toggleCM{$id}", 'onclick' => "pbToggleCodeMirror({$id})");
        }
        if ($userLikesRich) {
            $readyScripts .= "jQuery(function(){pbToggleCodeMirror({$id});});";
        }
    }
    if (!$scramble && !$console && ($lessonNumber >= 4 || $lessonNumber < 0)) {
        $actions['consolecopy'] = array('value' => __t('Open in console'), 'onclick' => "pbConsoleCopy({$id})");
    }
    if (!$scramble && ($lessonNumber >= 4 || $lessonNumber < 0)) {
        $actions['visualize'] = array('value' => __t('Visualize'), 'onclick' => "pbVisualize({$id},'{$tni}')");
    }
    if (!$readonly && !$scramble) {
        //$actions['save'] = array('value'=>'Save without running', 'onclick'=>"pbSave($id)");
        if (array_key_exists("slug", $options)) {
            $historyAction = "historyClick({$id},'{$slug}')";
            $actions['history'] = array('value' => __t('History'), 'onclick' => $historyAction);
        }
        if (!($readonly === "Y") && $defaultcode != '' && $defaultcode !== FALSE) {
            // prepare the string for javaScript enclosure
            // we put in single-quotes, rather than json's default double quotes, for compatibility with
            // our $button usage
            $dc = substr(json_encode(htmlspecialchars_decode($defaultcode, ENT_QUOTES), JSON_HEX_APOS), 1, -1);
            $r .= "<input type='hidden' id='defaultCode{$id}' value='{$dc}'></input>\n";
            $actions['default'] = array('value' => __t('Reset code to default'), 'onclick' => "pbSetText({$id},descape(\$('#defaultCode{$id}').val()))");
        }
    }
    if (!$facultative && !$scramble && !get_option('cscircles_hide_help')) {
        $actions['help'] = array('value' => __t('Help'), 'onclick' => "helpClick({$id});");
    }
    if ($richreadonly) {
        $actions = array('CMtoggle' => $actions['CMtoggle']);
    }
    // get rid of all other options
    $r .= "<div class='pyboxbuttons'><table><tr>\n";
    if (!$richreadonly) {
        $r .= "<td><input type='submit' name='submit' id='submit{$id}' value=' '/></td>\n";
    }
    $mb = 3;
    //maximum number of buttons, not counting 'submit'
    $i = 0;
    foreach ($actions as $name => $atts) {
        $i++;
        if ($i <= $mb) {
            $r .= button($name, $atts);
            continue;
        }
        if ($i == 1 + $mb) {
            $r .= "</tr></table><select id='pbSelect{$id}' class='selectmore'><option name='more'>" . __t("More actions...") . "</option>\n";
        }
        $r .= option($name, $atts);
    }
    if (count($actions) > $mb) {
        $r .= "</select></div>\n";
    } else {
        $r .= "</tr></table></div>\n";
    }
    if (isset($cpulimit) && $cpulimit != 1) {
        $timeout = (WALLFACTOR * $cpulimit + WALLBUFFER + 2) * 1000;
        // + 2 seconds for network latency each way
        $r .= "<input type='hidden' name='timeout' value='{$timeout}'/>\n";
    }
    $r .= '<input type="hidden" name="lang" value="' . currLang4() . '"/>';
    $r .= '<input type="hidden" id="inputInUse' . $id . '" name="inputInUse" value="Y"/>' . "\n";
    $r .= '<input type="hidden" name="pyId" value="' . $id . '"/>' . "\n";
    $r .= '<input type="hidden" name="hash" value="' . $hash . '"/>' . "\n";
    // although inputInUse starts as Y, the next script sets it to N and fixes the button labels
    $readyScripts .= $allowinput ? 'pbInputSwitch(' . $id . ',"' . ($usertni ? 'Y' : 'N') . '");' : 'document.getElementById("submit' . $id . '").value = "' . __t('Run program') . '";' . 'document.getElementById("inputInUse' . $id . '").value = "N";';
    /// part 5 : results area, and footers
    $c = count($actions) > $mb ? ' avoidline' : '';
    $r .= "<div id='pbresults{$id}' class='pbresults{$c}'></div>\n";
    $r .= problemSourceWidget(array('hash' => $hash), count($actions) > $mb);
    $r .= '</div>' . "\n";
    $r .= '</form>' . "\n";
    if ($readyScripts != '') {
        $r .= "<script type='text/javascript'>{$readyScripts}</script>\n";
    }
    $GLOBALS['pb_translation'] = NULL;
    return $r;
}
function doGrading($usercode, $TC)
{
    $files = array();
    if ($TC['showonly'] !== FALSE) {
        $desired = explode(" ", $TC['showonly']);
        foreach ($TC as $name => $value) {
            if (substr($name, 0, 4) == "show") {
                $TC[$name] = in_array(substr($name, 4), $desired) ? "Y" : "N";
            }
        }
    }
    if ($TC['answer'] !== FALSE) {
        $TC['answer'] = ensureNewlineTerminated($TC['answer']);
    }
    $TC["inplace"] = booleanize($TC["inplace"]);
    extract($TC);
    // same as $showinput = $TC["showinput"], etc
    $mainFile = "";
    $er = FALSE;
    $mainFile .= "from _UTILITIES import *\n";
    $lang = 'en_US';
    if (array_key_exists("lang", $_REQUEST) && preg_match("~^[a-zA-Z_]*\$~", $_REQUEST["lang"])) {
        $lang = $_REQUEST["lang"];
    }
    $mainFile .= "_setLanguage('{$lang}')\n";
    $inputMaker = inputMaker($TC);
    $noInput = $inputMaker === FALSE;
    $mainFile .= ($inputMaker === FALSE ? "_stdin=''" : $inputMaker) . "\n_stdincopy = open('stdincopy', 'w', encoding='utf-8')\nprint(_stdin, file=_stdincopy, end='')\n_stdincopy.close()\n";
    if ($precode !== FALSE) {
        $mainFile .= softSafeDereference($precode) . "\n";
    }
    $files['stdincopy'] = NULL;
    $mainFile .= "import _GRADER\n";
    $mainFile .= "_G = _GRADER\n";
    global $inputInUse, $facultative;
    if (!$inputInUse && ($inplace || $solver !== FALSE)) {
        if ($solver !== FALSE) {
            $files['solver'] = $solver;
        }
        if ($solver !== FALSE) {
            $mainFile .= "_GRADER.globalsInitAndEcho(globals())\n";
        } else {
            $mainFile .= "_GRADER.globalsInitAndEcho(globals(), False)\n";
        }
        $files['graderreply'] = NULL;
        $files['graderpre'] = NULL;
        $files['solverstdout'] = NULL;
        // run the solver before usercode, lest they mess up our globals.
        $mainFile .= "_GRADER.runSolverWithTests()\n";
        $testcode = "";
        if ($rawtests !== FALSE) {
            $testcode .= $rawtests . "\n";
        }
        if ($autotests != FALSE) {
            $autotests = softSafeDereference($autotests);
            $python_ident_regex = '(\\p{L}|\\p{Nl}|_)(\\p{L}|\\p{N}|\\p{Mn}|\\p{Mc}|\\p{Pc})*';
            // note: this is close to, but not technically, 100% the
            // same as the formal Python definition of an identifier
            $py_regex_parens = 2;
            foreach (explode("\n", $autotests) as $autotestline) {
                if (preg_match('|^(\\s*)(\\S.*)$|', $autotestline, $matches) === 0) {
                    continue;
                }
                //skip blank lines
                $indentation = $matches[1];
                $command = trim($matches[2]);
                if (1 == preg_match('@^' . $python_ident_regex . '$@u', $command)) {
                    //varname
                    $testcode .= $indentation . "_G.checkVar('{$command}')\n";
                } elseif (1 == preg_match('@^(' . $python_ident_regex . ')\\s*\\((.*)\\)$@u', $command, $pieces)) {
                    if (strpos($pieces[2], $pieces[1]) === FALSE) {
                        // looks like a non-self-nested function call
                        $testcode .= $indentation . "_G.autotestCall('" . $pieces[1] . "',[" . $pieces[2 + $py_regex_parens] . "])\n";
                    } else {
                        // something more complex
                        $testcode .= $indentation . "_G.sayRunning(\"" . $command . "\")\n";
                        $testcode .= $indentation . "_G.autotestCompare(\"" . $command . "\", {$command})\n";
                    }
                } else {
                    $testcode .= $autotestline . "\n";
                }
                // just leave it alone
            }
        }
        $files['testcode'] = $testcode === FALSE ? "" : softSafeDereference($testcode) . "\n";
    }
    $mainFile .= '
_orig_std = (_sys.stdin, _sys.stdout)
_user_stdout = _StringIO()
_sys.stdout = _TeeOut(_user_stdout, _orig_std[1])
_sys.stdin = _StringIO(_stdin)
exec(compile(open(\'usercode\', encoding="utf-8").read(), ' . '\'usercode\', \'exec\'))
';
    if (!$inputInUse) {
        // lesson 18, part 2: may do this even if facultative
        if ($inplace) {
            $mainFile .= "exec(compile(open('testcode', encoding='utf-8').read()," . " 'testcode', 'exec'))\n";
            $mainFile .= "_G.say('Y', 'noend')\n";
            // success if none of the tests crash
        }
    }
    // we've got all the user stdout necessary for testing
    $mainFile .= '
__user_stdout = _user_stdout.getvalue()
_user_stdout.close()
(_sys.stdin, _sys.stdout) = _orig_std
';
    if (!$facultative && !$inputInUse) {
        if ($answer !== FALSE) {
            $mainFile .= "_G._solver_stdout = " . pythonEscape(softSafeDereference($answer)) . "\n";
        }
        if ($grader !== '*nograder*' && ($answer !== FALSE || $solver !== FALSE)) {
            $mainFile .= "_G.stdoutGrading(_stdin,__user_stdout,_G._solver_stdout, " . pythonEscape(softSafeDereference($grader)) . " )\n";
            $files['stdoutgraderreply'] = NULL;
        }
    }
    $testDescription = FALSE;
    $files["usercode"] = $usercode;
    global $usertni;
    if ($inputInUse && $usertni) {
        $mainFile .= "\n" . "exec(compile(open('usertests', encoding='utf-8').read(), " . "'usertests', 'exec'))\n";
        global $userinput;
        $files['usertests'] = $userinput;
    }
    $files["mainfile"] = $mainFile;
    $userResult = safepython($files, "mainfile", "", $cpulimit);
    extract($userResult);
    // start printing stuff out now.
    $m = '';
    if ($testDescription != FALSE) {
        $m .= $testDescription;
    }
    if (!$inputInUse && $inplace && trim($outdata['graderpre']) != '') {
        $m .= '<i>' . __t('Before running your code:') . '</i> ' . $outdata['graderpre'] . '<br/>';
    }
    if ($showinput == "Y" && !$inputInUse && !$noInput && ($hideemptyinput == "N" || $outdata['stdincopy'] != "")) {
        $m .= __t("Input:") . preBox($outdata['stdincopy']);
    }
    global $submit_code_stderr, $submit_code_errnice;
    $submit_code_stderr = $stderr;
    $submit_code_errnice = stderrNiceify($stderr);
    if (userIsAdmin() && $stderrlen > 0) {
        $m .= JQpopUp("Debug: view unsanitized", preBox($stderr, $stderrlen));
    }
    if ($stderr == '') {
        $errnice = '';
    } else {
        $errnice = '<p>' . __t('Error messages: ') . preBoxHinted(stderrNiceify($stderr), $stderrlen) . '</p>';
    }
    if ($ok) {
        $m .= "<p>" . __t('Program executed without crashing.') . "</p>";
    } elseif (firstLine($safeexecOut) == 'Command exited with non-zero status (1)') {
        $m .= "<p>" . __t("Program crashed.") . "</p>";
    } else {
        $m .= "<p>" . __t("Program crashed &mdash; ") . firstLine($safeexecOut) . ".</p>";
    }
    if (1 === 2) {
        // these lines are just to trick gettext
        __t("Memory Limit Exceeded") . __t("Time Limit Exceeded") . __t("Command exited with non-zero status") . __t("Command terminated by signal") . __t("Output Limit Exceeded") . __t("Invalid Function") . __t("Internal Error");
    }
    if ($showsafeexec == "Y") {
        $m .= "Sandbox messages:" . preBox($safeexecOut);
    }
    $simpleOutputDescription = outputDescription(NULL, array('showoutput' => $showoutput, 'stdoutlen' => $stdoutlen, 'hideemptyoutput' => $hideemptyoutput, 'stdout' => $stdout, 'ok' => $ok));
    if ($desirederror !== FALSE) {
        $m .= $simpleOutputDescription;
        $lines = explode("\n", trim($userResult["stderr"]));
        $goodFail = count($lines) > 0 && $lines[count($lines) - 1] == $desirederror;
        $m .= $errnice;
        return $goodFail ? tcpass($m) : tcfail($m);
    }
    if (!$ok || $facultative) {
        // we don't care what's in stdout
        $graderreply = trim(getSoft($outdata, 'graderreply', ''));
        if (!$ok && !$inputInUse && $graderreply != '') {
            $m .= "<i>" . __t("The grader said:") . "</i>" . "<div>" . $graderreply . "</div>";
        } elseif ($inplace && $solver === FALSE & $graderreply != '') {
            $m .= "<i>" . __t("Automatic tests:") . "</i>" . "<div>" . substr($graderreply, 0, -1) . "</div>";
        }
        $m .= $errnice . $simpleOutputDescription;
        return $ok ? tcpass($m) : tcfail($m);
    }
    if ($inplace) {
        // don't care what's in stdout, unless solverstdout != ''
        $GR = $outdata['graderreply'];
        $inplaceresult = substr($GR, -1);
        $inplacereply = substr($GR, 0, -1);
        if ($inplacereply != '') {
            $inplacereply = "<i>" . __t("The grader said:") . "</i>" . "<div>{$inplacereply}</div>";
        }
        if ($inplaceresult == 'Y') {
            if ($outdata['solverstdout'] == '') {
                return tcpass($m . $inplacereply . $errnice . $simpleOutputDescription);
            }
        } elseif ($inplaceresult == 'N') {
            return tcfail($m . $inplacereply . $errnice . $simpleOutputDescription);
        }
        $m .= $inplacereply;
        // carry on and let the stdout grader do its thing
    }
    // the user's code did not crash. what did the stdout grader say?
    $outGraderReply = $outdata['stdoutgraderreply'];
    if ($outGraderReply == "" || !($outGraderReply[0] == "Y" || $outGraderReply[0] == "N")) {
        throw new PyboxException("Grader error 2 [" . $outGraderReply . '|' . $outdata['graderreply'] . "|" . ord(substr($outdata['graderreply'], -1)) . "| {$m} ]");
    }
    $outinfo = array('stdout' => $stdout, 'stdoutlen' => $stdoutlen, 'requiredStdout' => getSoft($outdata, 'solverstdout', $answer), 'showoutput' => $showoutput, 'showexpected' => $showexpected, 'grader' => $grader);
    $m .= outputDescription($outGraderReply[0] == "Y", $outinfo) . $errnice;
    if (strlen(trim($outGraderReply)) > 1) {
        $m .= "<p>" . __t("Result of grading: ") . substr($outGraderReply, 1) . "</p>";
    }
    return $outGraderReply[0] == "Y" ? tcpass($m) : tcfail($m);
}