xref: /haiku/src/kits/network/libnetservices/HttpResult.cpp (revision d0834b34d523dff018ef0551e195fd9109daa93f)
1 /*
2  * Copyright 2010-2017 Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Christophe Huriaux, c.huriaux@gmail.com
7  *		Adrien Destugues, pulkomandy@pulkomandy.tk
8  */
9 
10 #include <HttpResult.h>
11 
12 #include <errno.h>
13 #include <Debug.h>
14 
15 
16 using std::ostream;
17 
18 #ifndef LIBNETAPI_DEPRECATED
19 using namespace BPrivate::Network;
20 #endif
21 
22 
23 BHttpResult::BHttpResult(const BUrl& url)
24 	:
25 	fUrl(url),
26 	fHeaders(),
27 	fStatusCode(0)
28 {
29 }
30 
31 
32 #ifdef LIBNETAPI_DEPRECATED
33 BHttpResult::BHttpResult(BMessage* archive)
34 	:
35 	BUrlResult(archive),
36 	fUrl(archive->FindString("http:url")),
37 	fHeaders(),
38 	fStatusCode(archive->FindInt32("http:statusCode"))
39 {
40 	fStatusString = archive->FindString("http:statusString");
41 
42 	BMessage headers;
43 	archive->FindMessage("http:headers", &headers);
44 	fHeaders.PopulateFromArchive(&headers);
45 }
46 #endif
47 
48 
49 BHttpResult::BHttpResult(const BHttpResult& other)
50 	:
51 	fUrl(other.fUrl),
52 	fHeaders(other.fHeaders),
53 	fStatusCode(other.fStatusCode),
54 	fStatusString(other.fStatusString)
55 {
56 }
57 
58 
59 BHttpResult::~BHttpResult()
60 {
61 }
62 
63 
64 // #pragma mark Result parameters modifications
65 
66 
67 void
68 BHttpResult::SetUrl(const BUrl& url)
69 {
70 	fUrl = url;
71 }
72 
73 
74 // #pragma mark Result parameters access
75 
76 
77 const BUrl&
78 BHttpResult::Url() const
79 {
80 	return fUrl;
81 }
82 
83 
84 BString
85 BHttpResult::ContentType() const
86 {
87 	return Headers()["Content-Type"];
88 }
89 
90 
91 #ifdef LIBNETAPI_DEPRECATED
92 size_t
93 BHttpResult::Length() const
94 {
95 	const char* length = Headers()["Content-Length"];
96 	if (length == NULL)
97 		return 0;
98 
99 	/* NOTE: Not RFC7230 compliant:
100 	 * - If Content-Length is a list, all values must be checked and verified
101 	 *   to be duplicates of each other, but this is currently not supported.
102 	 */
103 	size_t result = 0;
104 	/* strtoul() will ignore a prefixed sign, so we verify that there aren't
105 	 * any before continuing (RFC7230 only permits digits).
106 	 *
107 	 * We can check length[0] directly because header values are trimmed by
108 	 * HttpHeader beforehand. */
109 	if (length[0] != '-' && length[0] != '+') {
110 		errno = 0;
111 		char *endptr = NULL;
112 		result = strtoul(length, &endptr, 10);
113 		/* ERANGE will be signalled if the result is too large (which can
114 		 * happen), in that case, return 0. */
115 		if (errno != 0 || *endptr != '\0')
116 			result = 0;
117 	}
118 	return result;
119 }
120 
121 #else
122 
123 off_t
124 BHttpResult::Length() const
125 {
126 	const char* length = Headers()["Content-Length"];
127 	if (length == NULL)
128 		return 0;
129 
130 	/* NOTE: Not RFC7230 compliant:
131 	 * - If Content-Length is a list, all values must be checked and verified
132 	 *   to be duplicates of each other, but this is currently not supported.
133 	 */
134 	off_t result = 0;
135 	/* strtoull() will ignore a prefixed sign, so we verify that there aren't
136 	 * any before continuing (RFC7230 only permits digits).
137 	 *
138 	 * We can check length[0] directly because header values are trimmed by
139 	 * HttpHeader beforehand. */
140 	if (length[0] != '-' && length[0] != '+') {
141 		errno = 0;
142 		char *endptr = NULL;
143 		result = strtoull(length, &endptr, 10);
144 		/* ERANGE will be signalled if the result is too large (which can
145 		 * happen), in that case, return 0. */
146 		if (errno != 0 || *endptr != '\0')
147 			result = 0;
148 	}
149 	return result;
150 }
151 #endif // BNETAPI_DEPRECATED
152 
153 
154 const BHttpHeaders&
155 BHttpResult::Headers() const
156 {
157 	return fHeaders;
158 }
159 
160 
161 int32
162 BHttpResult::StatusCode() const
163 {
164 	return fStatusCode;
165 }
166 
167 
168 const BString&
169 BHttpResult::StatusText() const
170 {
171 	return fStatusString;
172 }
173 
174 
175 // #pragma mark Result tests
176 
177 
178 bool
179 BHttpResult::HasHeaders() const
180 {
181 	return fHeaders.CountHeaders() > 0;
182 }
183 
184 
185 // #pragma mark Overloaded members
186 
187 
188 BHttpResult&
189 BHttpResult::operator=(const BHttpResult& other)
190 {
191 	if (this == &other)
192 		return *this;
193 
194 	fUrl = other.fUrl;
195 	fHeaders = other.fHeaders;
196 	fStatusCode = other.fStatusCode;
197 	fStatusString = other.fStatusString;
198 
199 	return *this;
200 }
201 
202 
203 #ifdef LIBNETAPI_DEPRECATED
204 status_t
205 BHttpResult::Archive(BMessage* target, bool deep) const
206 {
207 	status_t result = BUrlResult::Archive(target, deep);
208 	if (result != B_OK)
209 		return result;
210 
211 	target->AddString("http:url", fUrl);
212 	target->AddInt32("http:statusCode", fStatusCode);
213 	target->AddString("http:statusString", fStatusString);
214 
215 	BMessage headers;
216 	fHeaders.Archive(&headers);
217 	target->AddMessage("http:headers", &headers);
218 
219 	return B_OK;
220 }
221 
222 
223 /*static*/ BArchivable*
224 BHttpResult::Instantiate(BMessage* archive)
225 {
226 	if (!validate_instantiation(archive, "BHttpResult"))
227 		return NULL;
228 
229 	return new BHttpResult(archive);
230 }
231 #endif
232