View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
05103User patchesOtherpublic2011-04-11 20:372012-06-21 13:22
Assigned ToTMSWhite 
Product Version1.91RC5 
Target VersionFixed in Version2.00 
Summary05103: Support conditional piping/tailoring and complex calculations via embedded equation parser
DescriptionI'd like to add an embedded equation parser to LimeSurvey similar to the one I had to create for a different survey platform.

Steps include:
(1) Agree upon a way to delimit portions of a string that should be treated as plain text and those that should be run through the equation parser. In my case, I surrounded computable sections with back-tiks (`). For sake of discusion here, I'll assume we decide to use back-tiks, but I'm certainly open to using a different set of delimiters.
(2) Create way to lookup Question-Objects and their associated attributes and answers by the variable name associated with the question. This way users can write complex equations using the variable names they are used to (as an alternative to having to figure out what the SGQA-equivalent would be). Since there is already a way to lookup questions by Question Number {Question:
(3) Agree upon a grammar for the equation parser. Using JavaScript grammar is most convenient, because it is well known/documented, it can be debugged using existing IDE tools and FireBug, and there are published YACC grammars in case we need a compiler-compiler.
(4) Agree on syntax for referring to Question attributes (in a read-only manner). For example, say you have a variable called BothersomenessOfPsychoticSymptoms (BOPS), and the question text is "{FirstName}, you mentioned having {X} psychotic symptoms, including {list-of-symptoms}. On a scale of 1-5, from not-at-all to severe, how much do they bother you on a daily basis?". And, say you've translated this into 15 languages. Some of the attributes of the question you might want to access include (but are not limited to): BOPS.question (to get text of question as rendered to user in whatever language they saw it in), BOPS.answer (to get the text of the answer choice they selected, such as "moderately"), BOPS.answerCode (to get the numerical value of the answer they selected, such as 3), BOPS.questionSrc (to get the unparsed text of the question - e.g. for debugging purposes). We might also want the variable name without dot extension to refer to the answer (since that is the most common usage).
(5) Agree upon an execution engine for the syntax. Other groups, like the National Library of Medicine and Project REDCap both do the parsing directly in JavaScript, so they found ways to make that secure. I happened to write a JavaCC compiler-compiler for my system, but I don't recommend going to that extreme. Rather, if we can validate that there are no security risks in the equation, we can let JavaScript do the processing itself. This would make it easier to add additional functions and functionality.

Say we agreed to use back-tiks as the delimiter, you might have the following questions, in comma-delimited format (variableName, Question, AnswerType, AnswerChoices). For AnswerChoices, the syntax is <message>,<code>[|<message>,<code>]*

hasChild, "Do you have any chidren?", list, "No,0|Yes,1"
male, "What gender `(hasChild==1)?'is your oldest child':'might you want your first child to be'`?", list, "Female,0|Male,1"
name, "What `(hasChild==1)?'is':'might you want'` `(male==1)?'his':'her'` name `(hasChild==1)?'':'to be'`?, text

The parser would take the following steps for each question:
(1) Divide the string into sections - those outside of the back-tiks and those within them, putting the collection of sections into an array.
(2) Run each section within back-tiks through the equation parser, then concatenate the array sections back into a string as the value to be shown to the user.
(3) For each section within back-tiks:
(a) optionally use preg_match to find everything that looks like a function declaration and ensure it is a supported function (e.g. to optionally support only a subset of Javascript functions)
(b) optionally use preg_match to find any other JavaScript syntax we're worried about and return an error message showing the requested function and the string position of the start of the detected problem.
(c) At development-time, use preg_match to find everthing that looks like a variable (e.g. name of a question), and check against $_SESSION['fieldarray'] to ensure that each those variables exist and have already been "declared" prior to being used within the current question. If not, generate a list of variables which are not yet defined and return them to the user.
(d) At run-time, use preg_replace to replace all of the variables names with JavaScript code needed to get the current value for that questions (or other specified attributes, like the question text or answer code). If despite step (c) the question hasn't been asked before the user gets to it (this can happen if there are conditions that make dependent questions not-applicable), then display the result as *UNASKED*

Steps (1),(2),and (3)(a)-(c) would need to be applied when a user saves a Question or Answer during development
Steps (1),(2), and (3)(d) would need to be applied at each place where a string to display is returned (e.g. qanda.php:answer_replace() - I haven't looked at all the locations yet).

Once there is a mechanism to do arbitrary calculations, it can also be used for advanced validations and conditions to determine whether a question is relevant.
For example, in some of the epidemiological surveys we've run, we first determine whether the patients meets criteria for depression (5 of 12 symptoms in last 2 weeks with no systemic cause), and then ask symptom-specific follow-up questions. We've had questions and groups with a dozen pre-conditions.

I would recommend treating this sort of functionality as a power-user-only set of features. Although it might eventually be possible to create a GUI for it, I found the the epidemiologists I worked with preferred not to use a GUI, since they could have thousands of questions and it was easier to put them in Excel and use Excel-style filtering and searches to find the variables they needed and their allowable value-sets.
TagsNo tags attached.
Complete LimeSurvey version number (& build)9992
Attached Files? file icon limesurvey_survey_showing_conditional_tailoring_using_equation_parser.lss [^] (28,583 bytes) 2011-06-10 08:28
patch file icon issue_05103.patch [^] (64,510 bytes) 2011-06-10 09:15 [Show Content]
patch file icon issue_05103-rev2.patch [^] (83,074 bytes) 2011-06-12 09:38 [Show Content]
? file icon limesurvey_survey_showing_conditional_tailoring_using_equation_parser-rev2.lss [^] (30,727 bytes) 2011-06-12 09:44
patch file icon issue_05103-20110616.patch [^] (90,972 bytes) 2011-06-16 08:57 [Show Content]
? file icon ExpressionManager-plus-all-question-types.lss [^] (169,303 bytes) 2011-06-16 08:58
patch file icon issue_05103-20110616a.patch [^] (90,279 bytes) 2011-06-16 09:45 [Show Content]
zip file icon [^] (450,029 bytes) 2011-06-16 14:12
zip file icon [^] (117,240 bytes) 2011-06-16 14:12
patch file icon issue_05268-20110617.patch [^] (153,393 bytes) 2011-06-17 12:00
patch file icon issue_05268-20110617-v2.patch [^] (155,683 bytes) 2011-06-18 00:35
? file icon RegressionTester-en-de.lss [^] (321,776 bytes) 2011-07-11 23:25

- Relationships
related to 05288closedTMSWhite User patches Optionally replace Assessments with ExpressionManager features 
related to 05269closedTMSWhite User patches Use ExpressionManager for Branching logic as optional alternative to Conditions 
related to 05268closedc_schmitz User patches Do all LimeReplacementField and Token replacements in a single function 
related to 05104closedTMSWhite User patches Create new question type for stored calculation results, called Equation 
related to 05279acknowledged Development  Add a GUI for ExpressionManager 
related to 04424closedTMSWhite User patches New URL field {GATE} to switch exit-URL and parameters by logical expressions 

-  Notes
TMSWhite (reporter)
2011-04-19 20:36

This proposal is a more generic version of Issue 04424: "New URL field {GATE} to switch exit-URL and parameters by logical expressions". Given the security risk of using eval(), I've been looking into some options to address this.

The most robust solution is to build a compiler compiler with the stripped down functionality needed for processing these expressions. In general, I've found compiler compilers are easy to build and maintain in YACC, Bison, and JavaCC. However, they emit code for C, C, and Java, respectively. Unless LimeSurvey is open to having a binary plug-in (e.g. compiled C code), I presume you'd want a JavaScript and/or PHP-based compiler-compiler. Oddly, I've been having a hard time finding operational and maintained compiler-compilers for either JavaScript or PHP.

Here is the best of what I've found so far:

(1), [^] and [^]
-894 lines of JavaScript, and clearly-enough written that would be easy to extend. However, it appears based upon a Shunting Yard algorithm rather than a Backus–Naur Form (BNF) grammar, so might be harder to add additional syntactic functionality (like array references) if truly needed.
(2) RPA Search: [^]
- Does use BNF, and has operational demo
- 95K binary (for windows, linux), GNU v3 license
(3) Narcissus: [^] and [^]
- Uses a metacircular interpreter, which is harder to develop and maintain than BNF
- Requires installation of SpiderMonkey shell
- Not clear that actively maintained
(4) FireBug: [^]
- This is a robust platform for JavaScript, CSS, etc. It includes equation building and debugging capabilities. However, it is very over-inclusive. Would need to check with developers to see whether there is a way to get a version that only does the needed JavaScript expression parsing.

- I could not find any operational PHP compiler-compilers. However, something like RPA-Search could do the trick
Mazi (developer)
2011-05-27 13:42

Carsten, I assigned the ticket to you because TMS wanted to talk about some details and post further suggestion here. This way you will be notified.
TMSWhite (reporter)
2011-05-27 15:53

Here's where I am so far, (using the numbering from above).

I have proposed solutions for #s 1 and 2, and a comment/question about #3.

(1) Syntax: I plan to use {EVAL: ... }, and treat the ... as an equation to be parsed where variable names are of the form question.title
(2) Retrieve value by queestion.title - successfully prototyped that I could do this using {ANS: ... } via .\classes\dTexts\dFunctions\dFunctionAns.php
(3) Grammar - this will be tricky. I haven't been able to find a decent compiler compiler for PHP, and although I wrote a stack-based equation parser in C 20 years ago, I don't want to recreate such work when there really should be a BNF or EBNF compiler compiler out there somewhere.

(3) Grammar - In lieu of building a custom equation parser (although I'm happy to do this if someone finds a robust and well-maintained BNF parser that generates PHP), I'd like to find a safe way to validate a self-entered equation so that it can be parsed by PHP eval(). There are several pretty good examples of "safe_eval" here: [^] . I envision taking this approach:
(a) Blacklist certain operators and syntax, perhaps including =, =>, dot notation to call member functions of an object, [ ] to access array elements, &.
(b) Create a whitelist of allowable functions (e.g. math, and pluggable functions loaded, perhaps, using a method like that used in dTexts)
(c) Create a list of allowable variable names (using either SGQA or question.title syntax) from questions that have already been
(d) Add known token names to the list of allowable variables
(e) Check that the equation only contains Strings, known variables, white-listed functions, and allowed punctuation. Otherwise throw an error, noting the offending part of the equation.
(f) When replacing variables with their values, first check whether they are numeric or string. For Strings, surround them with quotes (so that users can't inject arbitrary code in an answer and have it evaluated). If the variable does not yet have a value, or is undefined, treat it as a String (e.g. [UNANSWERED: myVar]) to ease debugging
(g) Validate that the string to be evaluated ends with ';'
(h) Validate that parentheses match (to avoid one set of errors)
(i) Consider using forking or other methods (like in [^] notes) so can catch errors at execution time. Otherwise, a FATAL error in the eval() will kill the rest of the script. I don't have a good sense of what sorts of syntax errors might be fatal
(j) Use PHP eval() to evaluate the resulting string and return the resulting value.

Are there other steps I need to consider to make this approach safe and secure?
Alternatively, do you know of a well-supported, PHP-based equation parser or grammar generator I could use? (see notes above for what I've already explored)
TMSWhite (reporter)
2011-05-27 20:21

Another option for (3) (since I'm having a hard time letting go of the idea of being able to do this in BNF).

To recap, the functionality I'm looking for here is very basic:
(1) All basic math operators and functions
(2) Ability to call other functions from a "white list" of supported functions (which would be included from an external source - could be existing JavaScript/PHP functions, or external ones we need to add). At present, I categorize the functions by whether they take 0, 1, 2, 3, or unlimited arguments, so I can enforce a small degree of syntax checking.
(3) Ability to handle numbers, strings, and dates separately (e.g. so can throw syntax exceptions if the a given math operator is not appropriate for a data type)
(4) Only allowable syntax is supported (so can avoid calls to arrays, functions, hashes, macros, etc. - anything that might be unsafe or put the website at risk of an injection attack)
(5) Only be able to reference known variables (e.g. question.title, SGQA, and token names).

From a usability perspective, we want to
(1) Validate that the equation is safe
(2) Provide the user appropriate and helpful feedback if there is a syntax error.

Once we have validated that the equation is safe, we could let PHP and/or JavaScript's eval() functions execute the code (after doing some token substitutions so that PHP/JavaScript lookup the answers properly based upon the question.title, SGQA, or token names).

Also, I presume we only need to validate the equation using JavaScript, since the user will always use a web page to author the survey. Even if they import it from a file, we could always generate a test page that validates the equation syntax (using JavaScript) before final acceptance of the import. The only risk I see here is if a user manually edits the equation in the MySQL tables, but I presume that should be a minimal risk (e.g. you can trash a website you are managing, but not one belonging to someone else).

So, are there good JavaScript-based expression evaluators / syntax checkers?

I see that JSLint ( [^]) is written in JavaScript, available via GPL-equivalent on GitHub, and very well and recently documented.

I'm going to see what other options are out there, and what it would take to trim down JSLint to validate the simplified equation syntax I'm targeting.

Are there any concerns with this approach, should it pan out?
TMSWhite (reporter)
2011-06-10 00:24

I have created a safe equation parser with complete unit tests. It is committed to the limesurvey_dev_tms branch under limesurvey/classes/eval. You can see the unit test results here: limesurvey/classes/eval/Test_ExpressionManager_Evaluate.php

The system provides read-only access to registered variables (e.g. all pre-defined variables in the survey), and registered functions (e.g. all match functions, plus others we want to add, like sum(), if(test,if_true,if_false))

The parser can be changed to allow read-write access to variables if we want, or give the ability to create temporary variables, but both such options could cause unexpected side effects.
TMSWhite (reporter)
2011-06-10 08:27

DONE, and fully unit tested.

As per the commit message (revision 10245):

Added embedded equation parser, which uses a recursive descent parser to support arbitrarily complex equations.
The equation parser optionally provides detailed information about syntax errors, and safely returns NULL if user evaluates a poorly formed equation.
The equation parser has read-only access to all previously asked survey variables via either question title or SGQA code.
The equation parser currently provides safe access to ~100 PHP math and string functions, plus conditional logic via the if(test,true,false) function.
The equation parser is called via the {EVAL: equation} syntax
Also added {ANS: varName} syntax so can refer to variable by its question title instead of SGQA code.
Fixed minor bug in dTexts.php that would cause {EVAL: equation } parsing to fail if there were a colon in the equation.
TMSWhite (reporter)
2011-06-10 08:31

The file limesurvey_survey_showing_conditional_tailoring_using_equation_parser.lss demonstrates how to use the new {EVAL: expression} and {ANS: varName} features. It asks 4 preliminary questions (name, age, number of kids, number of pets), then generates a tailored question based upon that information.

Please give it a try.
TMSWhite (reporter)
2011-06-10 09:06

Quick update to prior notes:

In the end, I had to create my own compiler (a recursive descent parser) to safely evaluate equations. None of the compiler-compiler options would generate PHP code. Antlr looked most promising, but the plug-in for generating PHP was not well maintained. JSLint could not be easily modified to validate just the subset of functionality we needed, plus even if it did, it would still not address the PHP processing needs.

So, I bit the bullet and ported my JavaCC-based equation parser into PHP, converting it into a recursive descent parser instead of creating a state based machine. Recursive descent parsers are much easier to read (it is only 1500 lines of code, a third of which are unit tests) than state based machines. The only down side is that equations can have a maximum of 10 levels of nested parentheses before PHP throws a nesting error (but how often does one need ten levels deep of nested parentheses)?
TMSWhite (reporter)
2011-06-10 09:20

Please test the attached unified patch (issue_05103.patch). It was generated against limesurvey (main branch) revision 10245.

I have tested the limesurvey_survey_showing_conditional_tailoring_using_equation_parser.lss survey and unit tests (http://localhost/limesurvey/classes/eval/Test_ExpressionManager_Evaluate.php [^]) after applying this patch, and they all run fine for me.

So, if this also works for you, please add this feature to the main branch and mark this issue 'resolved'.

TMSWhite (reporter)
2011-06-11 21:49

What is the preferred way to set values of variables in the database?

Several of the other threads seem they could benefit from this,so I have upgraded the equation parser to support assigning registered variables within an equation (e.g. a = b, c += d, etc). The unit testing on the equation parser works fine, but all assignment is done locally within the equation parser. To integrate with LimeSurvey, I'll set a dirty flag so that we know which of the registered variables had had their values changed.

So, once I know which of the variables have changed values, how do I ensure that this gets recorded?
(1) Server-Side (PHP) - Do I have to update the database directly?
(2) Client-Side (JavaScript) - If I just update the value of the appropriate DOM object (e.g. document.getElementById("answerSGQA").value = new_value, where SGQA is the SGQA code), will LimeSurvey automatically update the associated database field, or do I need to do something else too?
TMSWhite (reporter)
2011-06-12 09:40
edited on: 2011-06-12 09:44

I've uploaded a new patch that provides significant enhancements.

Description of ExpressionManager
(1) Does safe evaluation of PHP expressions. Only registered Functions, Variables, and ReservedWords are allowed.
  (a) Functions include any math, string processing, conditional, formatting, etc. functions
  (b) Variables are typically the question name (question.title)
  (c) ReservedWords are any LimeReplacementField or Token, including all INSERTANS:SGQA codes
(2) This class can replace LimeSurvey's current process of resolving strings that contain LimeReplacementFields
  (a) String is split by expressions (by curly braces, but safely supporting strings and escaped curly braces)
  (b) Expressions (things surrounded by curly braces) are evaluated - thereby doing LimeReplacementField substitution and/or more complex calculations
  (c) Non-expressions are left intact
  (d) The array of stringParts are re-joined to create the desired final string.

Try this link to test the new functionality: http://localhost/limesurvey/classes/eval/Test_ExpressionManager_ProcessStringContainingExpressions.php [^]

You can also try this new survey: limesurvey_survey_showing_conditional_tailoring_using_equation_parser-rev2.lss

Both validate that the parser can now handle SGQA names (and other LimeReplacementFields that contain a colon, like TOKEN:NAME)

TMSWhite (reporter)
2011-06-13 18:45

Alhtough I initially planned to use the dTexts module to call these expressions (so added support for {ANS:xxxx} and {EVAL:xxxx}, it looks as though dTexts is nearly obsolete, so I'll have the ExpressionManager handle both types of replacement directly.

ExpressionManager will parse a string, and do replacement on anything found between curly braces. So, rather than {EVAL:a * b - c}, we'd do {a * b - c}.
TMSWhite (reporter)
2011-06-16 09:03
edited on: 2011-06-16 09:46

First tests of integrating ExpressionManager into the LS1 branch have been successful. At present, it is only integrated into template_replace, but it should not be hard to put it into the other places that do {} replacement.

Please give this a try.
(1) Apply patch issue_05103-20110616a.patch
(2) Try survey ExpressionManager-plus-all-question-types.lss
  (a) 1st 2 pages show conditional substitution of 4 variables to change wording of question
  (b) 3rd page tests all question types, and reports (on 4th page), table of question asked, answer given, and code value, all using named variables (rather than SGQA codes)

TMSWhite (reporter)
2011-06-16 14:12

Some have asked how to test the ExpressionManager. Here are the details:

(1) Apply patch_issue_05103_20110616a.patch (or merge in the - everything is in the /classes/eval/*, except fora one line change in /classes/dTexts/dTexts.php, plus a 3 line change in common_functions.php

(2) Load the ExpressionManager-plus-all-question-types.lss survey. shows screen shots of what it should look like.

(3) For lower-level testing, try
(a) http://localhost/limesurvey/classes/eval/Test_ExpressionManager_Tokenizer.php [^]
(d) http://localhost/limesurvey/classes/eval/Test_ExpressionManager_Evaluate.php [^]
(c) http://localhost/limesurvey/classes/eval/Test_ExpressionManager_ProcessStringContainingExpressions.php [^]

The screens hots and survey are in
The changed source is in
TMSWhite (reporter)
2011-06-17 08:28

Improved error reporting. Whenever there are expressions with syntax errors, ExpressionManager now highlights the whole expression, red-boxes the text that caused errors (like unknown variables or extra parentheses), and provides mouse-over ToolTips describing the errors.
TMSWhite (reporter)
2011-06-17 12:01

To the best of my knowledge, ExpressionManager is now fully operational, and integrated into LimeSurvey via this patch: issue_05268-20110617.patch (see also issue 05268)

Please test.
TMSWhite (reporter)
2011-06-17 12:29

For screen shots of ExpressionManager's new way of reporting syntax errors, see here: [^]
TMSWhite (reporter)
2011-06-18 00:32

Have now tested ExpressionManager integration into LimeSurvey for the following features:
(1) Development + deployed surveys
(2) Token management
(3) Template management
(4) Data entry screen
(5) Printable summary of responses given - passed this through templatereplace() so that can see the text as the respondent saw it, not as the survey-designer built it.

In the process, identified 1 small bug in ExpressionManager, and several bugs in other files (mostly lack of detection of undefined variables).

The only sections I have yet to test are ones that aren't built into any of my test surveys:
(1) Assessments
(2) Conditions

Please try the latest patch (issue_50268-20110617-v2.patch)
TMSWhite (reporter)
2011-06-19 18:11

I need to try some example surveys that have custom JavaScript to ensure that ExpressionManager processes them correctly.

Current, ExpressionManager first looks for strings (surrounded by single or double quotes), and then looks for tokens. So, tokens contained within strings are not parsed. Also, it looks for anything within curly braces, so it would think that JavaScript code is an Expression.

From the LimeSurvey docs ( [^]), there is this example:

Hello {TOKEN:FIRSTNAME}. We sent an email to you using this address {TOKEN:EMAIL}. Is this correct?
What do you as a {TOKEN:ATTRIBUTE_1} think about your
<script type="text/javascript" language="Javascript">;
    var job='{TOKEN:ATTRIBUTE_1}';
    if (job=='worker') {
       document.write ('bosses')
    } else {

ExpressionManager, as is, would think that '{TOKEN:ATTRIBUTE_1}' is a string, and would detect two syntax errors here:
    if (job=='worker') {
       document.write ('bosses')
    } else {

Some solutions may include:
(1) Conditionally parse expressions within strings
(2) Ignore curly braces with this pattern '{\s+\n.*?\s*}' - this would put the burden on the survey authors to not write JavaScript code like
if (job=='worker') { document.write('bosses') }
else { document.write('workers') }
This also might get a little tricky in detecting nested curly braces so that it matches the correct pair - so this should be an optional parsing style just for people wanting to use JavaScript overrides.
(3) Ignore anything between XML quotes (<!-- -->) - but that wouldn't allow substitution within JavaScript strings like '{TOKEN:ATTRIBUTE_1}' However, that might support recursive substitution without getting confused by JavaScript added as part of a substitution step.

TMSWhite (reporter)
2011-07-02 07:19

Fixed ExpressionManager so that it properly substitutes {TOKEN:ATTRIBUTE_1} above without throwing errors related to the JavaScript code
TMSWhite (reporter)
2011-07-04 09:36

ExpressionManager is now stable in the limesurvey_dev_tms branch

Use the following to test it:
(1) http://localhost/limesurvey_dev_tms/classes/eval/ExpressionManagerTestSuite.php [^]
(2) Load and test this survey: ExpressionManager-plus-all-question-types.lss
TMSWhite (reporter)
2011-07-11 23:22

Syntax changed slightly to so that JavaScript and CSS can be safely handled.

ExpressionManager will now only process expressions that are surrounded by curly braces with no leading or trailing white space. So:

{5 * 7} => 35
{ 5 * 7} => { 5 * 7}
{5 * 7 } => {5 * 7 }

There are a few places within qanda.php where JavaScript functions did not have any leading or trailing spaces (e.g. {document.getElementById()....}), but now adding a single space will keep them from being highlighted by ExpressionManager as having syntax errors.

This may require that people with custom JavaScript ensure that they have added such leading/trailing spaces, or just use line-feed to properly indent their code. I expect this will be the minority of users. There may be a way to detect such custom JavaScript at survey load or activation time.

To test this, try latest limesurvey_dev_tms revision (10481) using the RegressionTester-en-de.lss instrument
TMSWhite (reporter)
2011-07-24 07:29

This now works in revision 10579, with versions of tailoring and relevance calculations using much-improved in Javascript.syntax highlighting and tool-tipping.

It also supports real-time changes to question visibility and micro-tailoring on the current page without visibility.
TMSWhite (reporter)
2011-10-28 23:03

This is available in version 2.0alpha+

- Issue History
Date Modified Username Field Change
2011-04-11 20:37 TMSWhite New Issue
2011-04-19 20:36 TMSWhite Note Added: 14849
2011-05-07 11:58 c_schmitz Status new => acknowledged
2011-05-27 13:41 Mazi Assigned To => c_schmitz
2011-05-27 13:41 Mazi Status acknowledged => assigned
2011-05-27 13:42 Mazi Note Added: 15135
2011-05-27 15:53 TMSWhite Note Added: 15136
2011-05-27 20:21 TMSWhite Note Added: 15138
2011-06-10 00:24 TMSWhite Note Added: 15393
2011-06-10 08:27 TMSWhite Note Added: 15395
2011-06-10 08:28 TMSWhite File Added: limesurvey_survey_showing_conditional_tailoring_using_equation_parser.lss
2011-06-10 08:31 TMSWhite Note Added: 15396
2011-06-10 09:06 TMSWhite Note Added: 15398
2011-06-10 09:15 TMSWhite File Added: issue_05103.patch
2011-06-10 09:20 TMSWhite Note Added: 15399
2011-06-11 21:49 TMSWhite Note Added: 15411
2011-06-12 09:38 TMSWhite File Added: issue_05103-rev2.patch
2011-06-12 09:40 TMSWhite Note Added: 15412
2011-06-12 09:44 TMSWhite Note Edited: 15412 View Revisions
2011-06-12 09:44 TMSWhite File Added: limesurvey_survey_showing_conditional_tailoring_using_equation_parser-rev2.lss
2011-06-13 18:45 TMSWhite Note Added: 15419
2011-06-16 08:57 TMSWhite File Added: issue_05103-20110616.patch
2011-06-16 08:58 TMSWhite File Added: ExpressionManager-plus-all-question-types.lss
2011-06-16 09:03 TMSWhite Note Added: 15451
2011-06-16 09:45 TMSWhite File Added: issue_05103-20110616a.patch
2011-06-16 09:46 TMSWhite Note Edited: 15451 View Revisions
2011-06-16 14:12 TMSWhite Note Added: 15455
2011-06-16 14:12 TMSWhite File Added:
2011-06-16 14:12 TMSWhite File Added:
2011-06-17 08:28 TMSWhite Note Added: 15472
2011-06-17 12:00 TMSWhite File Added: issue_05268-20110617.patch
2011-06-17 12:01 TMSWhite Note Added: 15474
2011-06-17 12:29 TMSWhite Note Added: 15476
2011-06-18 00:32 TMSWhite Note Added: 15483
2011-06-18 00:35 TMSWhite File Added: issue_05268-20110617-v2.patch
2011-06-19 18:11 TMSWhite Note Added: 15509
2011-06-19 18:59 TMSWhite Relationship added related to 05288
2011-06-19 19:01 TMSWhite Relationship added related to 05269
2011-06-19 19:02 TMSWhite Relationship added related to 05268
2011-06-19 19:03 TMSWhite Relationship added related to 05104
2011-06-19 19:03 TMSWhite Relationship added related to 05279
2011-07-02 07:19 TMSWhite Note Added: 15614
2011-07-04 09:36 TMSWhite Note Added: 15626
2011-07-11 23:22 TMSWhite Note Added: 15731
2011-07-11 23:25 TMSWhite File Added: RegressionTester-en-de.lss
2011-07-12 03:58 TMSWhite Relationship added related to 04424
2011-07-24 07:29 TMSWhite Note Added: 15847
2011-10-28 23:03 TMSWhite Note Added: 16565
2011-10-28 23:03 TMSWhite Status assigned => resolved
2011-10-28 23:03 TMSWhite Fixed in Version => 2.00
2011-10-28 23:03 TMSWhite Resolution open => fixed
2011-10-28 23:03 TMSWhite Assigned To c_schmitz => TMSWhite
2012-06-21 13:22 c_schmitz Status resolved => closed

Copyright © 2000 - 2016 MantisBT Team
Powered by Mantis Bugtracker