View Issue Details

This bug affects 1 person(s).
 4
IDProjectCategoryView StatusLast Update
05317Bug reportsOtherpublic2021-03-08 20:08
ReporterTMSWhite Assigned ToTMSWhite  
PrioritynormalSeverityminor 
Status closedResolutionfixed 
Product Version1.91+ 
Fixed in Version1.91+ 
Summary05317: templatereplace() doesn't properly handle some missing replacement values
Description

Such as {SURVEYDESCRIPTION} if $thissurvey['description'], or {WELCOME} if $thissurvey['welcome'] has not been set.

I have re-factored templatereplace() to assign all variables, place them in an alphabetized array, and do all of the replacements in a single loop (rather than having str_replace() functions scattered throughout templatereplace()

The patch is attached.

Additional Information

Note, although this is related to Issue 05268, is is a stand-alone-refactoring that is not dependent upon ExpressionManager at all. However, this refactoring will make it much easier to swap-in the ExpressionManager in the future.

There have been several bug fixes related to the replacement values in the last month. As long as they are spread throughout the code instead of consolidated, every attempt to integrate ExpressionManager would need to re-review all replacements in the code to make sure I haven't missed any.

If we can agree to consolidate the declaration of those replacement values and put any future fixes or new replacement values in this function, it will be much easier to cut over to ExpressionManager when the time is right.

TagsNo tags attached.
Attached Files
bug_5317_fix.patch (74,160 bytes)   
# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: C:\xampp\htdocs\limesurvey
# This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and \n newlines.
# Above lines and this line are ignored by the patching process.
Index: common_functions.php
--- common_functions.php Base (BASE)
+++ common_functions.php Locally Modified (Based On LOCAL)
@@ -14,6 +14,7 @@
  *	Files Purpose: lots of common functions
  */
 
+require_once('replacements.php');
 
 
 /**
@@ -2763,706 +2764,6 @@
 
 
 /**
- * This function replaces keywords in a text and is mainly intended for templates
- * If you use this functions put your replacement strings into the $replacements variable
- * instead of using global variables
- *
- * @param mixed $line Text to search in
- * @param mixed $replacements Array of replacements:  Array( <stringtosearch>=><stringtoreplacewith>
- * @return string  Text with replaced strings
- */
-function templatereplace($line, $replacements=array())
-{
-    global $surveylist, $sitename, $clienttoken, $rooturl;
-    global $thissurvey, $imageurl, $defaulttemplate;
-    global $percentcomplete, $move;
-    global $groupname, $groupdescription;
-    global $question;
-    global $showXquestions, $showgroupinfo, $showqnumcode;
-    global $questioncode, $answer, $navigator;
-    global $help, $totalquestions, $surveyformat;
-    global $completed, $register_errormsg;
-    global $notanswered, $privacy, $surveyid;
-    global $publicurl, $templatedir, $token;
-    global $assessments, $s_lang;
-    global $errormsg, $clang;
-    global $saved_id, $usertemplaterootdir;
-    global $totalBoilerplatequestions, $relativeurl;
-    global $languagechanger;
-    global $printoutput, $captchapath, $loadname;
-
-    // lets sanitize the survey template
-    if(isset($thissurvey['templatedir']))
-    {
-        $templatename=$thissurvey['templatedir'];
-    }
-    else
-    {
-        $templatename=$defaulttemplate;
-    }
-    $templatename=validate_templatedir($templatename);
-
-    // create absolute template URL and template dir vars
-    $templateurl=sGetTemplateURL($templatename).'/';
-    $templatedir=sgetTemplatePath($templatename);
-
-    if (stripos ($line,"</head>"))
-    {
-        $line=str_ireplace("</head>",
-            "<script type=\"text/javascript\" src=\"$rooturl/scripts/survey_runtime.js\"></script>\n"
-        .use_firebug()
-        ."\t</head>", $line);
-    }
-    // Get some vars : move elsewhere ?
-    // surveyformat
-    if (isset($thissurvey['format']))
-    {
-        $surveyformat = str_replace(array("A","S","G"),array("allinone","questionbyquestion","groupbygroup"),$thissurvey['format']);
-    }
-    else
-    {
-        $surveyformat = "";
-    }
-    // real survey contact
-    if (isset($surveylist['contact']))
-    {
-        $surveycontact = $surveylist['contact'];
-    }
-    elseif (isset($thissurvey['admin']) && $thissurvey['admin']!="")
-    {
-        $surveycontact=sprintf($clang->gT("Please contact %s ( %s ) for further assistance."),$thissurvey['admin'],$thissurvey['adminemail']);
-    }
-    else
-    {
-        $surveycontact="";
-    }
-
-    // If there are non-bracketed replacements to be made do so above this line.
-    // Only continue in this routine if there are bracketed items to replace {}
-    if (strpos($line, "{") === false) {
-        return $line;
-    }
-
-    foreach ($replacements as $replacementkey=>$replacementvalue)
-    {
-        if (strpos($line, '{'.$replacementkey.'}') !== false) $line=str_replace('{'.$replacementkey.'}', $replacementvalue, $line);
-    }
-
-    if (strpos($line, "{SURVEYLISTHEADING}") !== false) $line=str_replace("{SURVEYLISTHEADING}", $surveylist['listheading'], $line);
-    if (strpos($line, "{SURVEYLIST}") !== false) $line=str_replace("{SURVEYLIST}", $surveylist['list'], $line);
-    if (strpos($line, "{NOSURVEYID}") !== false) $line=str_replace("{NOSURVEYID}", $surveylist['nosid'], $line);
-    if (strpos($line, "{SURVEYCONTACT}") !== false) $line=str_replace("{SURVEYCONTACT}", $surveylist['contact'], $line);
-
-    if (strpos($line, "{SITENAME}") !== false) $line=str_replace("{SITENAME}", $sitename, $line);
-
-    if (strpos($line, "{SURVEYLIST}") !== false) $line=str_replace("{SURVEYLIST}", $surveylist, $line);
-    if (strpos($line, "{CHECKJAVASCRIPT}") !== false) $line=str_replace("{CHECKJAVASCRIPT}", "<noscript><span class='warningjs'>".$clang->gT("Caution: JavaScript execution is disabled in your browser. You may not be able to answer all questions in this survey. Please, verify your browser parameters.")."</span></noscript>", $line);
-
-    if (strpos($line, "{SURVEYLANGAGE}") !== false) $line=str_replace("{SURVEYLANGAGE}", $clang->langcode, $line);
-    if (strpos($line, "{SURVEYCONTACT}") !== false) $line=str_replace("{SURVEYCONTACT}", $surveycontact, $line);
-    if (strpos($line, "{SURVEYNAME}") !== false) $line=str_replace("{SURVEYNAME}", $thissurvey['name'], $line);
-    if (strpos($line, "{SURVEYDESCRIPTION}") !== false) $line=str_replace("{SURVEYDESCRIPTION}", $thissurvey['description'], $line);
-    if (strpos($line, "{SURVEYFORMAT}") !== false) $line=str_replace("{SURVEYFORMAT}", $surveyformat, $line);
-        if (strpos($line, "{WELCOME}") !== false) $line=str_replace("{WELCOME}", $thissurvey['welcome'], $line);
-    if (strpos($line, "{LANGUAGECHANGER}") !== false) $line=str_replace("{LANGUAGECHANGER}", $languagechanger, $line);
-    if (strpos($line, "{PERCENTCOMPLETE}") !== false) $line=str_replace("{PERCENTCOMPLETE}", $percentcomplete, $line);
-
-    if(
-        $showgroupinfo == 'both' ||
-	    $showgroupinfo == 'name' ||
-	    ($showgroupinfo == 'choose' && !isset($thissurvey['showgroupinfo'])) ||
-	    ($showgroupinfo == 'choose' && $thissurvey['showgroupinfo'] == 'B') ||
-	    ($showgroupinfo == 'choose' && $thissurvey['showgroupinfo'] == 'N')
-    )
-    {
-        if (strpos($line, "{GROUPNAME}") !== false) $line=str_replace("{GROUPNAME}", $groupname, $line);
-    }
-    else
-    {
-        if (strpos($line, "{GROUPNAME}") !== false) $line=str_replace("{GROUPNAME}", '' , $line);
-    };
-    if(
-        $showgroupinfo == 'both' ||
-	    $showgroupinfo == 'description' ||
-	    ($showgroupinfo == 'choose' && !isset($thissurvey['showgroupinfo'])) ||
-	    ($showgroupinfo == 'choose' && $thissurvey['showgroupinfo'] == 'B') ||
-	    ($showgroupinfo == 'choose' && $thissurvey['showgroupinfo'] == 'D')
-    )
-    {
-        if (strpos($line, "{GROUPDESCRIPTION}") !== false) $line=str_replace("{GROUPDESCRIPTION}", $groupdescription, $line);
-    }
-    else
-    {
-        if (strpos($line, "{GROUPDESCRIPTION}") !== false) $line=str_replace("{GROUPDESCRIPTION}", '' , $line);
-    };
-
-    if (is_array($question))
-    {
-        if (strpos($line, "{QUESTION}") !== false)
-        {
-            $line=str_replace("{QUESTION}", $question['all'], $line);
-        }
-        else
-        {
-            if (strpos($line, "{QUESTION_TEXT}") !== false) $line=str_replace("{QUESTION_TEXT}", $question['text'], $line);
-            if (strpos($line, "{QUESTION_HELP}") !== false) $line=str_replace("{QUESTION_HELP}", $question['help'], $line);
-            if (strpos($line, "{QUESTION_MANDATORY}") !== false) $line=str_replace("{QUESTION_MANDATORY}", $question['mandatory'], $line);
-            if (strpos($line, "{QUESTION_MAN_MESSAGE}") !== false) $line=str_replace("{QUESTION_MAN_MESSAGE}", $question['man_message'], $line);
-            if (strpos($line, "{QUESTION_VALID_MESSAGE}") !== false) $line=str_replace("{QUESTION_VALID_MESSAGE}", $question['valid_message'], $line);
-            if (strpos($line, "{QUESTION_FILE_VALID_MESSAGE}") !== false) $line=str_replace("{QUESTION_FILE_VALID_MESSAGE}", $question['file_valid_message'], $line);
-        }
-        if (strpos($line, "{SGQ}") !== false) $line=str_replace("{SGQ}", $question['sgq'], $line);
-    }
-    else
-    {
-        if (strpos($line, "{QUESTION}") !== false) $line=str_replace("{QUESTION}", $question, $line);
-    };
-    if (strpos($line, '{QUESTION_ESSENTIALS}') !== false) $line=str_replace('{QUESTION_ESSENTIALS}', $question['essentials'], $line);
-    if (strpos($line, '{QUESTION_CLASS}') !== false) $line=str_replace('{QUESTION_CLASS}', $question['class'], $line);
-    if (strpos($line, '{QUESTION_MAN_CLASS}') !== false) $line=str_replace('{QUESTION_MAN_CLASS}', $question['man_class'], $line);
-    if (strpos($line, "{QUESTION_INPUT_ERROR_CLASS}") !== false) $line=str_replace("{QUESTION_INPUT_ERROR_CLASS}", $question['input_error_class'], $line);
-
-    if(
-        $showqnumcode == 'both' ||
-	    $showqnumcode == 'number' ||
-	    ($showqnumcode == 'choose' && !isset($thissurvey['showqnumcode'])) ||
-	    ($showqnumcode == 'choose' && $thissurvey['showqnumcode'] == 'B') ||
-	    ($showqnumcode == 'choose' && $thissurvey['showqnumcode'] == 'N')
-    )
-    {
-        if (strpos($line, "{QUESTION_NUMBER}") !== false) $line=str_replace("{QUESTION_NUMBER}", $question['number'], $line);
-    }
-    else
-    {
-        if (strpos($line, "{QUESTION_NUMBER}") !== false) $line=str_replace("{QUESTION_NUMBER}", '' , $line);
-    };
-    if(
-        $showqnumcode == 'both' ||
-	    $showqnumcode == 'code' ||
-	    ($showqnumcode == 'choose' && !isset($thissurvey['showqnumcode'])) ||
-	    ($showqnumcode == 'choose' && $thissurvey['showqnumcode'] == 'B') ||
-	    ($showqnumcode == 'choose' && $thissurvey['showqnumcode'] == 'C')
-    )
-    {
-    if (strpos($line, "{QUESTION_CODE}") !== false) $line=str_replace("{QUESTION_CODE}", $question['code'], $line);
-    }
-    else
-    {
-        if (strpos($line, "{QUESTION_CODE}") !== false) $line=preg_replace("/{QUESTION_CODE}:?/", '', $line);
-
-    };
-
-    if (strpos($line, "{ANSWER}") !== false) $line=str_replace("{ANSWER}", $answer, $line);
-    $totalquestionsAsked = $totalquestions - $totalBoilerplatequestions;
-    if(
-      $showXquestions == 'show' ||
-      ($showXquestions == 'choose' && !isset($thissurvey['showXquestions'])) ||
-      ($showXquestions == 'choose' && $thissurvey['showXquestions'] == 'Y')
-    )
-    {
-        if ($totalquestionsAsked < 1)
-        {
-            if (strpos($line, "{THEREAREXQUESTIONS}") !== false) $line=str_replace("{THEREAREXQUESTIONS}", $clang->gT("There are no questions in this survey"), $line); //Singular
-        }
-        elseif ($totalquestionsAsked == 1)
-        {
-            if (strpos($line, "{THEREAREXQUESTIONS}") !== false) $line=str_replace("{THEREAREXQUESTIONS}", $clang->gT("There is 1 question in this survey"), $line); //Singular
-        }
-        else
-        {
-             if (strpos($line, "{THEREAREXQUESTIONS}") !== false) $line=str_replace("{THEREAREXQUESTIONS}", $clang->gT("There are {NUMBEROFQUESTIONS} questions in this survey."), $line); //Note this line MUST be before {NUMBEROFQUESTIONS}
-	};
-    }
-    else
-    {
-    	if (strpos($line, '{THEREAREXQUESTIONS}') !== false) $line=str_replace('{THEREAREXQUESTIONS}' , '' , $line);
-    };
-    if (strpos($line, "{NUMBEROFQUESTIONS}") !== false) $line=str_replace("{NUMBEROFQUESTIONS}", $totalquestionsAsked, $line);
-
-    if (strpos($line, "{TOKEN}") !== false) {
-        if (isset($token)) {
-            $line=str_replace("{TOKEN}", $token, $line);
-        }
-        elseif (isset($clienttoken)) {
-            $line=str_replace("{TOKEN}", htmlentities($clienttoken,ENT_QUOTES,'UTF-8'), $line);
-        }
-        else {
-            $line=str_replace("{TOKEN}",'', $line);
-        }
-    }
-
-    if (strpos($line, "{SID}") !== false) $line=str_replace("{SID}", $surveyid, $line);
-
-    if (strpos($line, "{EXPIRY}") !== false)
-    {
-       	$dateformatdetails=getDateFormatData($thissurvey['surveyls_dateformat']);
-    	$datetimeobj = new Date_Time_Converter($thissurvey['expiry'] , "Y-m-d");
-    	$dateoutput=$datetimeobj->convert($dateformatdetails['phpdate']);
-       	$line=str_replace("{EXPIRY}", $dateoutput, $line);
-    }
-    if (strpos($line, "{NAVIGATOR}") !== false) $line=str_replace("{NAVIGATOR}", $navigator, $line);
-    if (strpos($line, "{SUBMITBUTTON}") !== false) {
-        $submitbutton="<input class='submit' type='submit' value=' ".$clang->gT("Submit")." ' name='move2' onclick=\"javascript:document.limesurvey.move.value = 'movesubmit';\" />";
-        $line=str_replace("{SUBMITBUTTON}", $submitbutton, $line);
-    }
-    if (strpos($line, "{COMPLETED}") !== false) $line=str_replace("{COMPLETED}", $completed, $line);
-    if (strpos($line, "{URL}") !== false) {
-        if ($thissurvey['surveyls_url']!=""){
-            if (trim($thissurvey['surveyls_urldescription'])!=''){
-                $linkreplace="<a href='{$thissurvey['surveyls_url']}'>{$thissurvey['surveyls_urldescription']}</a>";
-            }
-            else {
-                $linkreplace="<a href='{$thissurvey['surveyls_url']}'>{$thissurvey['surveyls_url']}</a>";
-            }
-        }
-        else $linkreplace='';
-        $line=str_replace("{URL}", $linkreplace, $line);
-        $line=str_replace("{SAVEDID}",$saved_id, $line);     // to activate the SAVEDID in the END URL
-        if (isset($clienttoken)) {$token=$clienttoken;} else {$token='';}
-        $line=str_replace("{TOKEN}",urlencode($token), $line);          // to activate the TOKEN in the END URL
-        $line=str_replace("{SID}", $surveyid, $line);       // to activate the SID in the RND URL
-    }
-
-    if (strpos($line, "{LANG}") !== false)
-    {
-        $line=str_replace("{LANG}", $clang->getlangcode(), $line);
-    }
-    if (strpos($line, "{PRIVACY}") !== false)
-    {
-        $line=str_replace("{PRIVACY}", $privacy, $line);
-    }
-    if (strpos($line, "{PRIVACYMESSAGE}") !== false)
-    {
-        $line=str_replace("{PRIVACYMESSAGE}", "<span style='font-weight:bold; font-style: italic;'>".$clang->gT("A Note On Privacy")."</span><br />".$clang->gT("This survey is anonymous.")."<br />".$clang->gT("The record kept of your survey responses does not contain any identifying information about you unless a specific question in the survey has asked for this. If you have responded to a survey that used an identifying token to allow you to access the survey, you can rest assured that the identifying token is not kept with your responses. It is managed in a separate database, and will only be updated to indicate that you have (or haven't) completed this survey. There is no way of matching identification tokens with survey responses in this survey."), $line);
-    }
-    if (strpos($line, "{CLEARALL}") !== false)  {
-
-        $clearall = "<input type='button' name='clearallbtn' value='".$clang->gT("Exit and Clear Survey")."' class='clearall' "
-        ."onclick=\"if (confirm('".$clang->gT("Are you sure you want to clear all your responses?",'js')."')) {window.open('{$publicurl}/index.php?sid=$surveyid&amp;move=clearall&amp;lang=".$_SESSION['s_lang'];
-        if (returnglobal('token'))
-        {
-            $clearall .= "&amp;token=".urlencode(trim(sanitize_xss_string(strip_tags(returnglobal('token')))));
-        }
-        $clearall .= "', '_top')}\" />";
-
-        $line=str_replace("{CLEARALL}", $clearall, $line);
-
-    }
-    // --> START NEW FEATURE - SAVE
-    if (strpos($line, "{DATESTAMP}") !== false) {
-        if (isset($_SESSION['datestamp'])) {
-            $line=str_replace("{DATESTAMP}", $_SESSION['datestamp'], $line);
-        }
-        else {
-            $line=str_replace("{DATESTAMP}", "-", $line);
-        }
-    }
-    // <-- END NEW FEATURE - SAVE
-    if (strpos($line, "{SAVE}") !== false)  {
-        //Set up save/load feature
-        if ($thissurvey['allowsave'] == "Y")
-        {
-            // Find out if the user has any saved data
-
-            if ($thissurvey['format']=='A')
-            {
-                if($thissurvey['tokenanswerspersistence'] != 'Y')
-                {
-                    $saveall = "\t\t\t<input type='submit' name='loadall' value='".$clang->gT("Load Unfinished Survey")."' class='saveall' ". (($thissurvey['active'] != "Y")? "disabled='disabled'":"") ."/>"
-                    ."\n\t\t\t<input type='button' name='saveallbtn' value='".$clang->gT("Resume Later")."' class='saveall' onclick=\"javascript:document.limesurvey.move.value = this.value;addHiddenField(document.getElementById('limesurvey'),'saveall',this.value);document.getElementById('limesurvey').submit();\" ". (($thissurvey['active'] != "Y")? "disabled='disabled'":"") ."/>";  // Show Save So Far button
-                }
-                else
-                {
-                    $saveall= "\t\t\t<input type='button' name='saveallbtn' value='".$clang->gT("Resume Later")."' class='saveall' onclick=\"javascript:document.limesurvey.move.value = this.value;addHiddenField(document.getElementById('limesurvey'),'saveall',this.value);document.getElementById('limesurvey').submit();\" ". (($thissurvey['active'] != "Y")? "disabled='disabled'":"") ."/>";  // Show Save So Far button
-        	};
-            }
-            elseif (!isset($_SESSION['step']) || !$_SESSION['step'])  //First page, show LOAD
-            {
-                if($thissurvey['tokenanswerspersistence'] != 'Y')
-                {
-                    $saveall = "\t\t\t<input type='submit' name='loadall' value='".$clang->gT("Load Unfinished Survey")."' class='saveall' ". (($thissurvey['active'] != "Y")? "disabled='disabled'":"") ."/>";
-                }
-		else
-		{
-                    $saveall = '';
-		};
-            }
-            elseif (isset($_SESSION['scid']) && (isset($move) && $move == "movelast"))  //Already saved and on Submit Page, dont show Save So Far button
-            {
-                $saveall='';
-            }
-            else
-            {
-                $saveall= "<input type='button' name='saveallbtn' value='".$clang->gT("Resume Later")."' class='saveall' onclick=\"javascript:document.limesurvey.move.value = this.value;addHiddenField(document.getElementById('limesurvey'),'saveall',this.value);document.getElementById('limesurvey').submit();\" ". (($thissurvey['active'] != "Y")? "disabled='disabled'":"") ."/>";  // Show Save So Far button
-            }
-        }
-        else
-        {
-            $saveall="";
-        }
-        $line=str_replace("{SAVE}", $saveall, $line);
-
-    }
-    if (strpos($line, "{TEMPLATEURL}") !== false) {
-        $line=str_replace("{TEMPLATEURL}", $templateurl, $line);
-    }
-
-    if (strpos($line, "{TEMPLATECSS}") !== false) {
-        $templatecss="<link rel='stylesheet' type='text/css' href='{$templateurl}template.css' />\n";
-        if (getLanguageRTL($clang->langcode))
-        {
-            $templatecss.="<link rel='stylesheet' type='text/css' href='{$templateurl}template-rtl.css' />\n";
-        }
-        $line=str_replace("{TEMPLATECSS}", $templatecss, $line);
-    }
-
-    if (FlattenText($help,true)!='') {
-        if (strpos($line, "{QUESTIONHELP}") !== false)
-        {
-            If (!isset($helpicon))
-            {
-                if (file_exists($templatedir.'/help.gif'))
-                {
-
-                    $helpicon=$templateurl.'help.gif';
-                }
-                elseif (file_exists($templatedir.'/help.png'))
-                {
-
-                    $helpicon=$templateurl.'help.png';
-                }
-                else
-                {
-                    $helpicon=$imageurl."/help.gif";
-                }
-            }
-            $line=str_replace("{QUESTIONHELP}", "<img src='$helpicon' alt='Help' align='left' />".$help, $line);
-
-        }
-        if (strpos($line, "{QUESTIONHELPPLAINTEXT}") !== false) $line=str_replace("{QUESTIONHELPPLAINTEXT}", strip_tags(addslashes($help)), $line);
-    }
-    else
-    {
-        if (strpos($line, "{QUESTIONHELP}") !== false) $line=str_replace("{QUESTIONHELP}", $help, $line);
-        if (strpos($line, "{QUESTIONHELPPLAINTEXT}") !== false) $line=str_replace("{QUESTIONHELPPLAINTEXT}", strip_tags(addslashes($help)), $line);
-    }
-
-    $line=insertansReplace($line);
-
-    if (strpos($line, "{SUBMITCOMPLETE}") !== false) $line=str_replace("{SUBMITCOMPLETE}", "<strong>".$clang->gT("Thank you!")."<br /><br />".$clang->gT("You have completed answering the questions in this survey.")."</strong><br /><br />".$clang->gT("Click on 'Submit' now to complete the process and save your answers."), $line);
-    if (strpos($line, "{SUBMITREVIEW}") !== false) {
-        if (isset($thissurvey['allowprev']) && $thissurvey['allowprev'] == "N") {
-            $strreview = "";
-        }
-        else {
-            $strreview=$clang->gT("If you want to check any of the answers you have made, and/or change them, you can do that now by clicking on the [<< prev] button and browsing through your responses.");
-        }
-        $line=str_replace("{SUBMITREVIEW}", $strreview, $line);
-    }
-
-    $line=tokenReplace($line);
-
-    if (strpos($line, "{ANSWERSCLEARED}") !== false) $line=str_replace("{ANSWERSCLEARED}", $clang->gT("Answers Cleared"), $line);
-    if (strpos($line, "{RESTART}") !== false)
-    {
-        if ($thissurvey['active'] == "N")
-        {
-            $replacetext= "<a href='{$publicurl}/index.php?sid=$surveyid&amp;newtest=Y";
-            if (isset($s_lang) && $s_lang!='') $replacetext.="&amp;lang=".$s_lang;
-            $replacetext.="'>".$clang->gT("Restart this Survey")."</a>";
-            $line=str_replace("{RESTART}", $replacetext, $line);
-        } else {
-            $restart_extra = "";
-            $restart_token = returnglobal('token');
-            if (!empty($restart_token)) $restart_extra .= "&amp;token=".urlencode($restart_token);
-            else $restart_extra = "&amp;newtest=Y";
-            if (!empty($_GET['lang'])) $restart_extra .= "&amp;lang=".returnglobal('lang');
-            $line=str_replace("{RESTART}",  "<a href='{$publicurl}/index.php?sid=$surveyid".$restart_extra."'>".$clang->gT("Restart this Survey")."</a>", $line);
-        }
-    }
-    if (strpos($line, "{CLOSEWINDOW}") !== false) $line=str_replace("{CLOSEWINDOW}", "<a href='javascript:%20self.close()'>".$clang->gT("Close this window")."</a>", $line);
-    if (strpos($line, "{SAVEERROR}") !== false) $line=str_replace("{SAVEERROR}", $errormsg, $line);
-    if (strpos($line, "{SAVEHEADING}") !== false) $line=str_replace("{SAVEHEADING}", $clang->gT("Save Your Unfinished Survey"), $line);
-    if (strpos($line, "{SAVEMESSAGE}") !== false) $line=str_replace("{SAVEMESSAGE}", $clang->gT("Enter a name and password for this survey and click save below.")."<br />\n".$clang->gT("Your survey will be saved using that name and password, and can be completed later by logging in with the same name and password.")."<br /><br />\n".$clang->gT("If you give an email address, an email containing the details will be sent to you.")."<br /><br />\n".$clang->gT("After having clicked the save button you can either close this browser window or continue filling out the survey."), $line);
-    if (strpos($line, "{SAVEALERT}") !== false)
-    {
-        if (isset($thissurvey['anonymized']) && $thissurvey['anonymized'] =='Y')
-        {
-            $savealert=$clang->gT("To remain anonymous please use a pseudonym as your username, also an email address is not required.");
-        }
-        else
-        {
-            $savealert="";
-        }
-        $line=str_replace("{SAVEALERT}", $savealert, $line);
-    }
-
-    if (strpos($line, "{RETURNTOSURVEY}") !== false)
-    {
-        $savereturn = "<a href='$relativeurl/index.php?sid=$surveyid";
-        if (returnglobal('token'))
-        {
-            $savereturn.= "&amp;token=".urlencode(trim(sanitize_xss_string(strip_tags(returnglobal('token')))));
-        }
-        $savereturn .= "'>".$clang->gT("Return To Survey")."</a>";
-        $line=str_replace("{RETURNTOSURVEY}", $savereturn, $line);
-    }
-    if (strpos($line, "{SAVEFORM}") !== false) {
-        //SAVE SURVEY DETAILS
-        $saveform = "<table><tr><td align='right'>".$clang->gT("Name").":</td><td><input type='text' name='savename' value='";
-        if (isset($_POST['savename'])) {$saveform .= html_escape(auto_unescape($_POST['savename']));}
-        $saveform .= "' /></td></tr>\n"
-        . "<tr><td align='right'>".$clang->gT("Password").":</td><td><input type='password' name='savepass' value='";
-        if (isset($_POST['savepass'])) {$saveform .= html_escape(auto_unescape($_POST['savepass']));}
-        $saveform .= "' /></td></tr>\n"
-        . "<tr><td align='right'>".$clang->gT("Repeat Password").":</td><td><input type='password' name='savepass2' value='";
-        if (isset($_POST['savepass2'])) {$saveform .= html_escape(auto_unescape($_POST['savepass2']));}
-        $saveform .= "' /></td></tr>\n"
-        . "<tr><td align='right'>".$clang->gT("Your Email").":</td><td><input type='text' name='saveemail' value='";
-        if (isset($_POST['saveemail'])) {$saveform .= html_escape(auto_unescape($_POST['saveemail']));}
-        $saveform .= "' /></td></tr>\n";
-        if (function_exists("ImageCreate") && captcha_enabled('saveandloadscreen',$thissurvey['usecaptcha']))
-        {
-            $saveform .="<tr><td align='right'>".$clang->gT("Security Question").":</td><td><table><tr><td valign='middle'><img src='{$captchapath}verification.php?sid=$surveyid' alt='' /></td><td valign='middle' style='text-align:left'><input type='text' size='5' maxlength='3' name='loadsecurity' value='' /></td></tr></table></td></tr>\n";
-        }
-        $saveform .= "<tr><td align='right'></td><td></td></tr>\n"
-        . "<tr><td></td><td><input type='submit'  id='savebutton' name='savesubmit' value='".$clang->gT("Save Now")."' /></td></tr>\n"
-        . "</table>";
-        $line=str_replace("{SAVEFORM}", $saveform, $line);
-    }
-    if (strpos($line, "{LOADERROR}") !== false) $line=str_replace("{LOADERROR}", $errormsg, $line);
-    if (strpos($line, "{LOADHEADING}") !== false) $line=str_replace("{LOADHEADING}", $clang->gT("Load A Previously Saved Survey"), $line);
-    if (strpos($line, "{LOADMESSAGE}") !== false) $line=str_replace("{LOADMESSAGE}", $clang->gT("You can load a survey that you have previously saved from this screen.")."<br />".$clang->gT("Type in the 'name' you used to save the survey, and the password.")."<br />", $line);
-    if (strpos($line, "{LOADFORM}") !== false) {
-        //LOAD SURVEY DETAILS
-        $loadform = "<table><tr><td align='right'>".$clang->gT("Saved name").":</td><td><input type='text' name='loadname' value='";
-        if ($loadname) {$loadform .= html_escape(auto_unescape($loadname));}
-        $loadform .= "' /></td></tr>\n"
-        . "<tr><td align='right'>".$clang->gT("Password").":</td><td><input type='password' name='loadpass' value='";
-        if (isset($loadpass)) { $loadform .= html_escape(auto_unescape($loadpass)); }
-        $loadform .= "' /></td></tr>\n";
-        if (function_exists("ImageCreate") && captcha_enabled('saveandloadscreen',$thissurvey['usecaptcha']))
-        {
-            $loadform .="<tr><td align='right'>".$clang->gT("Security Question").":</td><td><table><tr><td valign='middle'><img src='{$captchapath}verification.php?sid=$surveyid' alt='' /></td><td valign='middle'><input type='text' size='5' maxlength='3' name='loadsecurity' value='' alt=''/></td></tr></table></td></tr>\n";
-        }
-
-
-        $loadform .="<tr><td align='right'></td><td></td></tr>\n"
-        . "<tr><td></td><td><input type='submit' id='loadbutton' value='".$clang->gT("Load Now")."' /></td></tr></table>\n";
-        $line=str_replace("{LOADFORM}", $loadform, $line);
-    }
-    //REGISTER SURVEY DETAILS
-    if (strpos($line, "{REGISTERERROR}") !== false) $line=str_replace("{REGISTERERROR}", $register_errormsg, $line);
-    if (strpos($line, "{REGISTERMESSAGE1}") !== false) $line=str_replace("{REGISTERMESSAGE1}", $clang->gT("You must be registered to complete this survey"), $line);
-    if (strpos($line, "{REGISTERMESSAGE2}") !== false) $line=str_replace("{REGISTERMESSAGE2}", $clang->gT("You may register for this survey if you wish to take part.")."<br />\n".$clang->gT("Enter your details below, and an email containing the link to participate in this survey will be sent immediately."), $line);
-    if (strpos($line, "{REGISTERFORM}") !== false)
-    {
-        $registerform="<form method='post' action='{$publicurl}/register.php'>\n";
-        if (!isset($_REQUEST['lang']))
-        {
-            $reglang = GetBaseLanguageFromSurveyID($surveyid);
-        }
-        else
-        {
-            $reglang = returnglobal('lang');
-        }
-        $registerform .= "<input type='hidden' name='lang' value='".$reglang."' />\n";
-        $registerform .= "<input type='hidden' name='sid' value='$surveyid' id='sid' />\n";
-
-        $registerform.="<table class='register' summary='Registrationform'>\n"
-        ."<tr><td align='right'>"
-        .$clang->gT("First name").":</td>"
-        ."<td align='left'><input class='text' type='text' name='register_firstname'";
-        if (isset($_POST['register_firstname']))
-        {
-            $registerform .= " value='".htmlentities(returnglobal('register_firstname'),ENT_QUOTES,'UTF-8')."'";
-        }
-        $registerform .= " /></td></tr>"
-        ."<tr><td align='right'>".$clang->gT("Last name").":</td>\n"
-        ."<td align='left'><input class='text' type='text' name='register_lastname'";
-        if (isset($_POST['register_lastname']))
-        {
-            $registerform .= " value='".htmlentities(returnglobal('register_lastname'),ENT_QUOTES,'UTF-8')."'";
-        }
-        $registerform .= " /></td></tr>\n"
-        ."<tr><td align='right'>".$clang->gT("Email address").":</td>\n"
-        ."<td align='left'><input class='text' type='text' name='register_email'";
-        if (isset($_POST['register_email']))
-        {
-            $registerform .= " value='".htmlentities(returnglobal('register_email'),ENT_QUOTES,'UTF-8')."'";
-        }
-        $registerform .= " /></td></tr>\n";
-
-
-        if (function_exists("ImageCreate") && captcha_enabled('registrationscreen',$thissurvey['usecaptcha']))
-        {
-            $registerform .="<tr><td align='right'>".$clang->gT("Security Question").":</td><td><table><tr><td valign='middle'><img src='{$captchapath}verification.php?sid=$surveyid' alt='' /></td><td valign='middle'><input type='text' size='5' maxlength='3' name='loadsecurity' value='' /></td></tr></table></td></tr>\n";
-        }
-
-
-        /*      if(isset($thissurvey['attribute1']) && $thissurvey['attribute1'])
-         {
-         $registerform .= "<tr><td align='right'>".$thissurvey['attribute1'].":</td>\n"
-         ."<td align='left'><input class='text' type='text' name='register_attribute1'";
-         if (isset($_POST['register_attribute1']))
-         {
-         $registerform .= " value='".htmlentities(returnglobal('register_attribute1'),ENT_QUOTES,'UTF-8')."'";
-         }
-         $registerform .= " /></td></tr>\n";
-         }
-         if(isset($thissurvey['attribute2']) && $thissurvey['attribute2'])
-         {
-         $registerform .= "<tr><td align='right'>".$thissurvey['attribute2'].":</td>\n"
-         ."<td align='left'><input class='text' type='text' name='register_attribute2'";
-         if (isset($_POST['register_attribute2']))
-         {
-         $registerform .= " value='".htmlentities(returnglobal('register_attribute2'),ENT_QUOTES,'UTF-8')."'";
-         }
-         $registerform .= " /></td></tr>\n";
-         }        */
-        $registerform .= "<tr><td></td><td><input id='registercontinue' class='submit' type='submit' value='".$clang->gT("Continue")."' />"
-        ."</td></tr>\n"
-        ."</table>\n"
-        ."</form>\n";
-        $line=str_replace("{REGISTERFORM}", $registerform, $line);
-    }
-    if (strpos($line, "{ASSESSMENT_CURRENT_TOTAL}") !== false && function_exists('doAssessment'))
-    {
-        $assessmentdata=doAssessment($surveyid,true);
-        $line=str_replace("{ASSESSMENT_CURRENT_TOTAL}", $assessmentdata['total'], $line);
-    }
-    if (strpos($line, "{ASSESSMENTS}") !== false) $line=str_replace("{ASSESSMENTS}", $assessments, $line);
-    if (strpos($line, "{ASSESSMENT_HEADING}") !== false) $line=str_replace("{ASSESSMENT_HEADING}", $clang->gT("Your Assessment"), $line);
-    return $line;
-}
-
-/**
- * insertAnsReplace() takes a string and looks for any {INSERTANS:xxxx} variables
- *  which it then, one by one, substitutes the SGQA code with the relevant answer
- *  from the session array containing responses
- *
- *  The operations of this function were previously in the templatereplace function
- *  but have been moved to a function of their own to make it available
- *  to other areas of the script.
- *
- * @param mixed $line   string - the string to iterate, and then return
- *
- * @return string This string is returned containing the substituted responses
- *
- */
-function insertansReplace($line)
-{
-    if (!isset($_SESSION['dateformats']['phpdate'])) $_SESSION['dateformats']['phpdate']='';
-    while (strpos($line, "{INSERTANS:") !== false)
-    {
-        $answreplace=substr($line, strpos($line, "{INSERTANS:"), strpos($line, "}", strpos($line, "{INSERTANS:"))-strpos($line, "{INSERTANS:")+1);
-        $answreplace2=substr($answreplace, 11, strpos($answreplace, "}", strpos($answreplace, "{INSERTANS:"))-11);
-        $answreplace3=strip_tags(retrieve_Answer($answreplace2, $_SESSION['dateformats']['phpdate']));
-        $line=str_replace($answreplace, $answreplace3, $line);
-    }
-    return $line;
-}
-
-/**
- * tokenReplace() takes a string and looks for any {TOKEN:xxxx} variables
- *  which it then, one by one, substitutes the TOKEN code with the relevant token
- *  from the session array containing token information
- *
- *  The operations of this function were previously in the templatereplace function
- *  but have been moved to a function of their own to make it available
- *  to other areas of the script.
- *
- * @param mixed $line   string - the string to iterate, and then return
- *
- * @return string This string is returned containing the substituted responses
- *
- */
-function tokenReplace($line)
-{
-    global $surveyid;
-
-    if (isset($_SESSION['token']) && $_SESSION['token'] != '')
-    {
-        //Gather survey data for tokenised surveys, for use in presenting questions
-        $_SESSION['thistoken']=getTokenData($surveyid, $_SESSION['token']);
-    }
-
-    if (isset($_SESSION['thistoken']))
-    {
-        if (strpos($line, "{TOKEN:FIRSTNAME}") !== false) $line=str_replace("{TOKEN:FIRSTNAME}", $_SESSION['thistoken']['firstname'], $line);
-        if (strpos($line, "{TOKEN:LASTNAME}") !== false) $line=str_replace("{TOKEN:LASTNAME}", $_SESSION['thistoken']['lastname'], $line);
-        if (strpos($line, "{TOKEN:EMAIL}") !== false) $line=str_replace("{TOKEN:EMAIL}", $_SESSION['thistoken']['email'], $line);
-    }
-    else
-    {
-        if (strpos($line, "{TOKEN:FIRSTNAME}") !== false) $line=str_replace("{TOKEN:FIRSTNAME}", "", $line);
-        if (strpos($line, "{TOKEN:LASTNAME}") !== false) $line=str_replace("{TOKEN:LASTNAME}", "", $line);
-        if (strpos($line, "{TOKEN:EMAIL}") !== false) $line=str_replace("{TOKEN:EMAIL}", "", $line);
-    }
-
-    while (strpos($line, "{TOKEN:ATTRIBUTE_")!== false)
-    {
-        $templine=substr($line,strpos($line, "{TOKEN:ATTRIBUTE_"));
-        $templine=substr($templine,0,strpos($templine, "}")+1);
-        $attr_no=(int)substr($templine,17,strpos($templine, "}")-17);
-        $replacestr='';
-        if (isset($_SESSION['thistoken']['attribute_'.$attr_no])) $replacestr=$_SESSION['thistoken']['attribute_'.$attr_no];
-        $line=str_replace($templine, $replacestr, $line);
-    }
-    return $line;
-}
-
-/**
- * passthruReplace() takes a string and looks for {PASSTHRULABEL}, {PASSTHRUVALUE} and {PASSTHRU:myarg} variables
- *  which it then substitutes for passthru data sent in the initial URL and stored
- *  in the session array containing responses
- *
- * @param mixed $line   string - the string to iterate, and then return
- * @param mixed $thissurvey     string - the string containing the surveyinformation
- * @return string This string is returned containing the substituted responses
- *
- */
-function PassthruReplace($line, $thissurvey)
-{
-    $line=str_replace("{PASSTHRULABEL}", $thissurvey['passthrulabel'], $line);
-    $line=str_replace("{PASSTHRUVALUE}", $thissurvey['passthruvalue'], $line);
-
-    //  Replacement for variable passthru argument like {PASSTHRU:myarg}
-    while (strpos($line,"{PASSTHRU:") !== false)
-    {
-        $p1 = strpos($line,"{PASSTHRU:"); // startposition
-        $p2 = $p1 + 10; // position of the first arg char
-        $p3 = strpos($line,"}",10); // position of the last arg char
-
-        $cmd=substr($line,$p1,$p3-$p1+1); // extract the complete passthru like "{PASSTHRU:myarg}"
-        $arg=substr($line,$p2,$p3-$p2); // extract the arg to passthru (like "myarg")
-
-        // lookup for the fitting arg
-        $qstring = $_SESSION['ls_initialquerystr']; // get initial query_string
-
-        parse_str($qstring, $keyvalue); // split into key and value
-        $match = 0; // prevent an endless loop if there is no arg in url
-        foreach ($keyvalue as $key=>$value) // lookup loop
-        {
-            if ($key == $arg) // if match
-            {
-                $line=str_replace($cmd, $arg . "=" . $value, $line); // replace
-                $match = 1;
-                break;
-            }
-
-        }
-
-        if ($match == 0)
-        {
-            $line=str_replace($cmd, $arg . "=", $line); // clears "{PASSTHRU:myarg} to "myarg=" if there was no myarg in calling url
-        }
-    }
-
-    return $line;
-}
-
-/**
  * This function returns a count of the number of saved responses to a survey
  *
  * @param mixed $surveyid Survey ID
Index: replacements.php
--- replacements.php Locally New
+++ replacements.php Locally New
@@ -0,0 +1,748 @@
+<?php
+
+/**
+ * This function replaces keywords in a text and is mainly intended for templates
+ * If you use this functions put your replacement strings into the $replacements variable
+ * instead of using global variables
+ * NOTE - Don't do any embedded replacements in this function.  Create the array of replacement values and
+ * they will be done in batch at the end
+ *
+ * @param mixed $line Text to search in
+ * @param mixed $replacements Array of replacements:  Array( <stringtosearch>=><stringtoreplacewith>
+ * @return string  Text with replaced strings
+ */
+function templatereplace($line, $replacements=array())
+{
+    global $surveylist, $sitename, $clienttoken, $rooturl;
+    global $thissurvey, $imageurl, $defaulttemplate;
+    global $percentcomplete, $move;
+    global $groupname, $groupdescription;
+    global $question;
+    global $showXquestions, $showgroupinfo, $showqnumcode;
+    global $answer, $navigator;
+    global $help, $totalquestions, $surveyformat;
+    global $completed, $register_errormsg;
+    global $privacy, $surveyid;
+    global $publicurl, $templatedir, $token;
+    global $assessments, $s_lang;
+    global $errormsg, $clang;
+    global $saved_id;
+    global $totalBoilerplatequestions, $relativeurl;
+    global $languagechanger;
+    global $captchapath, $loadname;
+
+    // lets sanitize the survey template
+    if (isset($thissurvey['templatedir']))
+    {
+        $_templatename = $thissurvey['templatedir'];
+    }
+    else
+    {
+        $_templatename = $defaulttemplate;
+    }
+    $_templatename = validate_templatedir($_templatename);
+
+    // create absolute template URL and template dir vars
+    $_templateurl = sGetTemplateURL($_templatename) . '/';
+    $templatedir = sgetTemplatePath($_templatename);
+
+    if (stripos($line, "</head>"))
+    {
+        $line = str_ireplace("</head>",
+            "<script type=\"text/javascript\" src=\"$rooturl/scripts/survey_runtime.js\"></script>\n"
+                        . use_firebug()
+                        . "\t</head>", $line);
+    }
+    // Get some vars : move elsewhere ?
+    // surveyformat
+    if (isset($thissurvey['format']))
+    {
+        $surveyformat = str_replace(array("A", "S", "G"), array("allinone", "questionbyquestion", "groupbygroup"), $thissurvey['format']);
+    }
+    else
+    {
+        $surveyformat = "";
+    }
+    // real survey contact
+    if (isset($surveylist['contact']))
+    {
+        $_surveycontact = $surveylist['contact'];
+    }
+    elseif (isset($thissurvey['admin']) && $thissurvey['admin'] != "")
+    {
+        $_surveycontact = sprintf($clang->gT("Please contact %s ( %s ) for further assistance."), $thissurvey['admin'], $thissurvey['adminemail']);
+    }
+    else
+    {
+        $_surveycontact = "";
+    }
+
+    // If there are non-bracketed replacements to be made do so above this line.
+    // Only continue in this routine if there are bracketed items to replace {}
+    if (strpos($line, "{") === false)
+    {
+        return $line;
+    }
+
+    if (
+        $showgroupinfo == 'both' ||
+	    $showgroupinfo == 'name' ||
+	    ($showgroupinfo == 'choose' && !isset($thissurvey['showgroupinfo'])) ||
+	    ($showgroupinfo == 'choose' && $thissurvey['showgroupinfo'] == 'B') ||
+	    ($showgroupinfo == 'choose' && $thissurvey['showgroupinfo'] == 'N')
+    )
+    {
+        $_groupname = $groupname;
+    }
+    else
+    {
+        $_groupname = '';
+    };
+    if (
+        $showgroupinfo == 'both' ||
+	    $showgroupinfo == 'description' ||
+	    ($showgroupinfo == 'choose' && !isset($thissurvey['showgroupinfo'])) ||
+	    ($showgroupinfo == 'choose' && $thissurvey['showgroupinfo'] == 'B') ||
+	    ($showgroupinfo == 'choose' && $thissurvey['showgroupinfo'] == 'D')
+    )
+    {
+        $_groupdescription = $groupdescription;
+    }
+    else
+    {
+        $_groupdescription = '';
+    };
+
+    if (is_array($question))
+    {
+        $_question = $question['all'];
+        $_question_text = $question['text'];
+        $_question_help = $question['help'];
+        $_question_mandatory = $question['mandatory'];
+        $_question_man_message = $question['man_message'];
+        $_question_valid_message = $question['valid_message'];
+        $_question_file_valid_message = $question['file_valid_message'];
+        $_question_sgq = (isset($question['sgq']) ? $question['sgq'] : '');
+        $_question_essentials = $question['essentials'];
+        $_question_class = $question['class'];
+        $_question_man_class = $question['man_class'];
+        $_question_input_error_class = $question['input_error_class'];
+        }
+        else
+        {
+        $_question = $question;
+        $_question_text = '';
+        $_question_help = '';
+        $_question_mandatory = '';
+        $_question_man_message = '';
+        $_question_valid_message = '';
+        $_question_file_valid_message = '';
+        $_question_sgq = '';
+        $_question_essentials = '';
+        $_question_class = '';
+        $_question_man_class = '';
+        $_question_input_error_class = '';
+    };
+
+    if (
+        $showqnumcode == 'both' ||
+	    $showqnumcode == 'number' ||
+	    ($showqnumcode == 'choose' && !isset($thissurvey['showqnumcode'])) ||
+	    ($showqnumcode == 'choose' && $thissurvey['showqnumcode'] == 'B') ||
+	    ($showqnumcode == 'choose' && $thissurvey['showqnumcode'] == 'N')
+    )
+    {
+        $_question_number = $question['number'];
+    }
+    else
+    {
+        $_question_number = '';
+    };
+    if (
+        $showqnumcode == 'both' ||
+	    $showqnumcode == 'code' ||
+	    ($showqnumcode == 'choose' && !isset($thissurvey['showqnumcode'])) ||
+	    ($showqnumcode == 'choose' && $thissurvey['showqnumcode'] == 'B') ||
+	    ($showqnumcode == 'choose' && $thissurvey['showqnumcode'] == 'C')
+    )
+    {
+        $_question_code = $question['code'];
+    }
+    else
+    {
+        $_question_code = '';
+    }
+
+    $_totalquestionsAsked = $totalquestions - $totalBoilerplatequestions;
+    if (
+      $showXquestions == 'show' ||
+      ($showXquestions == 'choose' && !isset($thissurvey['showXquestions'])) ||
+      ($showXquestions == 'choose' && $thissurvey['showXquestions'] == 'Y')
+    )
+    {
+        if ($_totalquestionsAsked < 1)
+        {
+            $_therearexquestions = $clang->gT("There are no questions in this survey"); // Singular
+        }
+        elseif ($_totalquestionsAsked == 1)
+        {
+            $_therearexquestions = $clang->gT("There is 1 question in this survey"); //Singular
+        }
+        else
+        {
+            $_therearexquestions = $clang->gT("There are {NUMBEROFQUESTIONS} questions in this survey.");    //Note this line MUST be before {NUMBEROFQUESTIONS}
+	};
+    }
+    else
+    {
+        $_therearexquestions = '';
+    };
+
+    // Hack - just replace {THEREAREXQUESTIONS}.  ExpressionManager replaces too much otherwise; but sure can specify which subsets to replace if several passes needed
+    if (strpos($line,'{THEREAREXQUESTIONS}')) {
+        $line = str_replace('{THEREAREXQUESTIONS}', $_therearexquestions, $line);
+        }
+
+    if (isset($token))
+    {
+        $_token = $token;
+        }
+    elseif (isset($clienttoken))
+    {
+        $_token = htmlentities($clienttoken, ENT_QUOTES, 'UTF-8');
+        }
+    else
+    {
+        $_token = '';
+    }
+
+    if (isset($thissurvey['surveyls_dateformat']))
+    {
+        $dateformatdetails = getDateFormatData($thissurvey['surveyls_dateformat']);
+    }
+    else {
+        $dateformatdetails = getDateFormatData();
+    }
+    if (isset($thissurvey['expiry']))
+    {
+        $_datetimeobj = new Date_Time_Converter($thissurvey['expiry'], "Y-m-d");
+        $_dateoutput = $_datetimeobj->convert($dateformatdetails['phpdate']);
+            }
+    else
+    {
+        $_dateoutput = '-';
+            }
+    $_submitbutton = "<input class='submit' type='submit' value=' " . $clang->gT("Submit") . " ' name='move2' onclick=\"javascript:document.limesurvey.move.value = 'movesubmit';\" />";
+    if (isset($thissurvey['surveyls_url']) and $thissurvey['surveyls_url'] != "")
+    {
+        if (trim($thissurvey['surveyls_urldescription']) != '')
+        {
+            $_linkreplace = "<a href='{$thissurvey['surveyls_url']}'>{$thissurvey['surveyls_urldescription']}</a>";
+        }
+        else
+        {
+            $_linkreplace = "<a href='{$thissurvey['surveyls_url']}'>{$thissurvey['surveyls_url']}</a>";
+    }
+    }
+    else
+    {
+        $_linkreplace='';
+    }
+
+    if (isset($clienttoken))
+    {
+        $token = $clienttoken;
+    }
+    else
+    {
+        $token = '';
+    }
+
+    if (!isset($_SESSION['s_lang']))
+    {
+        $_s_lang = 'en';
+    }
+    else
+    {
+        $_s_lang = $_SESSION['s_lang'];
+    }
+
+    $_clearall = "<input type='button' name='clearallbtn' value='" . $clang->gT("Exit and Clear Survey") . "' class='clearall' "
+            . "onclick=\"if (confirm('" . $clang->gT("Are you sure you want to clear all your responses?", 'js') . "')) {window.open('{$publicurl}/index.php?sid=$surveyid&amp;move=clearall&amp;lang=" . $_s_lang;
+        if (returnglobal('token'))
+        {
+        $_clearall .= "&amp;token=" . urlencode(trim(sanitize_xss_string(strip_tags(returnglobal('token')))));
+        }
+        $_clearall .= "', '_top')}\" />";
+
+    if (isset($_SESSION['datestamp']))
+    {
+        $_datestamp = $_SESSION['datestamp'];
+    }
+    else
+    {
+        $_datestamp = '-';
+        }
+        //Set up save/load feature
+    if (isset($thissurvey['allowsave']) and $thissurvey['allowsave'] == "Y")
+        {
+            // Find out if the user has any saved data
+
+        if ($thissurvey['format'] == 'A')
+            {
+            if ($thissurvey['tokenanswerspersistence'] != 'Y')
+                {
+                $_saveall = "\t\t\t<input type='submit' name='loadall' value='" . $clang->gT("Load Unfinished Survey") . "' class='saveall' " . (($thissurvey['active'] != "Y") ? "disabled='disabled'" : "") . "/>"
+                        . "\n\t\t\t<input type='button' name='saveallbtn' value='" . $clang->gT("Resume Later") . "' class='saveall' onclick=\"javascript:document.limesurvey.move.value = this.value;addHiddenField(document.getElementById('limesurvey'),'saveall',this.value);document.getElementById('limesurvey').submit();\" " . (($thissurvey['active'] != "Y") ? "disabled='disabled'" : "") . "/>";  // Show Save So Far button
+                }
+                else
+                {
+                $_saveall = "\t\t\t<input type='button' name='saveallbtn' value='" . $clang->gT("Resume Later") . "' class='saveall' onclick=\"javascript:document.limesurvey.move.value = this.value;addHiddenField(document.getElementById('limesurvey'),'saveall',this.value);document.getElementById('limesurvey').submit();\" " . (($thissurvey['active'] != "Y") ? "disabled='disabled'" : "") . "/>";  // Show Save So Far button
+        	};
+            }
+        elseif (!isset($_SESSION['step']) || !$_SESSION['step'])
+        {  //First page, show LOAD
+            if ($thissurvey['tokenanswerspersistence'] != 'Y')
+            {
+                $_saveall = "\t\t\t<input type='submit' name='loadall' value='" . $clang->gT("Load Unfinished Survey") . "' class='saveall' " . (($thissurvey['active'] != "Y") ? "disabled='disabled'" : "") . "/>";
+                }
+		else
+		{
+                    $_saveall = '';
+		};
+            }
+        elseif (isset($_SESSION['scid']) && (isset($move) && $move == "movelast"))
+        {  //Already saved and on Submit Page, dont show Save So Far button
+            $_saveall = '';
+            }
+            else
+            {
+            $_saveall = "<input type='button' name='saveallbtn' value='" . $clang->gT("Resume Later") . "' class='saveall' onclick=\"javascript:document.limesurvey.move.value = this.value;addHiddenField(document.getElementById('limesurvey'),'saveall',this.value);document.getElementById('limesurvey').submit();\" " . (($thissurvey['active'] != "Y") ? "disabled='disabled'" : "") . "/>";  // Show Save So Far button
+            }
+        }
+        else
+        {
+        $_saveall = "";
+        }
+
+    $_templatecss = "<link rel='stylesheet' type='text/css' href='{$_templateurl}template.css' />\n";
+        if (getLanguageRTL($clang->langcode))
+        {
+            $_templatecss.="<link rel='stylesheet' type='text/css' href='{$_templateurl}template-rtl.css' />\n";
+        }
+
+    if (FlattenText($help, true) != '')
+        {
+            If (!isset($helpicon))
+            {
+            if (file_exists($templatedir . '/help.gif'))
+                {
+
+                $helpicon = $_templateurl . 'help.gif';
+                }
+            elseif (file_exists($templatedir . '/help.png'))
+                {
+
+                $helpicon = $_templateurl . 'help.png';
+                }
+                else
+                {
+                $helpicon = $imageurl . "/help.gif";
+                }
+            }
+        $_questionhelp = '';
+        }
+    else
+    {
+        $_questionhelp = $help;
+    }
+
+    if (isset($thissurvey['allowprev']) && $thissurvey['allowprev'] == "N")
+    {
+            $_strreview = "";
+        }
+    else
+    {
+        $_strreview = $clang->gT("If you want to check any of the answers you have made, and/or change them, you can do that now by clicking on the [<< prev] button and browsing through your responses.");
+        }
+
+    if (isset($thissurvey['active']) and $thissurvey['active'] == "N")
+    {
+        $_restart = "<a href='{$publicurl}/index.php?sid=$surveyid&amp;newtest=Y";
+        if (isset($s_lang) && $s_lang != '') {
+            $_restart.="&amp;lang=" . $s_lang;
+        }
+        $_restart.="'>" . $clang->gT("Restart this Survey") . "</a>";
+    } else
+        {
+            $restart_extra = "";
+            $restart_token = returnglobal('token');
+        if (!empty($restart_token))
+            $restart_extra .= "&amp;token=" . urlencode($restart_token);
+        else
+            $restart_extra = "&amp;newtest=Y";
+        if (!empty($_GET['lang']))
+            $restart_extra .= "&amp;lang=" . returnglobal('lang');
+        $_restart = "<a href='{$publicurl}/index.php?sid=$surveyid" . $restart_extra . "'>" . $clang->gT("Restart this Survey") . "</a>";
+        }
+    if (isset($thissurvey['anonymized']) && $thissurvey['anonymized'] == 'Y')
+    {
+        $_savealert = $clang->gT("To remain anonymous please use a pseudonym as your username, also an email address is not required.");
+        }
+        else
+        {
+        $_savealert = "";
+        }
+
+        $_return_to_survey = "<a href='$relativeurl/index.php?sid=$surveyid";
+        if (returnglobal('token'))
+        {
+        $_return_to_survey.= "&amp;token=" . urlencode(trim(sanitize_xss_string(strip_tags(returnglobal('token')))));
+        }
+    $_return_to_survey .= "'>" . $clang->gT("Return To Survey") . "</a>";
+
+    $_saveform = "<table><tr><td align='right'>" . $clang->gT("Name") . ":</td><td><input type='text' name='savename' value='";
+    if (isset($_POST['savename']))
+    {
+        $_saveform .= html_escape(auto_unescape($_POST['savename']));
+    }
+        $_saveform .= "' /></td></tr>\n"
+            . "<tr><td align='right'>" . $clang->gT("Password") . ":</td><td><input type='password' name='savepass' value='";
+    if (isset($_POST['savepass']))
+    {
+        $_saveform .= html_escape(auto_unescape($_POST['savepass']));
+    }
+        $_saveform .= "' /></td></tr>\n"
+            . "<tr><td align='right'>" . $clang->gT("Repeat Password") . ":</td><td><input type='password' name='savepass2' value='";
+    if (isset($_POST['savepass2']))
+    {
+        $_saveform .= html_escape(auto_unescape($_POST['savepass2']));
+    }
+        $_saveform .= "' /></td></tr>\n"
+            . "<tr><td align='right'>" . $clang->gT("Your Email") . ":</td><td><input type='text' name='saveemail' value='";
+    if (isset($_POST['saveemail']))
+    {
+        $_saveform .= html_escape(auto_unescape($_POST['saveemail']));
+    }
+        $_saveform .= "' /></td></tr>\n";
+    if (isset($thissurvey['usecaptcha']) && function_exists("ImageCreate") && captcha_enabled('saveandloadscreen', $thissurvey['usecaptcha']))
+        {
+        $_saveform .="<tr><td align='right'>" . $clang->gT("Security Question") . ":</td><td><table><tr><td valign='middle'><img src='{$captchapath}verification.php?sid=$surveyid' alt='' /></td><td valign='middle' style='text-align:left'><input type='text' size='5' maxlength='3' name='loadsecurity' value='' /></td></tr></table></td></tr>\n";
+        }
+        $_saveform .= "<tr><td align='right'></td><td></td></tr>\n"
+            . "<tr><td></td><td><input type='submit'  id='savebutton' name='savesubmit' value='" . $clang->gT("Save Now") . "' /></td></tr>\n"
+        . "</table>";
+
+    $_loadform = "<table><tr><td align='right'>" . $clang->gT("Saved name") . ":</td><td><input type='text' name='loadname' value='";
+    if ($loadname)
+    {
+        $_loadform .= html_escape(auto_unescape($loadname));
+    }
+        $_loadform .= "' /></td></tr>\n"
+            . "<tr><td align='right'>" . $clang->gT("Password") . ":</td><td><input type='password' name='loadpass' value='";
+    if (isset($loadpass))
+    {
+        $_loadform .= html_escape(auto_unescape($loadpass));
+    }
+        $_loadform .= "' /></td></tr>\n";
+    if (isset($thissurvey['usecaptcha']) && function_exists("ImageCreate") && captcha_enabled('saveandloadscreen', $thissurvey['usecaptcha']))
+        {
+        $_loadform .="<tr><td align='right'>" . $clang->gT("Security Question") . ":</td><td><table><tr><td valign='middle'><img src='{$captchapath}verification.php?sid=$surveyid' alt='' /></td><td valign='middle'><input type='text' size='5' maxlength='3' name='loadsecurity' value='' alt=''/></td></tr></table></td></tr>\n";
+        }
+
+        $_loadform .="<tr><td align='right'></td><td></td></tr>\n"
+            . "<tr><td></td><td><input type='submit' id='loadbutton' value='" . $clang->gT("Load Now") . "' /></td></tr></table>\n";
+
+    $_registerform = "<form method='post' action='{$publicurl}/register.php'>\n";
+        if (!isset($_REQUEST['lang']))
+        {
+            $_reglang = GetBaseLanguageFromSurveyID($surveyid);
+        }
+        else
+        {
+            $_reglang = returnglobal('lang');
+        }
+    $_registerform .= "<input type='hidden' name='lang' value='" . $_reglang . "' />\n";
+        $_registerform .= "<input type='hidden' name='sid' value='$surveyid' id='sid' />\n";
+
+        $_registerform.="<table class='register' summary='Registrationform'>\n"
+            . "<tr><td align='right'>"
+            . $clang->gT("First name") . ":</td>"
+            . "<td align='left'><input class='text' type='text' name='register_firstname'";
+        if (isset($_POST['register_firstname']))
+        {
+        $_registerform .= " value='" . htmlentities(returnglobal('register_firstname'), ENT_QUOTES, 'UTF-8') . "'";
+        }
+        $_registerform .= " /></td></tr>"
+            . "<tr><td align='right'>" . $clang->gT("Last name") . ":</td>\n"
+            . "<td align='left'><input class='text' type='text' name='register_lastname'";
+        if (isset($_POST['register_lastname']))
+        {
+        $_registerform .= " value='" . htmlentities(returnglobal('register_lastname'), ENT_QUOTES, 'UTF-8') . "'";
+        }
+        $_registerform .= " /></td></tr>\n"
+            . "<tr><td align='right'>" . $clang->gT("Email address") . ":</td>\n"
+            . "<td align='left'><input class='text' type='text' name='register_email'";
+        if (isset($_POST['register_email']))
+        {
+        $_registerform .= " value='" . htmlentities(returnglobal('register_email'), ENT_QUOTES, 'UTF-8') . "'";
+        }
+        $_registerform .= " /></td></tr>\n";
+
+
+    if (isset($thissurvey['usecaptcha']) && function_exists("ImageCreate") && captcha_enabled('registrationscreen', $thissurvey['usecaptcha']))
+        {
+        $_registerform .="<tr><td align='right'>" . $clang->gT("Security Question") . ":</td><td><table><tr><td valign='middle'><img src='{$captchapath}verification.php?sid=$surveyid' alt='' /></td><td valign='middle'><input type='text' size='5' maxlength='3' name='loadsecurity' value='' /></td></tr></table></td></tr>\n";
+        }
+
+
+        /*      if(isset($thissurvey['attribute1']) && $thissurvey['attribute1'])
+         {
+         $_registerform .= "<tr><td align='right'>".$thissurvey['attribute1'].":</td>\n"
+         ."<td align='left'><input class='text' type='text' name='register_attribute1'";
+         if (isset($_POST['register_attribute1']))
+         {
+         $_registerform .= " value='".htmlentities(returnglobal('register_attribute1'),ENT_QUOTES,'UTF-8')."'";
+         }
+         $_registerform .= " /></td></tr>\n";
+         }
+         if(isset($thissurvey['attribute2']) && $thissurvey['attribute2'])
+         {
+         $_registerform .= "<tr><td align='right'>".$thissurvey['attribute2'].":</td>\n"
+         ."<td align='left'><input class='text' type='text' name='register_attribute2'";
+         if (isset($_POST['register_attribute2']))
+         {
+         $_registerform .= " value='".htmlentities(returnglobal('register_attribute2'),ENT_QUOTES,'UTF-8')."'";
+         }
+         $_registerform .= " /></td></tr>\n";
+      } */
+    $_registerform .= "<tr><td></td><td><input id='registercontinue' class='submit' type='submit' value='" . $clang->gT("Continue") . "' />"
+            . "</td></tr>\n"
+            . "</table>\n"
+            . "</form>\n";
+
+    if (!is_null($surveyid) && function_exists('doAssessment'))
+    {
+        $assessmentdata = doAssessment($surveyid, true);
+        $_assessment_current_total = $assessmentdata['total'];
+    }
+    else
+    {
+        $_assessment_current_total = '';
+    }
+
+    // Set the array of replacement variables here - don't include curly braces
+	$corecoreReplacements = array();
+	$coreReplacements['ANSWER'] = $answer;  // global
+	$coreReplacements['ANSWERSCLEARED'] = $clang->gT("Answers Cleared");
+	$coreReplacements['ASSESSMENTS'] = $assessments;    // global
+	$coreReplacements['ASSESSMENT_CURRENT_TOTAL'] = $_assessment_current_total;
+	$coreReplacements['ASSESSMENT_HEADING'] = $clang->gT("Your Assessment");
+	$coreReplacements['CHECKJAVASCRIPT'] = "<noscript><span class='warningjs'>".$clang->gT("Caution: JavaScript execution is disabled in your browser. You may not be able to answer all questions in this survey. Please, verify your browser parameters.")."</span></noscript>";
+	$coreReplacements['CLEARALL'] = $_clearall;
+	$coreReplacements['CLOSEWINDOW']  =  "<a href='javascript:%20self.close()'>".$clang->gT("Close this window")."</a>";
+	$coreReplacements['COMPLETED'] = $completed;    // global
+	$coreReplacements['DATESTAMP'] = $_datestamp;
+	$coreReplacements['EXPIRY'] = $_dateoutput;
+	$coreReplacements['GROUPDESCRIPTION'] = $_groupdescription;
+	$coreReplacements['GROUPNAME'] = $_groupname;
+	$coreReplacements['LANG'] = $clang->getlangcode();
+	$coreReplacements['LANGUAGECHANGER'] = $languagechanger;    // global
+	$coreReplacements['LOADERROR'] = $errormsg; // global
+	$coreReplacements['LOADFORM'] = $_loadform;
+	$coreReplacements['LOADHEADING'] = $clang->gT("Load A Previously Saved Survey");
+	$coreReplacements['LOADMESSAGE'] = $clang->gT("You can load a survey that you have previously saved from this screen.")."<br />".$clang->gT("Type in the 'name' you used to save the survey, and the password.")."<br />";
+	$coreReplacements['NAVIGATOR'] = $navigator;    // global
+	$coreReplacements['NOSURVEYID'] = $surveylist['nosid']; // global
+	$coreReplacements['NUMBEROFQUESTIONS'] = $_totalquestionsAsked;
+	$coreReplacements['PERCENTCOMPLETE'] = $percentcomplete;    // global
+	$coreReplacements['PRIVACY'] = $privacy;    // global
+	$coreReplacements['PRIVACYMESSAGE'] = "<span style='font-weight:bold; font-style: italic;'>".$clang->gT("A Note On Privacy")."</span><br />".$clang->gT("This survey is anonymous.")."<br />".$clang->gT("The record kept of your survey responses does not contain any identifying information about you unless a specific question in the survey has asked for this. If you have responded to a survey that used an identifying token to allow you to access the survey, you can rest assured that the identifying token is not kept with your responses. It is managed in a separate database, and will only be updated to indicate that you have (or haven't) completed this survey. There is no way of matching identification tokens with survey responses in this survey.");
+	$coreReplacements['QUESTION'] = $_question;
+	$coreReplacements['QUESTIONHELP'] = $_questionhelp;
+	$coreReplacements['QUESTIONHELPPLAINTEXT'] = strip_tags(addslashes($help)); // global
+	$coreReplacements['QUESTION_CLASS'] = $_question_class;
+	$coreReplacements['QUESTION_CODE'] = $_question_code;
+	$coreReplacements['QUESTION_ESSENTIALS'] = $_question_essentials;
+	$coreReplacements['QUESTION_FILE_VALID_MESSAGE'] = $_question_file_valid_message;
+	$coreReplacements['QUESTION_HELP'] = $_question_help;
+	$coreReplacements['QUESTION_INPUT_ERROR_CLASS'] = $_question_input_error_class;
+	$coreReplacements['QUESTION_MANDATORY'] = $_question_mandatory;
+	$coreReplacements['QUESTION_MAN_CLASS'] = $_question_man_class;
+	$coreReplacements['QUESTION_MAN_MESSAGE'] = $_question_man_message;
+	$coreReplacements['QUESTION_NUMBER'] = $_question_number;
+	$coreReplacements['QUESTION_TEXT'] = $_question_text;
+	$coreReplacements['QUESTION_VALID_MESSAGE'] = $_question_valid_message;
+	$coreReplacements['REGISTERERROR'] = $register_errormsg;    // global
+	$coreReplacements['REGISTERFORM'] = $_registerform;
+	$coreReplacements['REGISTERMESSAGE1'] = $clang->gT("You must be registered to complete this survey");
+	$coreReplacements['REGISTERMESSAGE2'] = $clang->gT("You may register for this survey if you wish to take part.")."<br />\n".$clang->gT("Enter your details below, and an email containing the link to participate in this survey will be sent immediately.");
+	$coreReplacements['RESTART'] = $_restart;
+	$coreReplacements['RETURNTOSURVEY'] = $_return_to_survey;
+	$coreReplacements['SAVE'] = $_saveall;
+	$coreReplacements['SAVEALERT'] = $_savealert;
+	$coreReplacements['SAVEDID'] = $saved_id;   // global
+	$coreReplacements['SAVEERROR'] = $errormsg; // global - same as LOADERROR
+	$coreReplacements['SAVEFORM'] = $_saveform;
+	$coreReplacements['SAVEHEADING'] = $clang->gT("Save Your Unfinished Survey");
+	$coreReplacements['SAVEMESSAGE'] = $clang->gT("Enter a name and password for this survey and click save below.")."<br />\n".$clang->gT("Your survey will be saved using that name and password, and can be completed later by logging in with the same name and password.")."<br /><br />\n".$clang->gT("If you give an email address, an email containing the details will be sent to you.")."<br /><br />\n".$clang->gT("After having clicked the save button you can either close this browser window or continue filling out the survey.");
+	$coreReplacements['SGQ'] = $_question_sgq;
+	$coreReplacements['SID'] = $surveyid;   // global
+	$coreReplacements['SITENAME'] = $sitename;  // global
+	$coreReplacements['SUBMITBUTTON'] = $_submitbutton;
+	$coreReplacements['SUBMITCOMPLETE'] = "<strong>".$clang->gT("Thank you!")."<br /><br />".$clang->gT("You have completed answering the questions in this survey.")."</strong><br /><br />".$clang->gT("Click on 'Submit' now to complete the process and save your answers.");
+	$coreReplacements['SUBMITREVIEW'] = $_strreview;
+	$coreReplacements['SURVEYCONTACT'] = $_surveycontact;
+	$coreReplacements['SURVEYDESCRIPTION'] = (isset($thissurvey['description']) ? $thissurvey['description'] : '');
+	$coreReplacements['SURVEYFORMAT'] = $surveyformat;  // global
+	$coreReplacements['SURVEYLANGAGE'] = $clang->langcode;
+	$coreReplacements['SURVEYLIST'] = $surveylist['list'];  // global
+	$coreReplacements['SURVEYLISTHEADING'] =  $surveylist['listheading'];   // global
+	$coreReplacements['SURVEYNAME'] = $thissurvey['name'];  // global
+	$coreReplacements['TEMPLATECSS'] = $_templatecss;
+	$coreReplacements['TEMPLATEURL'] = $_templateurl;
+	$coreReplacements['THEREAREXQUESTIONS'] = $_therearexquestions;
+	$coreReplacements['TOKEN'] = $_token;
+	$coreReplacements['URL'] = $_linkreplace;
+	$coreReplacements['WELCOME'] = (isset($thissurvey['welcome']) ? $thissurvey['welcome'] : '');
+
+    $doTheseReplacements = array_merge($coreReplacements, $replacements);   // so $replacements overrides core values
+
+    // Now do all of the replacements
+    $line = insertansReplace($line);
+    $line = tokenReplace($line);
+    foreach ($doTheseReplacements as $key => $value )
+    {
+        $line=str_replace('{' . $key . '}', $value, $line);
+    }
+    
+    return $line;
+}
+
+/**
+ * insertAnsReplace() takes a string and looks for any {INSERTANS:xxxx} variables
+ *  which it then, one by one, substitutes the SGQA code with the relevant answer
+ *  from the session array containing responses
+ *
+ *  The operations of this function were previously in the templatereplace function
+ *  but have been moved to a function of their own to make it available
+ *  to other areas of the script.
+ *
+ * @param mixed $line   string - the string to iterate, and then return
+ *
+ * @return string This string is returned containing the substituted responses
+ *
+ */
+function insertansReplace($line)
+{
+    if (!isset($_SESSION['dateformats']['phpdate'])) $_SESSION['dateformats']['phpdate']='';
+    while (strpos($line, "{INSERTANS:") !== false)
+    {
+        $answreplace=substr($line, strpos($line, "{INSERTANS:"), strpos($line, "}", strpos($line, "{INSERTANS:"))-strpos($line, "{INSERTANS:")+1);
+        $answreplace2=substr($answreplace, 11, strpos($answreplace, "}", strpos($answreplace, "{INSERTANS:"))-11);
+        $answreplace3=strip_tags(retrieve_Answer($answreplace2, $_SESSION['dateformats']['phpdate']));
+        $line=str_replace($answreplace, $answreplace3, $line);
+    }
+    return $line;
+}
+
+/**
+ * tokenReplace() takes a string and looks for any {TOKEN:xxxx} variables
+ *  which it then, one by one, substitutes the TOKEN code with the relevant token
+ *  from the session array containing token information
+ *
+ *  The operations of this function were previously in the templatereplace function
+ *  but have been moved to a function of their own to make it available
+ *  to other areas of the script.
+ *
+ * @param mixed $line   string - the string to iterate, and then return
+ *
+ * @return string This string is returned containing the substituted responses
+ *
+ */
+function tokenReplace($line)
+{
+    global $surveyid;
+
+    if (isset($_SESSION['token']) && $_SESSION['token'] != '')
+    {
+        //Gather survey data for tokenised surveys, for use in presenting questions
+        $_SESSION['thistoken']=getTokenData($surveyid, $_SESSION['token']);
+    }
+
+    if (isset($_SESSION['thistoken']))
+    {
+        if (strpos($line, "{TOKEN:FIRSTNAME}") !== false) $line=str_replace("{TOKEN:FIRSTNAME}", $_SESSION['thistoken']['firstname'], $line);
+        if (strpos($line, "{TOKEN:LASTNAME}") !== false) $line=str_replace("{TOKEN:LASTNAME}", $_SESSION['thistoken']['lastname'], $line);
+        if (strpos($line, "{TOKEN:EMAIL}") !== false) $line=str_replace("{TOKEN:EMAIL}", $_SESSION['thistoken']['email'], $line);
+    }
+    else
+    {
+        if (strpos($line, "{TOKEN:FIRSTNAME}") !== false) $line=str_replace("{TOKEN:FIRSTNAME}", "", $line);
+        if (strpos($line, "{TOKEN:LASTNAME}") !== false) $line=str_replace("{TOKEN:LASTNAME}", "", $line);
+        if (strpos($line, "{TOKEN:EMAIL}") !== false) $line=str_replace("{TOKEN:EMAIL}", "", $line);
+    }
+
+    while (strpos($line, "{TOKEN:ATTRIBUTE_")!== false)
+    {
+        $templine=substr($line,strpos($line, "{TOKEN:ATTRIBUTE_"));
+        $templine=substr($templine,0,strpos($templine, "}")+1);
+        $attr_no=(int)substr($templine,17,strpos($templine, "}")-17);
+        $replacestr='';
+        if (isset($_SESSION['thistoken']['attribute_'.$attr_no])) $replacestr=$_SESSION['thistoken']['attribute_'.$attr_no];
+        $line=str_replace($templine, $replacestr, $line);
+    }
+    return $line;
+}
+
+/**
+ * passthruReplace() takes a string and looks for {PASSTHRULABEL}, {PASSTHRUVALUE} and {PASSTHRU:myarg} variables
+ *  which it then substitutes for passthru data sent in the initial URL and stored
+ *  in the session array containing responses
+ *
+ * @param mixed $line   string - the string to iterate, and then return
+ * @param mixed $thissurvey     string - the string containing the surveyinformation
+ * @return string This string is returned containing the substituted responses
+ *
+ */
+function PassthruReplace($line, $thissurvey)
+{
+    $line=str_replace("{PASSTHRULABEL}", $thissurvey['passthrulabel'], $line);
+    $line=str_replace("{PASSTHRUVALUE}", $thissurvey['passthruvalue'], $line);
+
+    //  Replacement for variable passthru argument like {PASSTHRU:myarg}
+    while (strpos($line,"{PASSTHRU:") !== false)
+    {
+        $p1 = strpos($line,"{PASSTHRU:"); // startposition
+        $p2 = $p1 + 10; // position of the first arg char
+        $p3 = strpos($line,"}",10); // position of the last arg char
+
+        $cmd=substr($line,$p1,$p3-$p1+1); // extract the complete passthru like "{PASSTHRU:myarg}"
+        $arg=substr($line,$p2,$p3-$p2); // extract the arg to passthru (like "myarg")
+
+        // lookup for the fitting arg
+        $qstring = $_SESSION['ls_initialquerystr']; // get initial query_string
+
+        parse_str($qstring, $keyvalue); // split into key and value
+        $match = 0; // prevent an endless loop if there is no arg in url
+        foreach ($keyvalue as $key=>$value) // lookup loop
+        {
+            if ($key == $arg) // if match
+            {
+                $line=str_replace($cmd, $arg . "=" . $value, $line); // replace
+                $match = 1;
+                break;
+            }
+
+        }
+
+        if ($match == 0)
+        {
+            $line=str_replace($cmd, $arg . "=", $line); // clears "{PASSTHRU:myarg} to "myarg=" if there was no myarg in calling url
+        }
+    }
+
+    return $line;
+}
+
+?>
bug_5317_fix.patch (74,160 bytes)   
Bug heat4
Complete LimeSurvey version number (& build)10407
I will donate to the project if issue is resolvedNo
BrowserFirefox
Database type & versionMysql 5
Server OS (if known)Windows XP
Webserver software & version (if known)Apache 2
PHP Version5.2

Users monitoring this issue

There are no users monitoring this issue.

Activities

c_schmitz

c_schmitz

2011-07-03 10:10

administrator   ~15619

Please commit to stable and dev branch. I am not sure if the CI port will still pick this up from dev. So it might still be necessary to re-integrate in the CI port.

TMSWhite

TMSWhite

2011-07-04 04:15

reporter   ~15625

Fixed in Revision 10415 for limesurvey branch
Fixed in Revision 10419 for limesurvey_dev branch

Note, the limesurvey_dev branch had the following 3 variables which were not in the main branch: GID, QID, AID.

c_schmitz

c_schmitz

2011-07-08 17:15

administrator   ~15689

New 1.91+ version released.

Issue History

Date Modified Username Field Change
2011-07-03 06:42 TMSWhite New Issue
2011-07-03 06:46 TMSWhite File Added: bug_5317_fix.patch
2011-07-03 06:53 TMSWhite Additional Information Updated
2011-07-03 10:09 c_schmitz Assigned To => TMSWhite
2011-07-03 10:09 c_schmitz Status new => assigned
2011-07-03 10:10 c_schmitz Note Added: 15619
2011-07-04 04:15 TMSWhite Note Added: 15625
2011-07-04 04:15 TMSWhite Status assigned => resolved
2011-07-04 04:15 TMSWhite Fixed in Version => 1.91+
2011-07-04 04:15 TMSWhite Resolution open => fixed
2011-07-08 17:15 c_schmitz Note Added: 15689
2011-07-08 17:15 c_schmitz Status resolved => closed