void EncodeRefs(WString& text, WFlags<RefEncoderOption> options) { if (text.empty()) return; std::string result = "<span>" + text.toUTF8() + "</span>"; char *ctext = const_cast<char *>(result.c_str()); // Shhht it's okay ! WApplication *app = WApplication::instance(); try { xml_document<> doc; doc.parse<parse_comment_nodes | parse_validate_closing_tags | parse_validate_utf8 | parse_xhtml_entity_translation>(ctext); EncodeRefs(doc.first_node(), app, options); WStringStream out; print(out.back_inserter(), *doc.first_node(), print_no_indenting); result = out.str(); } catch (parse_error& e) { LOG_ERROR("Error reading XHTML string: " << e.what()); return; } if (result.length() < 13) result.clear(); else result = result.substr(6, result.length() - 13); text = WString::fromUTF8(result); }
std::string WTemplate::encode(const std::string& text) const { WApplication *app = WApplication::instance(); if (app && (encodeInternalPaths_ || app->session()->hasSessionIdInUrl())) { WFlags<RefEncoderOption> options; if (encodeInternalPaths_) options |= EncodeInternalPaths; if (app->session()->hasSessionIdInUrl()) options |= EncodeRedirectTrampoline; return EncodeRefs(WString::fromUTF8(text), options).toUTF8(); } else return text; }
std::string WText::formattedText() const { if (text_.format == PlainText) return escapeText(text_.text, true).toUTF8(); else { WApplication *app = WApplication::instance(); if (flags_.test(BIT_ENCODE_INTERNAL_PATHS) || app->session()->hasSessionIdInUrl()) { WFlags<RefEncoderOption> options; if (flags_.test(BIT_ENCODE_INTERNAL_PATHS)) options |= EncodeInternalPaths; if (app->session()->hasSessionIdInUrl()) options |= EncodeRedirectTrampoline; return EncodeRefs(text_.text, options).toUTF8(); } else return text_.text.toUTF8(); } }
void WTemplate::renderTemplateText(std::ostream& result, const WString& templateText) { std::string text; WApplication *app = WApplication::instance(); if (app && (encodeInternalPaths_ || app->session()->hasSessionIdInUrl())) { WFlags<RefEncoderOption> options; if (encodeInternalPaths_) options |= EncodeInternalPaths; if (app->session()->hasSessionIdInUrl()) options |= EncodeRedirectTrampoline; WString t = templateText; EncodeRefs(t, options); text = t.toUTF8(); } else text = templateText.toUTF8(); std::size_t lastPos = 0; std::vector<WString> args; std::vector<std::string> conditions; int suppressing = 0; for (std::size_t pos = text.find('$'); pos != std::string::npos; pos = text.find('$', pos)) { if (!suppressing) result << text.substr(lastPos, pos - lastPos); lastPos = pos; if (pos + 1 < text.length()) { if (text[pos + 1] == '$') { // $$ -> $ if (!suppressing) result << '$'; lastPos += 2; } else if (text[pos + 1] == '{') { std::size_t startName = pos + 2; std::size_t endName = text.find_first_of(" \r\n\t}", startName); args.clear(); std::size_t endVar = parseArgs(text, endName, args); if (endVar == std::string::npos) { LOG_ERROR("variable syntax error near \"" << text.substr(pos) << "\""); return; } std::string name = text.substr(startName, endName - startName); std::size_t nl = name.length(); if (nl > 2 && name[0] == '<' && name[nl - 1] == '>') { if (name[1] != '/') { std::string cond = name.substr(1, nl - 2); conditions.push_back(cond); if (suppressing || !conditionValue(cond)) ++suppressing; } else { std::string cond = name.substr(2, nl - 3); if (conditions.back() != cond) { LOG_ERROR("mismatching condition block end: " << cond); return; } conditions.pop_back(); if (suppressing) --suppressing; } } else { if (!suppressing) { std::size_t colonPos = name.find(':'); bool handled = false; if (colonPos != std::string::npos) { std::string fname = name.substr(0, colonPos); std::string arg0 = name.substr(colonPos + 1); args.insert(args.begin(), WString::fromUTF8(arg0)); if (resolveFunction(fname, args, result)) handled = true; else args.erase(args.begin()); } if (!handled) resolveString(name, args, result); } } lastPos = endVar + 1; } else { if (!suppressing) result << '$'; // $. -> $. lastPos += 1; } } else { if (!suppressing) result << '$'; // $ at end of template -> $ lastPos += 1; } pos = lastPos; } result << text.substr(lastPos); }
void EncodeRefs(xml_node<> *x_node, WApplication *app, WFlags<RefEncoderOption> options) { xml_document<> *doc = x_node->document(); if (strcmp(x_node->name(), "a") == 0) { xml_attribute<> *x_href = x_node->first_attribute("href"); if (x_href) { std::string path = x_href->value(); if ((options & EncodeInternalPaths) && path.length() >= 2 && path.substr(0, 2) == "#/") { path = path.substr(1); std::string addClass, url; if (app->environment().ajax()) { url = app->bookmarkUrl(path); const char *name = "onclick"; char *value = doc->allocate_string ((WT_CLASS".navigateInternalPath(event, " + WWebWidget::jsStringLiteral(path) + ");").c_str()); xml_attribute<> *x_click = doc->allocate_attribute(name, value); x_node->insert_attribute(0, x_click); addClass = "Wt-rr"; } else { if (app->environment().agentIsSpiderBot()) url = app->bookmarkUrl(path); else url = app->session()->mostRelativeUrl(path); addClass = "Wt-ip"; } xml_attribute<> *x_class = x_node->first_attribute("class"); std::string styleClass = x_class ? x_class->value() : std::string(); styleClass = Utils::addWord(styleClass, addClass); if (x_class) x_class->value(doc->allocate_string(styleClass.c_str())); else { x_class = doc->allocate_attribute ("class", doc->allocate_string(styleClass.c_str())); x_node->insert_attribute(0, x_class); } x_href->value (doc->allocate_string(app->resolveRelativeUrl(url).c_str())); } else if (options & EncodeRedirectTrampoline) { if (path.find("://") != std::string::npos || boost::starts_with(path, "//")) { path = app->encodeUntrustedUrl(path); x_href->value(doc->allocate_string(path.c_str())); } } } } if (options & EncodeRedirectTrampoline) { xml_attribute<> *x_style = x_node->first_attribute("style"); if (x_style) { std::string style = x_style->value(); if (style.find("//") != std::string::npos) { style = replaceUrlInStyle(style, app); x_style->value(doc->allocate_string(style.c_str())); } } if (strcmp(x_node->name(), "img") == 0) { xml_attribute<> *x_scr = x_node->first_attribute("src"); if (x_scr) { std::string path = x_scr->value(); if (path.find("://") != std::string::npos || boost::starts_with(path, "//")) { path = app->encodeUntrustedUrl(path); x_scr->value(doc->allocate_string(path.c_str())); } } } } for (xml_node<> *x_child = x_node->first_node(); x_child; x_child = x_child->next_sibling()) EncodeRefs(x_child, app, options); if (!x_node->first_node() && x_node->value_size() == 0 && !DomElement::isSelfClosingTag(x_node->name())) { // We need to add an emtpy data node since <div /> is illegal HTML // (but valid XML / XHTML) xml_node<> *empty = x_node->document()->allocate_node(node_data, 0, 0, 0, 0); x_node->append_node(empty); } }