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