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