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