Coverage Report

Created: 2026-02-09 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wt/src/Wt/Http/Response.C
Line
Count
Source
1
/*
2
 * Copyright (C) 2009 Emweb bv, Herent, Belgium.
3
 *
4
 * See the LICENSE file for terms of use.
5
 */
6
7
#include "Wt/Http/Response.h"
8
#include "Wt/Http/ResponseContinuation.h"
9
#include "Wt/WResource.h"
10
#include "Wt/WStringStream.h"
11
#include "WebRequest.h"
12
#include "WebUtils.h"
13
14
#include <mutex>
15
16
namespace Wt {
17
  namespace Http {
18
19
void Response::setStatus(int status)
20
0
{
21
0
  if (response_)
22
0
    response_->setStatus(status);
23
0
}
24
25
void Response::setContentLength(::uint64_t length)
26
0
{
27
0
  if (response_)
28
0
    response_->setContentLength(length);
29
0
}
30
31
void Response::setMimeType(const std::string& mimeType)
32
0
{
33
0
  if (response_)
34
0
    response_->setContentType(mimeType);
35
0
}
36
37
void Response::addHeader(const std::string& name, const std::string& value)
38
0
{
39
0
  if (response_)
40
0
    response_->addHeader(name, value);
41
0
}
42
43
void Response::insertHeader(const std::string& name, const std::string& value)
44
0
{
45
0
  if (response_)
46
0
    response_->insertHeader(name, value);
47
0
}
48
49
ResponseContinuation *Response::createContinuation()
50
0
{
51
0
  if (!continuation_) {
52
0
    ResponseContinuation *c = new ResponseContinuation(resource_, response_);
53
0
    continuation_ = resource_->addContinuation(c);
54
0
  } else {
55
0
#ifdef WT_THREADED
56
0
    std::unique_lock<std::recursive_mutex> lock(*resource_->mutex_);
57
0
#endif
58
0
    continuation_->resource_ = resource_;
59
0
  }
60
61
0
  return continuation_.get();
62
0
}
63
64
ResponseContinuation *Response::continuation() const
65
0
{
66
0
  if (continuation_ && continuation_->resource_)
67
0
    return continuation_.get();
68
0
  else
69
0
    return nullptr;
70
0
}
71
72
WT_BOSTREAM& Response::out()
73
0
{
74
0
  if (!headersCommitted_) {
75
0
    if (response_ &&
76
0
        !continuation_ &&
77
0
        (resource_->dispositionType() != ContentDisposition::None
78
0
         || !resource_->suggestedFileName().empty())) {
79
0
      WStringStream cdp;
80
81
0
      switch (resource_->dispositionType()) {
82
0
      default:
83
0
      case ContentDisposition::Inline:
84
0
        cdp << "inline";
85
0
        break;
86
0
      case ContentDisposition::Attachment:
87
0
        cdp << "attachment";
88
0
        break;
89
0
      }
90
91
0
      const WString& fileName = resource_->suggestedFileName();
92
93
0
      if (!fileName.empty()) {
94
0
        if (resource_->dispositionType() == ContentDisposition::None) {
95
          // backward compatibility-ish with older Wt versions
96
0
          cdp.clear();
97
0
          cdp << "attachment";
98
0
        }
99
100
        // Browser incompatibility hell: internatianalized filename suggestions
101
        // First filename is for browsers that don't support RFC 5987
102
        // Second filename is for browsers that do support RFC 5987
103
0
        cdp << ';';
104
105
        // We cannot query wApp here, because wApp doesn't exist for
106
        // static resources.
107
0
        const char *ua = response_->userAgent();
108
0
        bool isIE = ua && strstr(ua, "MSIE") != nullptr;
109
0
        bool isChrome = ua && strstr(ua, "Chrome") != nullptr;
110
111
0
        if (isIE || isChrome) {
112
          // filename="foo-%c3%a4-%e2%82%ac.html"
113
          // Note: IE never converts %20 back to space, so avoid escaping
114
          // IE wil also not url decode the filename if the file has no ASCII
115
          // extension (e.g. .txt)
116
0
          cdp << "filename=\""
117
0
              << Utils::urlEncode(fileName.toUTF8(), " ")
118
0
              << "\";";
119
0
        } else {
120
          // Binary UTF-8 sequence: for FF3, Safari, Chrome, Chrome9
121
0
          cdp << "filename=\"" << fileName.toUTF8() << "\";";
122
0
        }
123
        // Next will be picked by RFC 5987 in favour of the
124
        // one without specified encoding (Chrome9,
125
0
        cdp << Utils::EncodeHttpHeaderField("filename", fileName);
126
0
        addHeader("Content-Disposition", cdp.str());
127
0
      } else {
128
0
        addHeader("Content-Disposition", cdp.str());
129
0
      }
130
0
    }
131
132
0
    headersCommitted_ = true;
133
0
  }
134
135
0
  if (out_)
136
0
    return *out_;
137
0
  else
138
0
    return response_->out();
139
0
}
140
141
std::string Response::nonce() const
142
0
{
143
0
  return response_ ? response_->nonce() : std::string();
144
0
}
145
146
Response::Response(WResource *resource, WebResponse *response,
147
                   ResponseContinuationPtr continuation)
148
0
  : resource_(resource),
149
0
    response_(response),
150
0
    continuation_(continuation),
151
0
    out_(nullptr),
152
0
    headersCommitted_(false)
153
0
{ }
154
155
Response::Response(WResource *resource, WT_BOSTREAM& out)
156
0
  : resource_(resource),
157
0
    response_(nullptr),
158
0
    out_(&out),
159
0
    headersCommitted_(false)
160
0
{ }
161
162
  }
163
}