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
15using namespace BPrivate::Network;
16
17
18BHttpResult::BHttpResult(const BUrl& url)
19	:
20	fUrl(url),
21	fHeaders(),
22	fStatusCode(0)
23{
24}
25
26
27BHttpResult::BHttpResult(const BHttpResult& other)
28	:
29	fUrl(other.fUrl),
30	fHeaders(other.fHeaders),
31	fStatusCode(other.fStatusCode),
32	fStatusString(other.fStatusString)
33{
34}
35
36
37BHttpResult::~BHttpResult()
38{
39}
40
41
42// #pragma mark Result parameters modifications
43
44
45void
46BHttpResult::SetUrl(const BUrl& url)
47{
48	fUrl = url;
49}
50
51
52// #pragma mark Result parameters access
53
54
55const BUrl&
56BHttpResult::Url() const
57{
58	return fUrl;
59}
60
61
62BString
63BHttpResult::ContentType() const
64{
65	return Headers()["Content-Type"];
66}
67
68
69off_t
70BHttpResult::Length() const
71{
72	const char* length = Headers()["Content-Length"];
73	if (length == NULL)
74		return 0;
75
76	/* NOTE: Not RFC7230 compliant:
77	 * - If Content-Length is a list, all values must be checked and verified
78	 *   to be duplicates of each other, but this is currently not supported.
79	 */
80	off_t result = 0;
81	/* strtoull() will ignore a prefixed sign, so we verify that there aren't
82	 * any before continuing (RFC7230 only permits digits).
83	 *
84	 * We can check length[0] directly because header values are trimmed by
85	 * HttpHeader beforehand. */
86	if (length[0] != '-' && length[0] != '+') {
87		errno = 0;
88		char *endptr = NULL;
89		result = strtoull(length, &endptr, 10);
90		/* ERANGE will be signalled if the result is too large (which can
91		 * happen), in that case, return 0. */
92		if (errno != 0 || *endptr != '\0')
93			result = 0;
94	}
95	return result;
96}
97
98
99const BHttpHeaders&
100BHttpResult::Headers() const
101{
102	return fHeaders;
103}
104
105
106int32
107BHttpResult::StatusCode() const
108{
109	return fStatusCode;
110}
111
112
113const BString&
114BHttpResult::StatusText() const
115{
116	return fStatusString;
117}
118
119
120// #pragma mark Result tests
121
122
123bool
124BHttpResult::HasHeaders() const
125{
126	return fHeaders.CountHeaders() > 0;
127}
128
129
130// #pragma mark Overloaded members
131
132
133BHttpResult&
134BHttpResult::operator=(const BHttpResult& other)
135{
136	if (this == &other)
137		return *this;
138
139	fUrl = other.fUrl;
140	fHeaders = other.fHeaders;
141	fStatusCode = other.fStatusCode;
142	fStatusString = other.fStatusString;
143
144	return *this;
145}
146