Example #1
0
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;
}
Example #2
0
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();
}