std::size_t WTemplate::parseArgs(const std::string& text, std::size_t pos, std::vector<WString>& result) { std::size_t Error = std::string::npos; if (pos == std::string::npos) return Error; enum { Next, Name, Value, SValue, DValue } state = Next; WStringStream v; for (; pos < text.length(); ++pos) { char c = text[pos]; switch (state) { case Next: if (!std::isspace(c)) { if (c == '}') return pos; else if (std::isalpha(c) || c == '_') { state = Name; v.clear(); v << c; } else if (c == '\'') { state = SValue; v.clear(); } else if (c == '"') { state = DValue; v.clear(); } else return Error; } break; case Name: if (c == '=') { state = Value; v << '='; } else if (std::isspace(c)) { result.push_back(WString::fromUTF8(v.str())); state = Next; } else if (c == '}') { result.push_back(WString::fromUTF8(v.str())); return pos; } else if (std::isalnum(c) || c == '_' || c == '-') v << c; else return Error; break; case Value: if (c == '\'') state = SValue; else if (c == '"') state = DValue; else return Error; break; case SValue: case DValue: char quote = state == SValue ? '\'' : '"'; std::size_t end = text.find(quote, pos); if (end == std::string::npos) return Error; if (text[end - 1] == '\\') v << text.substr(pos, end - pos - 1) << quote; else { v << text.substr(pos, end - pos); result.push_back(WString::fromUTF8(v.str())); state = Next; } pos = end; } } return pos == text.length() ? std::string::npos : pos; }
WT_BOSTREAM& Response::out() { if (!headersCommitted_) { if (response_ && !continuation_ && (resource_->dispositionType() != ContentDisposition::None || !resource_->suggestedFileName().empty())) { WStringStream cdp; switch (resource_->dispositionType()) { default: case ContentDisposition::Inline: cdp << "inline"; break; case ContentDisposition::Attachment: cdp << "attachment"; break; } const WString& fileName = resource_->suggestedFileName(); if (!fileName.empty()) { if (resource_->dispositionType() == ContentDisposition::None) { // backward compatibility-ish with older Wt versions cdp.clear(); cdp << "attachment"; } // Browser incompatibility hell: internatianalized filename suggestions // First filename is for browsers that don't support RFC 5987 // Second filename is for browsers that do support RFC 5987 cdp << ';'; // We cannot query wApp here, because wApp doesn't exist for // static resources. const char *ua = response_->userAgent(); bool isIE = ua && strstr(ua, "MSIE") != nullptr; bool isChrome = ua && strstr(ua, "Chrome") != nullptr; if (isIE || isChrome) { // filename="foo-%c3%a4-%e2%82%ac.html" // Note: IE never converts %20 back to space, so avoid escaping // IE wil also not url decode the filename if the file has no ASCII // extension (e.g. .txt) cdp << "filename=\"" << Utils::urlEncode(fileName.toUTF8(), " ") << "\";"; } else { // Binary UTF-8 sequence: for FF3, Safari, Chrome, Chrome9 cdp << "filename=\"" << fileName.toUTF8() << "\";"; } // Next will be picked by RFC 5987 in favour of the // one without specified encoding (Chrome9, cdp << Utils::EncodeHttpHeaderField("filename", fileName); addHeader("Content-Disposition", cdp.str()); } else { addHeader("Content-Disposition", cdp.str()); } } headersCommitted_ = true; } if (out_) return *out_; else return response_->out(); }