bool isValidVariableName(const String& name) { if (name.isEmpty()) return false; if (!isValidFirstVariableNameCharacter(name[0])) return false; unsigned length = name.length(); for (unsigned i = 1; i < length; ++i) { if (!isValidVariableNameCharacter(name[i])) return false; } return true; }
bool containsVariableReference(const String& text, bool& isValid) { isValid = true; bool foundReference = false; bool finished = false; int currentPosition = 0; const UChar* characters = text.characters(); while (!finished) { // Find beginning of variable reference int referenceStartPosition = text.find('$', currentPosition); if (referenceStartPosition == -1) { finished = true; break; } foundReference = true; int nameStartPosition = referenceStartPosition + 1; int nameEndPosition = -1; if (characters[nameStartPosition] == '(') { // If the input string contains an open brace, a close brace must exist as well nameEndPosition = text.find(')', nameStartPosition + 1); if (nameEndPosition == -1) { finished = true; isValid = false; break; } ++nameStartPosition; } else { int length = text.length(); for (nameEndPosition = nameStartPosition; nameEndPosition < length; ++nameEndPosition) { if (!isValidVariableNameCharacter(text[nameEndPosition])) break; } } if (nameEndPosition < nameStartPosition) { finished = true; isValid = false; break; } // Eventually split of conversion string, and check its syntax afterwards String conversionString; String variableName = text.substring(nameStartPosition, nameEndPosition - nameStartPosition); int conversionStringStart = variableName.find(':'); if (conversionStringStart != -1) { conversionString = variableName.substring(conversionStringStart + 1, variableName.length() - (conversionStringStart + 1)); variableName = variableName.left(conversionStringStart); } isValid = isValidVariableName(variableName); if (!isValid) { finished = true; break; } if (!conversionString.isEmpty()) { isValid = isValidVariableName(conversionString); if (!isValid) { finished = true; break; } WMLVariableEscapingMode escapeMode = WMLVariableEscapingNone; isValid = isValidVariableEscapingModeString(conversionString, escapeMode); if (!isValid) { finished = true; break; } } currentPosition = nameEndPosition; } return foundReference; }
String substituteVariableReferences(const String& reference, Document* document, WMLVariableEscapingMode escapeMode) { ASSERT(document); if (reference.isEmpty()) return reference; WMLPageState* pageState = wmlPageStateForDocument(document); if (!pageState) return reference; bool isValid = true; String remainingInput = reference; String result; while (!remainingInput.isEmpty()) { ASSERT(isValid); int start = remainingInput.find("$"); if (start == -1) { // Consume all remaining characters, as there's nothing more to substitute result += remainingInput; break; } // Consume all characters until the variable reference beginning result += remainingInput.left(start); remainingInput.remove(0, start); // Transform adjacent dollar signs into a single dollar sign as string literal if (remainingInput[1] == '$') { result += "$"; remainingInput.remove(0, 2); continue; } String variableName; String conversionMode; if (remainingInput[1] == '(') { int referenceEndPosition = remainingInput.find(")"); if (referenceEndPosition == -1) { isValid = false; break; } variableName = remainingInput.substring(2, referenceEndPosition - 2); remainingInput.remove(0, referenceEndPosition + 1); // Determine variable conversion mode string int pos = variableName.find(':'); if (pos != -1) { conversionMode = variableName.substring(pos + 1, variableName.length() - (pos + 1)); variableName = variableName.left(pos); } } else { int length = remainingInput.length(); int referenceEndPosition = 1; for (; referenceEndPosition < length; ++referenceEndPosition) { if (!isValidVariableNameCharacter(remainingInput[referenceEndPosition])) break; } variableName = remainingInput.substring(1, referenceEndPosition - 1); remainingInput.remove(0, referenceEndPosition); } isValid = isValidVariableName(variableName); if (!isValid) break; ASSERT(!variableName.isEmpty()); String variableValue = pageState->getVariable(variableName); if (variableValue.isEmpty()) continue; if (containsVariableReference(variableValue, isValid)) { if (!isValid) break; variableValue = substituteVariableReferences(variableValue, document, escapeMode); continue; } if (!conversionMode.isEmpty()) { // Override default escape mode, if desired WMLVariableEscapingMode specifiedEscapeMode = WMLVariableEscapingNone; if ((isValid = isValidVariableEscapingModeString(conversionMode, specifiedEscapeMode))) escapeMode = specifiedEscapeMode; if (!isValid) break; } switch (escapeMode) { case WMLVariableEscapingNone: break; case WMLVariableEscapingEscape: variableValue = encodeWithURLEscapeSequences(variableValue); break; case WMLVariableEscapingUnescape: variableValue = decodeURLEscapeSequences(variableValue); break; } result += variableValue; ASSERT(isValid); } if (!isValid) { reportWMLError(document, WMLErrorInvalidVariableReference); return reference; } return result; }