Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- header('Content-Type: text/html; charset=UTF-8');
- header('Access-Control-Allow-Origin: *');
- /**
- * Project: Collator: the Question Writer results collator
- * File: qwhtml5.php
- *
- * Copyright 2008-2013 Question Writer Corporation
- *
- * This application is provided as an extension of the
- * Question Writer desktop software. Where you hold a valid, paid-for
- * license for the Question Writer desktop software, you are hereby
- * granted a license to use and modify this application for personal use
- * and use internal to your organization. All other rights are reserved.
- *
- * This application is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * @link http://www.questionwriter.com/
- * @copyright 2008-2013 Question Writer Corporation
- * @author Alexander McCabe
- * @package Collator
- * @version 5.0.2
- *
- * 5.0.2
- * Use Source ID in preference to Candidate entry where present
- *
- * 5.0.1
- * Added Browser info to email for debugging
- *
- * 5
- * Changed XML parsing to modern library
- * Added content type and origin headers to allow XML post requests from HTML file
- *
- * 1.4.1
- * Added support for the order attribute added to item_result in QW4.1
- *
- * 1.4
- * Added support for Plugin Question types
- * Added support for Multiple Questions per page
- *
- * 1.3
- * Changed Error Logging to remove uninteresting errors
- *
- * 1.2
- * Added additional identifiers to the email where they are not blank
- * Added change IP recorded when resultset comes from backup server
- * Added additional Candidate fields written into userdata db fields
- * Added fix to XML parsing to allow for special XML characters in ID, also remove spaces after special XML characters
- * Added facility to check if e-mail is not provided directly, but referenced by an id
- *
- * 1.1.1
- * Put all the Resultsets into a single SQL query to reduce processing time
- * Added ReplyTo header to help with spam rating
- * Added MIME header for e-mail to avoid MIME_HEADER_CTYPE_ONLY rating
- * Added newline in table for each line - email was being rejected for having lines that were too long
- * Externalized e-mail call
- * Added duplicate result checking in LogXML function
- * Set LogXML to false as a default
- * Check PassFail value for PASS/FAIL value - set to pass if value not recognized
- * Check for empty name/value pairs generated by old QW quizzes
- *
- * 1.1.0
- * Added all questiondata to a single SQL statement
- * Added codedpreferences.inc.php to allow code to check whether to store results in database and send email
- * Time field now entered properly in QuestionData table after 'PS' characters trimmed
- * Removed spaces at start and end of PHP files which may have caused problems returning 500 errors
- * Added Total Time Field to database and filled it by summing time taken for questions
- * Added error returns where MySQL statements fail
- * Added Email functionality
- * Changed all table names to lower-case
- * Added logging of result set XML to files capability
- * Remove printing trivial XML document 'ok' from response
- * Formatted Quiz and Question title to remove extraneous numbers and ids
- * Modified total time to display in Hours, Minutes, Seconds
- *
- * 1.0.0
- * Initial Release
- */
- //Include the files this script depends upon
- include "config.php";
- include "include/processqwhtml5xml.inc.php";
- include "include/functions.inc.php";
- include "include/codedpreferences.inc.php";
- //include "include/parse_xml.inc.php";
- //Get the IP address of the result set sender
- $ipvar=$_SERVER['REMOTE_ADDR'];
- //Trim the e-mail to ignore leading and trailing whitespace.
- $emailID=trim($_GET['e']);
- //Ensure that the e-mail is a real email address.
- //This also returns an error if there are any disallowed characters in the email address
- if(!isValidEmail($emailID))
- {
- //error_log($_GET['id']);
- //Check if the user has been reference by ID instead
- $userid=trim($_GET['id']);
- if($emailID=getEmailFromUserID($userid,$dbhost,$dbusername,$dbuserpass,$db_name)){
- //Fine
- }else{
- //Otherwise return an error to the client
- returnError("Invalid E-mail Address. EmailID:".trim($_GET['e'])." UserID:".trim($_GET['id']));
- }
- }
- //Set the timestamp
- $newTime=time();
- //Check if this is from the backup server in which case we use the timestamp of the backup server
- //We only accept the communicated timestamp if we confirm the IP is that of the backup server
- if(isset($_GET['newtime']) && ($ipvar==$backupServerIP || $ipvar==$backupServerIPAlt))
- {
- $newTime=(int)$_GET['newtime'];
- $ipvar=$_GET['originalip'];
- }
- $HTTP_RAW_POST_DATA="";
- $newdatafile="";
- //Setup an array to store the question data
- $respIDs=array();
- //Set up an array to store the Resultset data
- $contextData=array();
- //Set up an array to store custom scores
- $customScores=array();
- //Check there is a valid XML file in the POST request
- if($xml = getPostedXML())
- {
- $data=$xml;
- //error_log($data);
- $newdatafile=$data;
- $validDoc=processResultXML($data,$emailID);
- if (!$validDoc)
- {
- // If XML is not valid, return error
- //$reason = xml_error_string(xml_get_error_code($xmlparser));
- //$reason .= xml_get_current_line_number($xmlparser);
- returnError("Error parsing posted XML - Invalid Document");
- }
- }
- else
- {
- returnError("No XML Document");
- //If XML is not found, return error, but don't log
- //returnErrorNoLog();
- //returnError("Error - did not find suitable XML " . $xml);
- }
- $XMLFileLog="";
- $XMLProcessedFileLog="";
- if(logXML()){
- //Check directory exists for day in question
- $XMLLogDirectory=$archivelogdirectory."/".date("Ymd",$newTime);
- if(!is_dir($XMLLogDirectory)){
- mkdir($XMLLogDirectory);
- chmod($XMLLogDirectory, 0757);
- }
- $md5hash=md5($newdatafile);
- //Write XML to directory
- $XMLFileLog=$XMLLogDirectory."/".$ipvar."-".$md5hash."-".$emailID.".xml";
- $XMLProcessedFileLog=$XMLLogDirectory."/".$ipvar."-".$md5hash."-".$emailID.".processed.xml";
- //Check for duplicates - exit with a processed code if this file has already been received.
- if(file_exists($XMLProcessedFileLog)){
- header('Content-Type: text/xml; Charset: utf-8');
- print("<OK/>");
- exit();
- }
- if($handle1=fopen($XMLFileLog, "w")){
- if (fwrite($handle1, $newdatafile)){
- if(!fclose($handle1)){
- returnError("Error - could not close log file - "+$XMLFileLog);
- }
- }else
- {
- returnError("Error - could not write XML to log file"+$XMLFileLog);
- }
- }else{
- returnError("Error - could not open file for writing - "+$XMLFileLog);
- }
- }
- //Check pass/fail value is PASS or FAIL
- if($contextData["passfail"]!='PASS' && $contextData["passfail"]!='FAIL'){
- $contextData["passfail"]='PASS';
- }
- //Make responses human readable
- foreach ($respIDs as $key => $value){
- if ($key=="RandomChooser" || startsWith($key,"Candidate")){
- continue;
- }
- $responseText="";
- switch ($value["Type"]){
- case "MultipleChoice":
- case "MultipleResponse":
- case "PartialCredit":
- case "Sequencing":
- $responseKeys=preg_split("/,/",$value["Response"]);
- foreach($responseKeys as $rk){
- $responseText=$responseText.tokenTruncate($value["summarydata"][$rk],60).", ";
- }
- $responseText=trim($responseText," ");
- $responseText=trim($responseText,",");
- break;
- case "Matching":
- $responseKeys=preg_split("/,/",$value["Response"]);
- $bracketcount=0;
- foreach($responseKeys as $rk){
- if($bracketcount%2==0){
- $responseText.="(";
- }else{
- $responseText.=":";
- }
- $responseText=$responseText.tokenTruncate($value["summarydata"][$rk],60);
- if($bracketcount%2==1){
- $responseText.="), ";
- }
- $bracketcount++;
- }
- $responseText=trim($responseText," ");
- $responseText=trim($responseText,",");
- break;
- case "FillInTheBlank":
- case "Essay":
- case "Plugin":
- $responseText=$value["Response"];
- break;
- default: //This covers Plugin questions with the plugin type specified
- $responseText=$value["Response"];
- break;
- }
- $respIDs[$key]["ResponseSummary"]=$responseText;
- }
- /*
- //Sort according to order in column 6 so if XML order has changed somehow, results will still be returned in the correct order.
- //Works only for quizzes created with QW 44.1.4123.37396+
- if($Aanswers[0][6]!=null || $Aanswers[1][6]!=null || $Aanswers[2][6]!=null){
- //Looking for a recorded order attribute here - should be one in the first three entries at least.
- $ordering = array();
- foreach ($Aanswers as $key => $row) {
- $ordering[$key] = $row[6];
- }
- array_multisort($ordering, SORT_ASC, $Aanswers);
- }
- //Add User Configured Scores
- foreach ($UserDefinedScores as $k => $v) {
- if($UserDefinedScoresCount[$k]>1 && $k!="score"){
- $Aanswers[$answerseq][5]="User Defined Score: " . $k;
- $Aanswers[$answerseq][1]="User Defined Score: " . $k;
- $Aanswers[$answerseq][3]=$UserDefinedScores[$k];
- $answerseq++;
- }
- }
- */
- //Some tests are returning these as empty - they cannot be empty
- if($contextData["TotalTime"]==""){$contextData["TotalTime"]="0";}
- if($contextData["overallscore"]==""){$contextData["overallscore"]="0";}
- if($contextData["totalpossiblescore"]==""){$contextData["totalpossiblescore"]="0";}
- if($contextData["percentagescore"]==""){$contextData["percentagescore"]="0";}
- if($contextData["percentagepass"]==""){$contextData["percentagepass"]="0";}
- //Check if the user has requested not to store info in the database
- if(storeResultsInDatabase($emailID,$dbhost,$dbusername,$dbuserpass,$db_name)){
- //Open the database connection
- mysql_connect($dbhost,$dbusername,$dbuserpass) or returnError("Error - could not connect to database");
- //Choose the database
- @mysql_select_db($db_name) or returnError("Error - unable to select database");
- //Begin the transaction - we'll only write to the database if we successfully write all the questions to the database too
- mysql_query("BEGIN") or returnError("Error - unable to begin database transaction");
- //QuizName,TotalTime,
- //Insert Resultset
- $query="INSERT INTO resultsets (Email,Candidate,QuizName,TotalTime,OverAllScore,TotalPossibleScore,PercentageScore,PercentageScoreString,PercentagePass,PassFail,TimeStamp,SystemLanguage,OS,ScreenRes,Version,ClientTime,SourceURL,Data1,Data2,Data3,Data4,Data5,UserIP,html5) VALUES ";
- $query .= "(";
- $query .= "\"".mysql_real_escape_string($emailID)."\",";
- $query .= "\"".mysql_real_escape_string($contextData["Source ID"]==""?$respIDs["Candidate"]["Response"]:$contextData["Source ID"])."\",";
- $query .= "\"".mysql_real_escape_string($contextData["Quiz Title"])."\",";
- $query .= mysql_real_escape_string($contextData["TotalTime"]).",";
- $query .= mysql_real_escape_string($contextData["overallscore"]).",";
- $query .= mysql_real_escape_string($contextData["totalpossiblescore"]).",";
- $query .= mysql_real_escape_string($contextData["percentagescore"]).",";
- $query .= "\"".mysql_real_escape_string($contextData["percentagescorestring"])."\",";
- $query .= mysql_real_escape_string($contextData["percentagepass"]).",";
- $query .= "\"".mysql_real_escape_string($contextData["passfail"])."\",";
- $query .= "".mysql_real_escape_string($newTime).",";
- $query .= "\"".mysql_real_escape_string($contextData["System Language"])."\",";
- $query .= "\"".mysql_real_escape_string($contextData["OS"])."\",";
- $query .= "\"".mysql_real_escape_string($contextData["Screen Res"])."\",";
- $query .= "\"".mysql_real_escape_string($contextData["Version"])."\",";
- $query .= "\"".mysql_real_escape_string($contextData["Client Time"])."\",";
- $query .= "\"".mysql_real_escape_string($contextData["Source URL"])."\",";
- $query .= "\"".mysql_real_escape_string($respIDs["Candidate"]["Response"])."\",";
- $query .= "\"".mysql_real_escape_string($respIDs["CandidateData2"]["Response"])."\",";
- $query .= "\"".mysql_real_escape_string($respIDs["CandidateData3"]["Response"])."\",";
- $query .= "\"".mysql_real_escape_string($respIDs["CandidateData4"]["Response"])."\",";
- $query .= "\"".mysql_real_escape_string($respIDs["CandidateData5"]["Response"])."\",";
- $query .= "\"".mysql_real_escape_string($ipvar)."\",";
- $query .= "1";
- $query .= "); ";
- //error_log($query);
- mysql_query($query) or returnError("Error - 1. unable to write result set data ".$ipvar." ".mysql_error());
- //Get the updated ID of the resultset
- $resultid=mysql_insert_id();
- $query="";
- foreach ($customScores as $key => $value){
- $query .= "(";
- $query .= mysql_real_escape_string($resultid).",";
- $query .= "\"".mysql_real_escape_string($key)."\",";
- $query .= mysql_real_escape_string($value);
- $query .= "),";
- }
- $query=trim($query,",");
- if($query!=""){
- $query = "INSERT INTO qw5customscores (ResultSetID,Varname,Score) VALUES ".$query;
- mysql_query($query) or returnError("Error 2 - unable to write result set data ".mysql_error());
- }
- $query1="";
- $query2="";
- foreach ($respIDs as $key => $value){
- if ($key=="RandomChooser" || startsWith($key,"Candidate")){
- continue;
- }
- if(!isset($value["Score"])){
- continue;
- }
- if(!is_numeric($value["Score"])){
- $value["Score"]=-1;
- }
- $query1 .= "(";
- $query1 .= "\"".mysql_real_escape_string($emailID)."\",";
- $query1 .= "\"".mysql_real_escape_string($value["MD5hash"])."\",";
- $query1 .= "\"".mysql_real_escape_string($key)."\",";
- $query1 .= "\"".mysql_real_escape_string($value["xmlsummary"])."\"";
- $query1 .= "),";
- $query2 .= "(";
- $query2 .= "".mysql_real_escape_string($resultid).",";
- $query2 .= "\"".mysql_real_escape_string($value["MD5hash"])."\",";
- $query2 .= "\"".mysql_real_escape_string($key)."\",";
- $query2 .= "\"".mysql_real_escape_string($value["Response"])."\",";
- $query2 .= "\"".mysql_real_escape_string($value["LongResponse"])."\",";
- $query2 .= "".mysql_real_escape_string($value["Score"]).",";
- $query2 .= "".mysql_real_escape_string($value["QuestionTime"]).",";
- $query2 .= "\"".mysql_real_escape_string($value["ResponseSummary"])."\"";
- $query2 .= "),";
- }
- $query1=trim($query1,",");
- $query2=trim($query2,",");
- if($query1!=""){
- $query1 = "INSERT IGNORE INTO qw5questionsref (Email,MD5hash,QuestionReference,xmlsummary) VALUES ".$query1;
- mysql_query($query1) or returnError("Error 4 - unable to write result set data ".$query1." ".mysql_error());
- }
- if($query2!=""){
- $query2 = "INSERT INTO qw5questiondata (ResultSetID,MD5hash,QuestionReference,Response,LongResponse,Score,QuestionTime,ResponseSummary) VALUES ".$query2;
- mysql_query($query2) or returnError("Error 5 - unable to write result set data ".$query2." ".mysql_error());
- }
- //Commit the transaction, writing to the database and closing the connection
- mysql_query("COMMIT");
- //mysql_close();
- }
- //Check if the user has requested email
- if(sendResultsByEmail($emailID,$dbhost,$dbusername,$dbuserpass,$db_name)){
- //Main Email Body
- $mailclient="";
- $mailclient.="<h1>".htmlspecialchars(formatQuizTitle($contextData["Quiz Title"]))."</h1>". "\r\n";
- $mailclient.="<h2>Summary</h2>". "\r\n";
- $mailclient.="<table border=\"0\" cellspacing=\"0\" cellpadding=\"4\">". "\r\n";
- $mailclient.=" <tr><th align=\"right\">Name or User ID: </th><td>".htmlspecialchars($contextData["Source ID"]==""?$respIDs["Candidate"]["Response"]:$contextData["Source ID"])."</td></tr>". "\r\n";
- if(strlen($respIDs["CandidateData2"]["Response"])>0){
- $mailclient.=" <tr><th align=\"right\">Second Identifier: </th><td>".htmlspecialchars($respIDs["CandidateData2"]["Response"])."</td></tr>". "\r\n";
- }
- if(strlen($respIDs["CandidateData3"]["Response"])>0){
- $mailclient.=" <tr><th align=\"right\">Third Identifier: </th><td>".htmlspecialchars($respIDs["CandidateData3"]["Response"])."</td></tr>". "\r\n";
- }
- if(strlen($respIDs["CandidateData4"]["Response"])>0){
- $mailclient.=" <tr><th align=\"right\">Fourth Identifier: </th><td>".htmlspecialchars($respIDs["CandidateData4"]["Response"])."</td></tr>". "\r\n";
- }
- if(strlen($respIDs["CandidateData5"]["Response"])>0){
- $mailclient.=" <tr><th align=\"right\">Fifth Identifier: </th><td>".htmlspecialchars($respIDs["CandidateData5"]["Response"])."</td></tr>". "\r\n";
- }
- $mailclient.=" <tr><th align=\"right\">Overall Score: </th><td>".htmlspecialchars($contextData["overallscore"])."</td></tr>". "\r\n";
- $mailclient.=" <tr><th align=\"right\">Total Possible Score: </th><td>".htmlspecialchars($contextData["totalpossiblescore"])."</td></tr>". "\r\n";
- $mailclient.=" <tr><th align=\"right\">Percentage Score: </th><td>".htmlspecialchars($contextData["percentagescore"])."</td></tr>". "\r\n";
- $mailclient.=" <tr><th align=\"right\">Percentage Score String: </th><td>".htmlspecialchars($contextData["percentagescorestring"])."</td></tr>". "\r\n";
- $mailclient.=" <tr><th align=\"right\">Percentage Pass: </th><td>".htmlspecialchars($contextData["percentagepass"])."</td></tr>". "\r\n";
- $mailclient.=" <tr><th align=\"right\">Pass/Fail: </th><td>".htmlspecialchars($contextData["passfail"])."</td></tr>". "\r\n";
- $mailclient.=" <tr><th align=\"right\">Timestamp: </th><td>".htmlspecialchars(date("D, M j, G:i:s T Y",$newTime))."</td></tr>". "\r\n";
- $mailclient.=" <tr><th align=\"right\">Time Spent: </th><td>".htmlspecialchars(formatseconds(number_format($contextData["TotalTime"],2,'.','')))."</td></tr>". "\r\n";
- foreach ($customScores as $key => $value){
- $mailclient.=" <tr><th align=\"right\">Custom Score(".htmlspecialchars($key)."): </th><td>".htmlspecialchars($value)."</td></tr>". "\r\n";
- }
- $mailclient.="</table><h2>Questions</h2>". "\r\n";
- $mailclient.="<table border=\"0\" cellspacing=\"0\" cellpadding=\"4\">". "\r\n";
- $mailclient.="<tr><th>Question</th><th>Score</th><th>Duration</th><th></th><th>Answer</th></tr>". "\r\n";
- foreach ($respIDs as $key => $value){
- if ($key=="RandomChooser" || startsWith($key,"Candidate")){
- continue;
- }
- $mailclient.="<tr><td>".htmlspecialchars(formatQuestionTitle($key))."</td><td align=\"right\">".htmlspecialchars($value["Score"])."</td><td align=\"right\">".htmlspecialchars(number_format($value["QuestionTime"],2,'.',''))."s</td><td> </td><td>".nl2br(htmlspecialchars($value["LongResponse"].$value["ResponseSummary"]))."</td></tr>\r\n";
- }
- $mailclient.="</table>". "\r\n";
- $mailclient.="<br/>Browser Info: ".htmlspecialchars($contextData["OS"]." ".$contextData["Screen Res"]." ".$contextData["Version"])."\r\n";
- $mailclient.="<br/>Quiz responses sent ".htmlspecialchars(date("D, M j, G:i:s T Y",$newTime))." from IP ".htmlspecialchars($ipvar). "<br/><br/>".getMessage()."\r\n";
- $subject="Quiz Results ".htmlspecialchars($contextData["Source ID"]==""?$respIDs["Candidate"]["Response"]:$contextData["Source ID"])."- ".htmlspecialchars($contextData["overallscore"])." (".htmlspecialchars($contextData["percentagescore"])."%)";
- sendEmail($emailID, $subject, $mailclient, $from, $fromemail,$dbhost,$dbusername,$dbuserpass,$db_name);
- //error_log($mailclient);
- }
- //Rename the log file to indicate that it has been processed.
- //This is help prevent duplicate requests being reprocessed.
- if(logXML() && file_exists($XMLFileLog) && !file_exists($XMLProcessedFileLog)){
- rename($XMLFileLog,$XMLProcessedFileLog);
- }
- print("<OK/>");
- //End of script
- ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement