function dbProblemHistory($limit, $sortname, $sortorder, $req = NULL) { global $db_query_info; $db_query_info = array(); if ($req == NULL) { $req = $_REQUEST; } $db_query_info['type'] = 'problem-history'; $problemname = getSoft($req, "p", ""); //which problem? $user = getSoft($req, "user", ""); if ($problemname == "") { return __t("You must enter a non-empty problem name."); } $db_query_info['problem'] = $problemname; $resultdesc = array('y' => __t('Did not crash.'), 'Y' => __t('Correct!'), 'N' => __t('Incorrect.'), 'E' => __t('Internal error.'), 'S' => __t('Saved.'), 's' => __t('Saved.')); if (!is_user_logged_in()) { return __t("You must log in to view past submissions."); } if ((userIsAdmin() || userIsAssistant()) && $user != "") { $u = get_userdata($user); if ($u === false) { return sprintf(__t("User number %s not found."), $u); } $db_query_info['viewuser'] = $user; } else { $u = wp_get_current_user(); } $uid = $u->ID; $uname = $u->user_login; global $wpdb; $table_name = $wpdb->prefix . "pb_submissions"; $counts = $wpdb->get_results($wpdb->prepare("SELECT COUNT(1), COUNT(userinput) from {$table_name}\nWHERE userid = %d AND problem = %s", $uid, $problemname), ARRAY_N); $count = $counts[0][0]; $showInputColumn = $counts[0][1] > 0; if ($count == 0) { return sprintf(__t('We do not have record of any submissions from user %1$s for problem %2$s.'), $uname . ' (#' . $uid . ')', $problemname); } $knownFields = array(__t("time & ID") => "beginstamp", __t("user code") => "usercode", __t("user input") => "userinput", __t("result") => "result"); if (array_key_exists($sortname, $knownFields)) { $sortString = $knownFields[$sortname] . " " . $sortorder . ", "; } else { $sortString = ""; } $prep = $wpdb->prepare("SELECT ID, beginstamp, usercode, userinput, result from {$table_name}\nWHERE userid = %d AND problem = %s ORDER BY {$sortString} ID DESC" . $limit, $uid, $problemname); $flexirows = array(); foreach ($wpdb->get_results($prep, ARRAY_A) as $r) { $cell = array(); $cell[__t('user code')] = preBox($r['usercode'], -1, -1); if ($showInputColumn) { $cell[__t('user input')] = $r['userinput'] === NULL ? '<i>' . __t('n/a') . '</i>' : preBox($r['userinput'], -1, 100000); } if ($problemname != "visualizer") { $cell[__t('result')] = getSoft($resultdesc, $r['result'], $r['result']); } $cell[__t('time & ID')] = str_replace(' ', '<br/>', $r['beginstamp']) . '<br/>#' . $r['ID']; $flexirows[] = array('id' => $r['ID'], 'cell' => $cell); } return array('total' => $count, 'rows' => $flexirows); }
function dbProblemSummary($limit, $sortname, $sortorder, $req = NULL) { global $db_query_info; $db_query_info = array(); if ($req == NULL) { $req = $_REQUEST; } $db_query_info['type'] = 'problem-summary'; if (!is_user_logged_in()) { return __t("You must log in to view past submissions."); } $problemslug = getSoft($req, "p", ""); //which problem? if ($problemslug == "") { return __t("You must enter a non-empty problem name."); } global $wpdb; $problem_table = $wpdb->prefix . "pb_problems"; $problemname = $wpdb->get_var($wpdb->prepare("SELECT publicname FROM {$problem_table} WHERE lang = '%s' AND slug = '%s'", pll_current_language(), $problemslug)); if ($problemname == null) { return sprintf(__t("Problem %s not found (at least in current language)"), $problemslug); } $db_query_info['problem'] = $problemslug; $u = wp_get_current_user(); $uid = $u->ID; $db_query_info['viewuser'] = $uid; $ulogin = $u->user_login; $submit_table = $wpdb->prefix . "pb_submissions"; $usermeta_table = $wpdb->prefix . "usermeta"; $user_table = $wpdb->prefix . "users"; $complete_table = $wpdb->prefix . "pb_completed"; $count = $wpdb->get_var(userIsAdmin() ? "SELECT count(1) FROM {$user_table}" : $wpdb->prepare("SELECT count(1) FROM {$usermeta_table} WHERE meta_key=%s AND meta_value=%s", 'pbguru', $ulogin)); $students = $wpdb->get_results(userIsAdmin() ? "SELECT ID FROM {$user_table} {$limit}" : $wpdb->prepare("SELECT user_id AS ID FROM {$usermeta_table} WHERE meta_key=%s AND meta_value=%s {$limit}", 'pbguru', $ulogin)); // no sorting allowed due to weird nature of query $flexirows = array(); foreach ($students as $r) { $sid = $r->ID; $sdata = $wpdb->get_row($wpdb->prepare("SELECT usercode, beginstamp FROM {$submit_table} \n WHERE userid={$sid} and problem='%s' and result='Y'\n ORDER BY beginstamp DESC limit 1", $problemslug)); $s = get_userdata($sid); $cell = array(); $cell['ID'] = $sid; $cell['info'] = userString($sid); if ($sdata != null) { $cell[__t('latest correct')] = prebox($sdata->usercode); $cell[__t('last time')] = $sdata->beginstamp; $cell[__t('first time')] = $wpdb->get_var($wpdb->prepare("SELECT time FROM {$complete_table} WHERE userid={$sid} and problem='%s'", $problemslug)); } else { $cell[__t('latest correct')] = '<i>n/a</i>'; $cell[__t('last time')] = '<i>n/a</i>'; $cell[__t('first time')] = '<i>n/a</i>'; } $flexirows[] = array('id' => $sid, 'cell' => $cell); } return array('total' => $count, 'rows' => $flexirows); }
function dbFlexigrid($innerFunction, $headers = TRUE) { $userid = getUserID(); $profilingID = beginProfilingEntry(array("activity" => "database", "userid" => $userid)); $page = getSoft($_REQUEST, "page", -1); //flexigrid required $rp = getSoft($_REQUEST, "rp", -1); //flexigrid required: results per page if (!is_numeric($page) || $page <= 0) { $page = 1; } if (!is_numeric($rp) || $rp < 0) { $rp = 1; } // $rp == 0 means you just want the count, it is not a real interface with flexigrid $sortname = trim(getSoft($_REQUEST, "sortname", NULL)); if ($sortname == "undefined") { $sortname = NULL; } $sortorder = trim(getSoft($_REQUEST, "sortorder", "")); // not yet utilized: sortname, sortorder, qtype, query if (strtoupper($sortorder) != "ASC") { $sortorder = "DESC"; } global $db_query_info; $result = $innerFunction(" LIMIT " . ($page - 1) * $rp . ", " . $rp . " ", $sortname, $sortorder); if ($headers) { header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT"); header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); header("Content-type: text/x-json"); } $activity = "database-"; if (array_key_exists('type', $db_query_info)) { $activity .= $db_query_info['type']; unset($db_query_info['type']); } if (is_array($result)) { // success case $result['page'] = $page; $db_query_info['result'] = 'success'; endProfilingEntry($profilingID, array("activity" => $activity, "meta" => $db_query_info)); return json_encode($result); } else { $db_query_info['result'] = 'error'; endProfilingEntry($profilingID, array("activity" => $activity, "meta" => $db_query_info)); return json_encode("Error: " . $result); // failure case; just sending a string. } }
function send($problem_info, $from, $to, $student, $slug, $body, $noreply) { global $wpdb, $current_user, $lang; $unanswered = getUserID() == $student ? 1 : 0; if (getUserID() != $student) { $wpdb->update($wpdb->prefix . 'pb_mail', array('unanswered' => 0), array('unanswered' => 1, 'ustudent' => $student, 'problem' => $slug)); } if ($noreply != 'false') { // don't redirect return "#"; } $insert_to = $to; if ($to == 0 && $lang != 'en') { $insert_to = getSoft(unserialize(CSCIRCLES_ASST_ID_MAP), $lang, $insert_to); } $wpdb->insert($wpdb->prefix . 'pb_mail', array('ufrom' => $from, 'uto' => $insert_to, 'ustudent' => $student, 'problem' => $slug, 'body' => $body, 'unanswered' => $unanswered), array('%d', '%d', '%d', '%s', '%s', '%d')); $mailref = $wpdb->insert_id; if (userIsAdmin() || userIsAssistant()) { $mFrom = '"' . __t("CS Circles Assistant") . '" <' . CSCIRCLES_BOUNCE_EMAIL . '>'; } else { $mFrom = '"' . $current_user->user_login . '" <' . $current_user->user_email . '>'; } $subject = __t('CS Circles') . ' - ' . __t('message about') . ' ' . $problem_info['publicname']; $contents = $body . "\n===\n"; $contents .= __t("To send a reply message, please visit") . "\n"; $contents .= cscurl('mail') . "?who={$student}&what={$slug}&which={$mailref}#m\n"; $contents .= __t("Problem URL:") . " " . $problem_info['url'] . "\n"; $contents .= "[" . __t("Sent by CS Circles") . " " . cscurl("homepage") . "]"; if ($to == 0) { // same fallback as admin-options.php $to_emailaddr = get_option('cscircles_asst_email', get_userdata(1)->user_email); $tmp = getSoft(unserialize(CSCIRCLES_ASST_ID_MAP), $lang, -1); if ($lang != 'en' && $tmp != -1) { $to_emailaddr = get_user_by('id', $tmp)->user_email; } } else { $to_emailaddr = get_user_by('id', $to)->user_email; } //pyboxlog($mFrom . " " . $to_emailaddr . " " . $subject . " " . $contents); pb_mail($mFrom, $to_emailaddr, $subject, $contents); if (get_the_author_meta('pbnocc', getUserID()) != 'true') { $to_desc = $to == 0 ? "the CS Circles Assistant" : get_user_by('id', $to)->user_login; pb_mail($mFrom, $current_user->user_email, __t("SENT:") . " " . $subject, sprintf(__t("THIS IS A COPY of a message you sent to %s."), $to_desc) . "\n\n" . $contents); } return $mailref; }
function db_profiling($options, $content) { $r = '<form>'; $r .= optionsHelper(array('4' => 'Year', '7' => 'Month', '10' => 'Day', '13' => 'Hour', '16' => 'Minute'), 'frequency'); $r .= optionsHelper(array('all' => 'All', 'noDatabases' => 'No databases', 'databases' => 'Databases'), 'activity'); $r .= '<input type="submit"/></form>'; $url = UPYBOX . 'db-profiling.php'; $period = getSoft($_GET, 'period', ''); $F = getSoft($_GET, 'frequency', ''); $A = getSoft($_GET, 'activity', ''); $r .= <<<EOT <script type='text/javascript'> \$ = jQuery; \$('.entry-content').append('<div id="zzz"></div>'); \$(function(){pyflex({'id':'zzz','url': '{$url}', 'dbparams': {'frequency':'{$F}','activity':'{$A}'}})}); </script> EOT; return $r; }
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}>"; }
<?php // this file is used for debugging purposes, so site admins can quickly see a problem's description require_once "include-to-load-wp.php"; global $wpdb; $row = $wpdb->get_results($wpdb->prepare("\nSELECT * FROM " . $wpdb->prefix . "pb_problems WHERE hash = %s", getSoft($_GET, "hash", "")), ARRAY_A); foreach ($row[0] as $field => $value) { if ($field == 'shortcodeArgs' || $field == 'graderArgs') { echo "<b>{$field}</b><br/>"; foreach (json_decode($value) as $sf => $sv) { echo '---' . $sf . preBox($sv); } } else { echo "<b>{$field}</b><br/>" . preBox($value); } }
<?php require_once "include-to-load-wp.php"; $message = $_REQUEST["message"]; $millis = $_REQUEST["millis"]; $user_stdin = $_REQUEST["user_stdin"]; $user_script = $_REQUEST["user_script"]; $error = getSoft($_REQUEST, "error", ""); $meta = array('message' => $message, 'user_stdin' => $user_stdin, 'user_script' => $user_script); if ($error != "") { $meta['error'] = $error; if ($message == 'failed') { pyboxlog("Notified of a visualizer error" . "\n" . $error . "\n" . $_SERVER['SERVER_PROTOCOL'] . " " . $_SERVER['HTTP_USER_AGENT'] . " " . $_SERVER["REMOTE_ADDR"] . " " . getUserID() . "\n" . $user_stdin . "\n" . $user_script); } } retroProfilingEntry($millis * 0.001, array('activity' => 'visualize', 'meta' => $meta));
function reselector(&$students, $cstudents) { global $wpdb; $problem_table = $wpdb->prefix . "pb_problems"; $problems = $wpdb->get_results("SELECT * FROM {$problem_table} WHERE facultative = 0 AND lang = '" . pll_current_language() . "' AND lesson IS NOT NULL ORDER BY lesson ASC, boxid ASC", ARRAY_A); $problemsByNumber = array(); foreach ($problems as $prow) { $problemsByNumber[$prow['slug']] = $prow; } $gp = getSoft($_GET, "what", ""); if ($gp != "" && $gp != "console" && !array_key_exists($gp, $problemsByNumber)) { echo sprintf(__t("Problem %s not found (at least in current language)"), $gp); return; } $preamble = "<div class='progress-selector'>\n <form method='get'><table style='border:none'>"; if ($cstudents > 0 || userIsAssistant()) { // slightly leaky but assistants will want to see progress $preamble .= "<tr><td>" . sprintf(__t("View mail with one of your students? (you have %s)"), $cstudents) . '</td><td>'; $options = array(); $options[''] = __t('Me'); if (!userIsAdmin()) { foreach ($students as $student) { $info = get_userdata($student); $options[$info->ID] = userString($info->ID); } } if (userIsAdmin()) { $preamble .= 'blank: you; "all": all; id#: user (<a href="' . cscurl('allusers') . '">list</a>) <input style = "padding:0px;width:60px" type="text" name="user" value="' . getSoft($_REQUEST, 'user', '') . '">'; } else { $preamble .= optionsHelper($options, 'who'); } $preamble .= "</td></tr>"; } $preamble .= "<tr><td>" . __t("View mail for another problem?") . "</td><td>"; $options = array(); $options[''] = 'all problems'; foreach ($problems as $problem) { if ($problem['type'] == 'code') { $options[$problem['slug']] = $problem['publicname']; } } $preamble .= optionsHelper($options, 'what') . "</td></tr>"; $preamble .= "</td></tr><tr><td colspan='2' style='text-align:center'><input style='width: 25%' type='submit' value='" . __t('Submit') . "'/></tr></td></table></form></div>"; return $preamble; }
or an array-pair (total, array of (id, cell) array-pairs), where each cell is an array representing a row. */ echo dbFlexigrid(function ($limit, $sortname, $sortorder) { global $db_query_info; $db_query_info = array(); $db_query_info['type'] = 'profiling'; if (!userIsAdmin()) { return "Error"; } global $wpdb; $L = getSoft($_POST, 'frequency', ''); if (!is_numeric($L) || $L <= 0) { $L = 10; } $A = getSoft($_POST, 'activity', ''); if ($A == 'all' || $A == '') { $where = ""; } else { if ($A == 'noDatabases') { $where = "WHERE activity NOT LIKE 'database%'"; } else { if ($A == 'databases') { $where = "WHERE activity LIKE 'database%'"; } else { $where = $wpdb->prepare("WHERE activity LIKE %s", $A); } } } $sortString = trim($sortname) == "" ? "" : " {$sortname} {$sortorder} "; $count = $wpdb->get_var("\nSELECT count(distinct activity, substring(start, 1, {$L}))\nFROM " . $wpdb->prefix . "pb_profiling\n{$where}");
function optionsHelper($options, $argname) { // $options is an associative array mapping value=>text for html <options> elements $select = getSoft($_GET, $argname, NULL); $r = "<select name='{$argname}'>"; foreach ($options as $key => $text) { if ($key == $select) { $r .= "<option value='{$key}' selected='selected'>{$text}</option>"; } else { $r .= "<option value='{$key}'>{$text}</option>"; } } $r .= '</select>'; return $r; }
function dbEntireHistory($limit, $sortname, $sortorder, $req = NULL) { global $db_query_info; $db_query_info = array(); if ($req == NULL) { $req = $_REQUEST; } $db_query_info['type'] = 'entire-history'; $user = getSoft($req, "user", ""); $problem = getSoft($req, "problemhash", ""); $resultdesc = array('y' => __t('Did not crash.'), 'Y' => __t('Correct!'), 'N' => __t('Incorrect.'), 'E' => __t('Internal error.'), 'S' => __t('Saved.'), 's' => __t('Saved.')); global $current_user; get_currentuserinfo(); global $wpdb; if (!is_user_logged_in()) { return __t("You must log in to view past submissions."); } if ($user == "all") { $u = "all"; } elseif ($user == "") { $u = $current_user; } elseif (userIsAdmin() || userIsAssistant()) { $u = get_userdata($user); if ($u === false) { return __t("User number not found."); } } else { $u = get_userdata($user); if ($u === false) { return __t("User number not found."); } if (strcasecmp(get_user_meta($user, 'pbguru', true), $current_user->user_login) != 0) { return sprintf(__t("User %s does not have you as their guru."), $user); } } if ($user != "") { $db_query_info['viewuser'] = $user; } // make an associative array indexed by slug $problemTable = $wpdb->get_results("SELECT slug, publicname, url FROM " . $wpdb->prefix . "pb_problems WHERE slug IS NOT NULL AND lang = '" . currLang2() . "'", OBJECT_K); $whereProblem = "1"; if ($problem != '') { if (!array_key_exists($problem, $problemTable)) { return sprintf(__t("Problem %s is unknown."), $problem); } $whereProblem = $wpdb->prepare("problem = %s", $problem); } $db_query_info['problem'] = $problem; $knownFields = array(__t("userid") => "userid", __t("time & ID") => "beginstamp", __t("problem") => "problem", __t("user code") => "usercode", __t("user input") => "userinput", __t("result") => "result"); if (array_key_exists($sortname, $knownFields)) { $sortString = $knownFields[$sortname] . " " . $sortorder . ", "; } else { $sortString = ""; } $whereStudent = NULL; if ($u == "all") { $whereStudent = userIsAdmin() ? "1" : "userid in " . getStudentList(); } else { $uid = $u->ID; $whereStudent = $wpdb->prepare("userid = %d", $uid); } $count = $wpdb->get_var("\nSELECT COUNT(1)\nFROM " . $wpdb->prefix . "pb_submissions \nWHERE {$whereStudent} AND {$whereProblem}"); if ($count == 0) { return __t("We do not have record of any submissions."); } $prep = "\nSELECT userid, ID, beginstamp, usercode, userinput, result, problem\nFROM " . $wpdb->prefix . "pb_submissions \nWHERE {$whereStudent} AND {$whereProblem}\nORDER BY {$sortString} ID DESC " . $limit; $flexirows = array(); foreach ($wpdb->get_results($prep, ARRAY_A) as $r) { $cell = array(); if ($u == "all") { $cell[__t('userid')] = str_replace(' ', "<br>", userString($r['userid'], true)); } $p = $r['problem']; if (array_key_exists($p, $problemTable)) { $cell[__t('problem')] = '<a class="open-same-window" href="' . $problemTable[$p]->url . '">' . $problemTable[$p]->publicname . '</a>'; } else { $cell[__t('problem')] = $p; } $cell[__t('user code')] = preBox($r['usercode'], -1, -1); $cell[__t('user input')] = $r['userinput'] == NULL ? '<i>' . __t('n/a') . '</i>' : preBox($r['userinput'], -1, 100000); if ($p != 'visualizer' && $p != 'visualizer-iframe') { $cell[__t('result')] = getSoft($resultdesc, $r['result'], '???'); } else { $cell[__t('result')] = '<i>n/a</i>'; } $cell[__t('time & ID')] = str_replace(' ', '<br/>', $r['beginstamp']) . '<br/>#' . $r['ID']; $flexirows[] = array('id' => $r['ID'], 'cell' => $cell); } return array('total' => $count, 'rows' => $flexirows); }
function export_submissions($content, $options) { $chunkSize = 500; $numChunks = 3250; // bigger is ok too i think global $wpdb; $problem_table = $wpdb->prefix . "pb_problems"; $problems = $wpdb->get_results("SELECT * FROM {$problem_table} WHERE " . "lang = 'en' ORDER BY lesson ASC, boxid ASC", ARRAY_A); $problemsByNumber = array(); foreach ($problems as $prow) { $problemsByNumber[$prow['slug']] = $prow; } file_put_contents("/home/cscircles/export.txt", ""); $outfile = fopen("/home/cscircles/export.txt", 'w'); if ($outfile === FALSE) { return "could not open file"; } echo strftime('%c'); $last_id = 9999999999; for ($i = 0; $i < $numChunks; $i++) { $results = $wpdb->get_results($wpdb->prepare("SELECT problem, usercode, userinput, hash, ID FROM " . $wpdb->prefix . "pb_submissions\n WHERE ID < %d \n ORDER by ID DESC\n LIMIT %d", $last_id, $chunkSize), ARRAY_A); foreach ($results as $row) { set_time_limit(30); // keeps going as long as needed $output = array(); $last_id = $row["ID"]; $output["id"] = $row["ID"]; $output["problem"] = $row["problem"]; $problemInfo = getSoft($problemsByNumber, $row["problem"], NULL); if ($problemInfo === NULL) { continue; } // certainly can't get error msg $output["problem_version_mismatch"] = $problemInfo["hash"] != $row["hash"] ? "True" : "False"; $output["just_testing"] = $row["userinput"] !== NULL ? "True" : "False"; $output["user_input"] = $row["userinput"] === NULL ? "" : $row["userinput"]; $output["user_code"] = $row["usercode"]; $post = array("hash" => $problemInfo["hash"], "pyId" => 0, "usercode0" => $row["usercode"], "userinput" => $row["userinput"], "inputInUse" => $row["userinput"] !== NULL); //echo submit_code_main($post, false); global $submit_code_stderr, $submit_code_errnice; if ($submit_code_stderr == NULL) { continue; } // not interested in it! $output["raw_errors"] = $submit_code_stderr === NULL ? "" : $submit_code_stderr; $output["nice_errors"] = $submit_code_errnice === NULL ? "" : $submit_code_errnice; foreach ($output as $k => $v) { $maxSize = 1000; // should be even $u = $v; if (strlen($u) > $maxSize) { $u = substr($u, 0, $maxSize / 2) . "...(" . (strlen($u) - $maxSize) . " characters skipped)..." . substr($u, strlen($u) - $maxSize / 2, $maxSize / 2); } fwrite($outfile, "{$k}: " . addcslashes($u, "\\\n\r") . "\n"); // if ($k == 'id' and rand(1, 10000)==1) { //echo strftime('%c'); //echo "<pre>"; //echo "$k: ".addcslashes($u, "\\\n\r")."\n"; //echo "</pre>"; //} } fwrite($outfile, "\n"); } } echo strftime('%c'); fclose($outfile); }
function dbMail($limit, $sortname, $sortorder, $req = NULL) { global $db_query_info; $db_query_info = array(); $who = getSoft($req === NULL ? $_REQUEST : $req, "who", ""); $xwho = getSoft($req === NULL ? $_REQUEST : $req, "xwho", ""); $what = getSoft($req === NULL ? $_REQUEST : $req, "what", ""); $xwhat = getSoft($req === NULL ? $_REQUEST : $req, "xwhat", ""); $unans = getSoft($req === NULL ? $_REQUEST : $req, "unans", ""); $db_query_info['type'] = 'mail-history'; $db_query_info['who'] = $who; $db_query_info['xwho'] = $xwho; $db_query_info['what'] = $what; $db_query_info['xwhat'] = $xwhat; $db_query_info['unans'] = $unans; if (!is_user_logged_in()) { return __t("You must log in to view past mail."); } $where = 'WHERE 1'; if (userIsAdmin()) { $where .= ' AND (uto = ' . getUserID() . ' OR uto = 0 OR ufrom = ' . getUserID() . ' OR ufrom = 0)'; } else { $students = getStudents(); $students[] = getUserID(); $where .= ' AND (ustudent IN (' . implode(',', $students) . ') OR uto = ' . getUserID() . ' OR ufrom = ' . getUserID() . ' )'; } if ($who != '') { if (!is_numeric($who)) { return sprintf(__t("%s must be numeric."), "'who'"); } $who = (int) $who; if (userIsAdmin() || getUserID() == $who || getUserID() == guruIDID($who) || userIsAssistant()) { $where .= ' AND ustudent = ' . $who; } else { return __t("Access denied."); } } else { if ($xwho != '') { if (!is_numeric($xwho)) { return sprintf(__t("%s must be numeric."), "'xwho'"); } $xwho = (int) $xwho; $where .= ' AND ustudent != ' . $xwho; } } if ($unans != '') { if (!is_numeric($unans)) { return sprintf(__t("%s must be numeric."), "'unans'"); } $unans = (int) $unans; $where .= ' AND unanswered = ' . $unans; } global $wpdb; if ($what != '') { $where .= $wpdb->prepare(' AND problem = %s', $what); } if ($xwhat != '') { $where .= $wpdb->prepare(' AND problem != %s', $xwhat); } $table_name = $wpdb->prefix . "pb_mail"; $knownFields = array(__t("from") => "ufrom", __t("to") => "uto", __t("when") => "time", __t("message") => "body", __t("problem") => "problem", __t("replied?") => "unanswered"); $sortString = array_key_exists($sortname, $knownFields) ? $knownFields[$sortname] . " " . $sortorder . ", " : ""; $count = $wpdb->get_var("SELECT COUNT(1) from {$table_name} {$where}"); $prep = "SELECT * from {$table_name} {$where} ORDER BY {$sortString} ID DESC" . $limit; // pyboxlog($prep); $flexirows = array(); foreach ($wpdb->get_results($prep, ARRAY_A) as $r) { $cell = array(); $cell[__t('from')] = nicefiedUsername($r['ufrom']); $cell[__t('to')] = nicefiedUsername($r['uto']); $url = cscurl('mail') . "?who=" . $r['ustudent'] . "&what=" . $r['problem'] . "&which=" . $r['ID'] . "#m"; $cell[__t('when')] = str_replace(' ', '<br>', $r['time']); if ($what == '') { $cell[__t('problem')] = $r['problem']; } if ($unans == '') { $cell[__t('replied?')] = $r['unanswered'] == 1 ? __t('no') : __t('yes'); } $cell[__t('message')] = "<a href='{$url}'>" . preBox($r['body']) . "</a>"; $flexirows[] = array('id' => $r['ID'], 'cell' => $cell); } return array('total' => $count, 'rows' => $flexirows); }
function run_submission($post) { /************************************************** part 0 : initialization and checking that a valid problem is selected ************************************************/ global $logRow, $beginstamp, $userid, $userinput, $meta, $wpdb, $inputInUse, $facultative, $usertni, $mainProfilingID, $slug, $log_it, $appendix; $beginstamp = time(); $logRow = FALSE; $meta = array(); if ($log_it) { $mainProfilingID = beginProfilingEntry(array("activity" => "submit-code")); } /*if ($_SERVER['REQUEST_METHOD'] != 'POST') return merror('', 'HTTP mangling: method "' . $_SERVER['REQUEST_METHOD'] . '" was requested instead of "POST"', 'suppress');*/ if (count($post) == 0) { return merror('', 'HTTP mangling: request contained no data', 'suppress'); } if (strlen(print_r($post, TRUE)) > POSTLIMIT) { pyboxlog("submit.php got too many bytes of data:" . strlen(print_r($post, TRUE))); return mfail(sprintf(__t('Submitted data (program and/or test input) ' . 'too large. Reduce size or <a href = "%s">' . 'run at home</a>.'), cscurl('install'))); } $id = getSoft($post, "pyId", "EMPTY"); $usercode = tabs_to_spaces(3, getSoft($post, "usercode" . $id, -1)); if (!is_string($usercode)) { return merror("", "No usercode" . $id . "!" . print_r($post, TRUE)); } $usercode = preg_replace('|\\xc2\\xa0|', ' ', $usercode); // nbsp $userinput = getSoft($post, "userinput", ""); $userinput = preg_replace('|\\xc2\\xa0|', ' ', $userinput); //nbsp $hash = $post["hash"]; //$graderArgsString = safeDereference("@file:" . $hash, 'hashes'); //if (!is_string($graderArgsString)) // return merror("", "PyBox error: problem hash " . $hash . " not found."); /************************************************** part 1 : set global variables, build skeleton log row; quit upon justsave. ************************************************/ //$problemArgs = multilineToAssociative($graderArgsString); // foreach ($problemArgs as $key=>$value) // $problemArgs[$key] = stripcslashes($value); $problemArgs = $wpdb->get_var($wpdb->prepare("\nSELECT graderArgs from " . $wpdb->prefix . "pb_problems WHERE hash = %s", $hash)); if ($problemArgs === NULL) { return merror("", sprintf(__t("Pybox error: problem hash %s not found. " . "Try reloading the page."), $hash)); } $problemArgs = json_decode($problemArgs, TRUE); // if ($problemArgs != $problemArgsNew) // pyboxlog("different: " . var_export($problemArgs, TRUE) // . var_export($problemArgsNew, TRUE)); //else // pyboxlog("same", TRUE); $re = '/^(' . implode("|", array_keys(optionsAndDefaults())) . ')([0-9]*)$/'; $problemOptions = optionsAndDefaults(); $subproblemOptions = array(); foreach ($problemArgs as $key => $value) { $match = preg_match($re, $key, $matches); if ($match == 0) { return merror("", "PyBox error: unknown option " . $key); } if ($matches[2] == "") { $problemOptions[$matches[1]] = $value; } else { if (!array_key_exists($matches[2], $subproblemOptions)) { $subproblemOptions[$matches[2]] = array(); } $subproblemOptions[$matches[2]][$matches[1]] = $value; } } foreach ($subproblemOptions as $index => $spo) { foreach ($problemOptions as $option => $value) { if (!array_key_exists($option, $spo)) { $subproblemOptions[$index][$option] = $value; } } } $inputInUse = isSoft($post, "inputInUse", "Y"); /* var_dump( $post, TRUE); echo "eq: " .(($post["inputInUse"] === "Y") ? "T":"F"); echo "inputinuse: " . ($inputInUse ? "T":"F");*/ if ($inputInUse && !isSoft($problemOptions, "allowinput", "Y")) { return merror("", "Pybox error: input not actually allowed"); } $facultative = isSoft($problemOptions, "facultative", "Y") || $inputInUse; $usertni = isSoft($problemOptions, "usertni", "Y"); $userid = is_user_logged_in() ? wp_get_current_user()->ID : -1; $meta['userid'] = $userid; $meta['problem'] = getSoft($problemArgs, 'slug', $hash); $slug = getSoft($problemArgs, 'slug', NULL); //most of submit logging preparation. quitting earlier => not logged in DB if ($log_it and !isSoft($problemOptions, "nolog", "Y")) { $postmisc = $post; unset($postmisc['usercode' . $id]); unset($postmisc['userinput']); unset($postmisc['hash']); $logRow = array('beginstamp' => date('Y-m-d H:i:s', $beginstamp), 'usercode' => $usercode, 'hash' => $hash, 'postmisc' => print_r($postmisc, TRUE), 'problem' => $slug, 'ipaddress' => $_SERVER['REMOTE_ADDR'], 'referer' => $_SERVER['HTTP_REFERER']); if ($inputInUse) { $logRow['userinput'] = $userinput; } $logRow['userid'] = $userid; //if ($logRow['problem']===NULL) //pyboxlog('nameless problem that is not read-only!', TRUE); } // old feature: // $justsave = array_key_exists('justsave', $post); //if ($justsave) // return msave(); /************************************************** part 2 : grading ************************************************/ if ($problemOptions['taboo'] != FALSE) { $taboo = explode(",", $problemOptions['taboo']); foreach ($taboo as $t) { $p = strpos($t, "|"); if ($p === FALSE) { $regex = $t; $display = $t; } else { $display = substr($t, 0, $p); $regex = substr($t, $p + 1); } $match = preg_match("#.*" . trim($regex) . ".*#", $usercode); if ($match != 0) { return mfail(sprintf(__t("You cannot use %s in this exercise."), "<code>" . trim($display) . "</code>")); } } } if ($problemOptions["maxeditdistance"] != FALSE) { $k = $problemOptions["maxeditdistance"]; $S = preg_replace('/\\s+/', '', $usercode); $T = preg_replace('/\\s+/', '', $problemOptions["originalcode"]); $s = strlen($S); $t = strlen($T); $msg = sprintf(__t("You are only allowed to change at most %s " . "characters compared to the original version " . "of the code."), $k); if (abs($s - $t) > 2 * $k + 5) { return mfail($msg) . " " . sprintf(__t("You changed %s or more."), 2 * $k + 5); } else { $DP = array_fill(0, $s + 1, NULL); for ($i = 0; $i <= $s; $i++) { $DP[$i] = array_fill(0, $t + 1, NULL); } for ($i = 0; $i <= $s; $i++) { for ($j = 0; $j <= $t; $j++) { if ($i == 0 || $j == 0) { $DP[$i][$j] = $i + $j; } else { $DP[$i][$j] = $DP[$i - 1][$j - 1]; if ($S[$i - 1] != $T[$j - 1]) { $DP[$i][$j]++; } $DP[$i][$j] = min($DP[$i][$j], 1 + min($DP[$i][$j - 1], $DP[$i - 1][$j])); } } } if ($DP[$s][$t] > 0 + $k) { return mfail($msg . " " . sprintf(__t("You changed %s."), $DP[$s][$t])); } } } /*************** done preprocessing source code, time to execute some things ************************/ if ($inputInUse && $slug != 'console') { global $usertni; $appendix = '<div class="testing-warning">'; if ($usertni) { $appendix .= __t('Note: ran with user tests.'); } else { $appendix .= __t('Note: ran with user inputs.'); } if (!isSoft($problemOptions, "facultative", "Y")) { $appendix .= ' ' . __t(' Click "Go back to grading" to switch back.'); } else { $appendix .= ' ' . __t(' Click "Hide input box" to switch back.'); } } else { $appendix = ''; } if (count($subproblemOptions) == 0) { // if ($problemOptions['grader'] == '*nograder*') $subproblemOptions["1"] = $problemOptions; //else //return merror("", "No test cases found!"); } // $spo: subproblemOptions for the current subproblem $tcTotal = 0; foreach ($subproblemOptions as $N => $spo) { $tcTotal += $spo["repeats"]; } $m = ''; //the result string, built a bit at a time. ksort($subproblemOptions); //test case 1, then 2, ... $tcCurrent = 0; $allCorrect = TRUE; ///*********************************************** main grading loop ***/ foreach ($subproblemOptions as $N => $spo) { // spo: subproblemOptions for current subproblem for ($i = 0; $i < $spo["repeats"]; $i++) { $tcCurrent++; if (!$inputInUse && $tcTotal > 1) { $m .= "<b>" . sprintf(__t('Results for test case %1$s out of %2$s'), $tcCurrent, $tcTotal) . "</b><br/>"; } try { $GLOBALS['pb_translation'] = getSoft($spo, 'translate', NULL); $tcOutcome = doGrading($usercode, $spo); $GLOBALS['pb_translation'] = NULL; $m .= $tcOutcome["message"]; if ($tcOutcome["result"] == "error") { return merror($m, $tcOutcome["errmsg"]); } if ($tcOutcome["result"] == "fail" && $spo["haltonwrong"] == "Y") { return mfail($m); } if ($tcOutcome["result"] == "fail") { $allCorrect = FALSE; } } catch (PyboxException $e) { return merror($m, $e->getMessage()); } if ($inputInUse) { break; } } if ($inputInUse) { break; } } return $allCorrect ? mpass($m) : mfail($m); }
require_once "include-to-load-wp.php"; function quote_it($s) { if (substr_count($s, '"') > substr_count($s, "'")) { return "'" . addcslashes($s, "'") . "'"; } else { return '"' . addcslashes($s, '"') . '"'; } } global $wpdb; $row = NULL; if (getSoft($_GET, "hash", "") != "") { $row = $wpdb->get_row($wpdb->prepare("SELECT type, shortcodeArgs, content, postid, url FROM " . $wpdb->prefix . "pb_problems WHERE hash = %s", $_GET["hash"]), ARRAY_A); } else { if (getSoft($_GET, "slug", "") != "") { $row = $wpdb->get_row($wpdb->prepare("SELECT type, shortcodeArgs, content, postid, url FROM " . $wpdb->prefix . "pb_problems WHERE slug = %s AND lang = %s", $_GET["slug"], getSoft($_GET, "lang", "en")), ARRAY_A); } } if ($row == NULL) { echo "Invalid problem"; return; } $args = json_decode($row['shortcodeArgs'], true); $r = ""; $r .= '['; if ($row['type'] == 'short answer') { $codename = 'pyShort'; } else { if ($row['type'] == 'multiple choice') { $codename = 'pyMulti'; } else {
function pyUser($options, $content) { if (!is_user_logged_in()) { return __t("You must login to view your user page."); } global $wpdb; $user = wp_get_current_user(); $uid = $user->ID; $students = getStudents(); $cstudents = count($students); $problem_table = $wpdb->prefix . "pb_problems"; $problems = $wpdb->get_results("SELECT * FROM {$problem_table} WHERE facultative = 0 AND lang = '" . currLang2() . "' AND lesson IS NOT NULL ORDER BY lesson ASC, boxid ASC", ARRAY_A); $problemsByNumber = array(); foreach ($problems as $prow) { $problemsByNumber[$prow['slug']] = $prow; } $gp = getSoft($_GET, "problem", ""); if ($gp != "" && $gp != "console" && !array_key_exists($gp, $problemsByNumber)) { echo sprintf(__t("Problem %s not found (at least in current language)"), $gp); return; } if (userIsAdmin() || userIsAssistant() || $cstudents > 0) { $preamble = "<div class='progress-selector'>\n <form method='get'><table style='border:none'><tr><td>" . sprintf(__t("View one of your students? (you have %s)"), $cstudents) . '</td><td>'; $options = array(); $options[''] = __t('Show only me'); $options['all'] = __t('Summary of all my students'); if (!userIsAdmin()) { foreach ($students as $student) { $info = get_userdata($student); $options[$info->ID] = userString($info->ID); } } if (userIsAdmin()) { $preamble .= 'blank: you; "all": all; id#: user (<a href="' . cscurl('allusers') . '">list</a>) <input style = "padding:0px;width:60px" type="text" name="user" value="' . getSoft($_REQUEST, 'user', '') . '">'; } else { $preamble .= optionsHelper($options, 'user'); } $preamble .= '</td></tr><tr><td>'; $preamble .= __t("Just show submissions for one problem?"); $options = array(); $options[''] = __t('Show all'); $options['console'] = __t('Console'); foreach ($problems as $problem) { if ($problem['type'] == 'code') { $options[$problem['slug']] = $problem['publicname']; } } $preamble .= '</td><td>'; $preamble .= optionsHelper($options, 'problem'); $preamble .= "</td></tr><tr><td colspan='2' style='text-align:center'><input style='width: 25%' type='submit' value='" . __t('Submit') . "'/></tr></td></table></form></div>"; echo $preamble; } $allStudents = isSoft($_GET, 'user', 'all'); $viewingAsStudent = '' == getSoft($_GET, 'user', ''); $allProblems = $gp == ""; if (!$viewingAsStudent) { if ($allProblems) { $problem_html = "all problems"; } else { if ($gp == 'console') { $problem_html = "Console"; } else { $problem_html = "<a href='" . $problemsByNumber[$gp]['url'] . "'>" . $problemsByNumber[$gp]['publicname'] . "</a>"; } } } if (!$allStudents && array_key_exists('user', $_GET) && $_GET['user'] != '') { if (!is_numeric($_GET['user'])) { return __t("User id must be numeric."); } $getuid = (int) $_GET['user']; if (userIsAdmin() || userIsAssistant()) { if (get_userdata($getuid) === FALSE) { return __t("Invalid user id."); } } else { if (!in_array($getuid, $students)) { return __t("Invalid user id."); } } $uid = $getuid; $user = get_userdata($uid); echo "<div class='history-prenote'>" . sprintf(__t("Now viewing %s for "), $problem_html) . userString($uid) . '</div>'; } if ($allStudents) { echo "<div class='history-prenote'>" . sprintf(__t("Now viewing %s for all of your students"), $problem_html) . "</div>"; } /***************** end of header ***************/ $flexigrids = ""; $completed_table = $wpdb->prefix . "pb_completed"; if ($allStudents && !$allProblems && $gp != "console") { $flexigrids .= niceFlex('perstudent', sprintf(__t("Solutions by my students for %s"), $problemsByNumber[$_GET['problem']]['publicname']), 'problem-summary', 'dbProblemSummary', array('p' => $_GET['problem'])); } $dbparams = array(); if (getSoft($_GET, 'user', '') != '') { $dbparams['user'] = $_GET['user']; } if (getSoft($_GET, 'problem', '') != '') { $dbparams['problemhash'] = $_GET['problem']; } $flexigrids .= niceFlex('submittedcode', $allProblems ? __t("Submitted code") : sprintf(__t("Submitted code for %s"), $_GET['problem'] == 'console' ? 'Console' : $problemsByNumber[$_GET['problem']]['publicname']), 'entire-history', 'dbEntireHistory', $dbparams); $recent = ""; if (!$allStudents) { // queries more than 6 in order to fill out progress table of all problems $completed = $wpdb->get_results("SELECT * FROM {$completed_table} WHERE userid = {$uid} ORDER BY time DESC", ARRAY_A); $recent .= '<div class="recent"><span class="latest-title">' . __t("Latest problems completed") . ":</span>"; // but for now we only use 6 entries for "most recently completed" section for ($i = 0; $i < count($completed) && $i < 6; $i++) { $p = getSoft($problemsByNumber, $completed[$i]['problem'], FALSE); if ($p !== FALSE) { if (getSoft($_GET, 'user', '') != '') { if ($problemsByNumber[$p['slug']]['type'] == 'code') { $url = '.?user='******'user'] . '&problem=' . $p['slug']; } else { $url = null; } } else { $url = $p['url']; } $recent .= ' <a class="open-same-window problem-completed" '; if ($url != null) { $recent .= ' href="' . $url . '" '; } $recent .= ' title="' . $completed[$i]['time'] . '">' . $p['publicname'] . '</a>'; } else { $recent .= '[' . $completed[$i]['problem'] . ']'; } } $recent .= '</div>'; } $submissions_table = $wpdb->prefix . "pb_submissions"; $studentTable = ''; if ($allStudents && !userIsAdmin()) { $studentList = getStudentList(); $where = "WHERE userid in {$studentList}"; if (!$allProblems) { $where .= $wpdb->prepare("and problem LIKE %s", $gp); } // show number of problems each student completed $scompleted = $wpdb->get_results("SELECT userid, count(1) as comps from {$completed_table} {$where} GROUP BY userid", OBJECT_K); // show number of submissions by each student for this problem $ssubmissions = $wpdb->get_results("SELECT userid, count(1) as subs from {$submissions_table} {$where} GROUP BY userid", OBJECT_K); $studentTable .= '<div class="history-note">Student listing (click name to drill down)</div>'; $studentTable .= '<table>'; foreach (getStudents() as $stu) { $studentTable .= '<tr>'; $studentTable .= '<td>'; $studentTable .= '<a class="open-same-window" href="?user='******'&problem=' . $gp . '">'; $studentTable .= userString($stu); $studentTable .= '</a></td>'; $studentTable .= '<td>'; if ($allProblems) { $studentTable .= (array_key_exists($stu, $scompleted) ? $scompleted[$stu]->comps : 0) . ' completed'; } else { $studentTable .= '<img src="' . UFILES . (array_key_exists($stu, $scompleted) ? 'checked' : 'icon') . '.png"/>'; } $studentTable .= '</td>'; $studentTable .= '<td>'; $studentTable .= (array_key_exists($stu, $ssubmissions) ? $ssubmissions[$stu]->subs : 0) . ' submissions'; $studentTable .= '</td>'; $studentTable .= '</tr>'; } $studentTable .= '</table>'; } $lessons_table = $wpdb->prefix . "pb_lessons"; $lessons = $wpdb->get_results("SELECT * FROM {$lessons_table} WHERE lang = '" . currLang2() . "'", ARRAY_A); $lessonsByNumber = array(); foreach ($lessons as $lrow) { $lessonsByNumber[$lrow['ordering']] = $lrow; } $overview = ''; if ($allProblems || !$allStudents) { $overview = '<h2 style="margin-top:5px;text-align:center">' . __t('List of all problems') . ' ' . ($allStudents ? __t('(with #completed)') : __t('(with #submissions)')) . '</h2>'; if (!$viewingAsStudent) { $overview .= "<div style='text-align:center'>Click on the <img style='height:1em,width:1em' src='" . UFILES . "/icon.png'> to drill down.</div>"; } $checkIt = array(); //array from slug to boolean, whether to check the icon $showNum = array(); //array from slug to number, number to display beside each if ($allStudents) { if (userIsAdmin() || userIsAssistant()) { $completed = $wpdb->get_results("SELECT count(userid), problem from {$completed_table} GROUP BY problem", ARRAY_A); } else { $studentList = getStudentList(); $completed = $wpdb->get_results("SELECT count(userid), problem from {$completed_table} WHERE userid in {$studentList} GROUP BY problem", ARRAY_A); } foreach ($completed as $crow) { $showNum[$crow['problem']] = $crow['count(userid)']; } } else { $submissions = $wpdb->get_results("SELECT count(1), problem from {$submissions_table} WHERE userid = {$uid} GROUP BY problem", ARRAY_A); foreach ($submissions as $srow) { $showNum[$srow['problem']] = $srow['count(1)']; } foreach ($completed as $crow) { // this was queried earlier $checkIt[$crow['problem']] = TRUE; } } $overview .= '<table style="width:auto;border:none;margin:0px auto;">'; $lesson = -1; $lrow = NULL; $llink = ""; $firstloop = true; foreach ($problems as $prow) { if ($prow['lesson'] != $lesson) { if (!$firstloop) { $overview .= "</td></tr>\n"; } $firstloop = false; $overview .= "<tr><td class='lessoninfo'>"; $lesson = $prow['lesson']; $lrow = $lessonsByNumber[$lesson]; $overview .= '<a class="open-same-window" href="'; $llink = get_page_link($lrow['id']); $overview .= $llink; $overview .= '">'; $overview .= $lrow['number'] . ": " . $lrow['title']; $overview .= '</a></td><td>'; } if (!$viewingAsStudent) { // drill-down link $url = '.?user='******'user'] . '&problem=' . $prow['slug']; } else { $url = $prow['url']; } $overview .= '<a class="open-same-window" '; if ($url != null) { $overview .= ' href="' . $url . '" '; } $overview .= '>'; $overview .= '<table class="history-tablette" ><tr class="history-tablette-top"><td>'; $overview .= '<img style="margin:-10px 0px" title="' . $prow['publicname'] . '" src="' . UFILES . (isSoft($checkIt, $prow['slug'], TRUE) ? 'checked' : 'icon') . '.png"/>'; $overview .= '</a></td></tr><tr class="history-tablette-bottom"><td>'; /* $overview .= '<a class="open-same-window" '; if ($url != null) $overview .= ' href="' . $url . '" '; $overview .= '>';*/ $overview .= array_key_exists($prow['slug'], $showNum) ? $showNum[$prow['slug']] : ' '; $overview .= '</td></tr></table></a>'; } $overview .= '</table>'; } return "<div class='userpage'>{$flexigrids} {$recent} {$studentTable} {$overview}</div>"; }
function cscircles_students_page() { echo "<div class='wrap'>\n<h2>Manage CS Circles Students</h2>"; if (isSoft($_REQUEST, 'submitted', 'true')) { $d = 0; $h = 0; $newhide = ""; $newnicks = array(); $newgroups = array(); foreach ($_REQUEST as $key => $val) { if (substr($key, 0, 1) == 's' && is_numeric(substr($key, 1))) { $id = substr($key, 1); if ($val == 'hide') { if ($newhide != '') { $newhide .= ","; } $newhide .= substr($key, 1); $h++; } else { if ($val == 'remove') { if (strtolower(get_user_meta(substr($key, 1), 'pbguru', true)) == strtolower(wp_get_current_user()->user_login)) { update_user_meta(substr($key, 1), 'pbguru', ''); } $d++; } } } if (substr($key, 0, 1) == 'n' && is_numeric(substr($key, 1))) { $id = substr($key, 1); $nick = $val; $nick = preg_replace('_[<>&\\"\\\\]_', "", trim($nick)); if ($nick != '') { $newnicks[$id] = $nick; } } if (substr($key, 0, 1) == 'g' && is_numeric(substr($key, 1))) { $id = substr($key, 1); $group = $val; $group = preg_replace('_[<>&\\"\\\\]_', "", trim($group)); if ($group != '') { $newgroups[$id] = $group; } } } update_user_meta(wp_get_current_user()->ID, 'pb_hidestudents', $newhide); update_user_meta(wp_get_current_user()->ID, 'pb_studentnicks', json_encode($newnicks)); update_user_meta(wp_get_current_user()->ID, 'pb_studentgroups', json_encode($newgroups)); echo "<div class='updated'>Deleted {$d} students. You have {$h} hidden students.</div>"; } echo "<script type='text/javascript'>classlist = function() {\n var classes={};\n jQuery('.grouplabel').each(function(i, elt) {classes[elt.value] = true;});\n var keys = [];\n for(var key in classes) {\n if (classes.hasOwnProperty(key)) {\n keys.push(key);\n }\n }\n keys.sort();\n jQuery('#classlist-select').html('');\n jQuery('#classlist-select').append(new Option('', ''));\n jQuery('#classlist-select').append(new Option('<show all students>', '<show all students>'));\n for (var i = 0; i < keys.length; i++) {\n if (keys[i] != '')\n jQuery('#classlist-select').append(new Option(keys[i], keys[i]));\n } \n}\nselectClass = function() {\n theclass = jQuery('#classlist-select')[0].value;\n jQuery('.student-row').each(function(i, row){\n if (jQuery(row).find('.grouplabel')[0].value == theclass || theclass == '<show all students>')\n jQuery(jQuery(row).find('.unhide')[0]).prop('checked',true);\n else\n jQuery(jQuery(row).find('.hide')[0]).prop('checked',true);\n });\n}\njQuery(classlist); // call once on load\n</script>"; echo "<p>Students who are hidden or removed won't show up\non the Progress page. You still have access to \nmessages between you and them in the Mail page histories.</p>\n\n<p>If you hide a student, you can unhide them later.</p>\n<p>If you remove a student, their guru is cleared. They would have to re-add you if you want them back.</p>\n<p>Students are listed in order of registration on CS Circles (earliest first).</p>\n<!--<p>Nicknames are optional. Otherwise, students appear by their e-mail and/or userid.</p>-->\n"; if (count(getStudents(true)) == 0) { echo "<div class='error'>You have no students. This page will disappear, and reappear if you get more students.</div>"; } else { echo "<form method='get' action='users.php'>\n <input type='hidden' name='page' value='cscircles-students'>\n <input type='hidden' name='submitted' value='true'>\n<table style='text-align:center'><tr><th>Unhidden</th><th>Hidden</th><th>Remove</th><th>Username</th><th>Name</th><th>E-mail</th><th>Optional nickname <br>(appears just to you, throughout site)</th><th>Optional class/section label</th></tr>"; $hidden = get_user_meta(wp_get_current_user()->ID, 'pb_hidestudents', true); $nicks = json_decode(get_user_meta(wp_get_current_user()->ID, 'pb_studentnicks', true), true); $groups = json_decode(get_user_meta(wp_get_current_user()->ID, 'pb_studentgroups', true), true); if (!is_array($nicks)) { $nicks = array(); } if (!is_array($groups)) { $groups = array(); } if ($hidden == '') { $hidden = ''; } $hidden = explode(",", $hidden); foreach (getStudents(true) as $index => $id) { $user = get_userdata($id); $hid = in_array($id, $hidden); $c1 = $hid ? "" : "checked='true'"; $c2 = $hid ? "checked='true'" : ""; $nick = getSoft($nicks, $id, ''); $group = getSoft($groups, $id, ''); echo "<tr class='student-row'>\n<td><input type='radio' class='unhide' name='s{$id}' {$c1} value='unhide'/></td>\n<td><input type='radio' class='hide' name='s{$id}' {$c2} value='hide'/></td>\n<td><input type='radio' name='s{$id}' value='remove'/></td>\n<td>{$user->user_login}</td>\n<td>{$user->user_firstname} {$user->user_lastname}</td>\n<td>{$user->user_email}</td>\n<td><input style='width:100%' type='text' name = 'n{$id}' value=\"{$nick}\"></td>\n<td><input style='width:100%' type='text' class = 'grouplabel' name = 'g{$id}' value=\"{$group}\" onkeyup=\"javascript:classlist()\" onchange=\"javascript:classlist()\"></td>\n</tr>"; } echo "<tr id='classlist-tr'>\n <td colspan='7' style='text-align:right'>\n <div id='classlist-label'>Show a class and hide all other students? (Select and press <b>Submit</b> to activate.)</div>\n </td>\n <td style='text-align:left'><select id='classlist-select' onchange='javascript:selectClass()'></select></td></tr>"; echo "</table>\n <button class='button-primary' id='submit'>Submit</button></form>"; echo "</div>"; } }
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 — 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) == '' ? ' ' : 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; }