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 BHttpResult::BHttpResult(BMessage* archive) 33 : 34 BUrlResult(archive), 35 fUrl(archive->FindString("http:url")), 36 fHeaders(), 37 fStatusCode(archive->FindInt32("http:statusCode")) 38 { 39 fStatusString = archive->FindString("http:statusString"); 40 41 BMessage headers; 42 archive->FindMessage("http:headers", &headers); 43 fHeaders.PopulateFromArchive(&headers); 44 } 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 size_t 90 BHttpResult::Length() const 91 { 92 const char* length = Headers()["Content-Length"]; 93 if (length == NULL) 94 return 0; 95 96 /* NOTE: Not RFC7230 compliant: 97 * - If Content-Length is a list, all values must be checked and verified 98 * to be duplicates of each other, but this is currently not supported. 99 */ 100 size_t result = 0; 101 /* strtoul() will ignore a prefixed sign, so we verify that there aren't 102 * any before continuing (RFC7230 only permits digits). 103 * 104 * We can check length[0] directly because header values are trimmed by 105 * HttpHeader beforehand. */ 106 if (length[0] != '-' && length[0] != '+') { 107 errno = 0; 108 char *endptr = NULL; 109 result = strtoul(length, &endptr, 10); 110 /* ERANGE will be signalled if the result is too large (which can 111 * happen), in that case, return 0. */ 112 if (errno != 0 || *endptr != '\0') 113 result = 0; 114 } 115 return result; 116 } 117 118 119 const BHttpHeaders& 120 BHttpResult::Headers() const 121 { 122 return fHeaders; 123 } 124 125 126 int32 127 BHttpResult::StatusCode() const 128 { 129 return fStatusCode; 130 } 131 132 133 const BString& 134 BHttpResult::StatusText() const 135 { 136 return fStatusString; 137 } 138 139 140 // #pragma mark Result tests 141 142 143 bool 144 BHttpResult::HasHeaders() const 145 { 146 return fHeaders.CountHeaders() > 0; 147 } 148 149 150 // #pragma mark Overloaded members 151 152 153 BHttpResult& 154 BHttpResult::operator=(const BHttpResult& other) 155 { 156 if (this == &other) 157 return *this; 158 159 fUrl = other.fUrl; 160 fHeaders = other.fHeaders; 161 fStatusCode = other.fStatusCode; 162 fStatusString = other.fStatusString; 163 164 return *this; 165 } 166 167 168 status_t 169 BHttpResult::Archive(BMessage* target, bool deep) const 170 { 171 status_t result = BUrlResult::Archive(target, deep); 172 if (result != B_OK) 173 return result; 174 175 target->AddString("http:url", fUrl); 176 target->AddInt32("http:statusCode", fStatusCode); 177 target->AddString("http:statusString", fStatusString); 178 179 BMessage headers; 180 fHeaders.Archive(&headers); 181 target->AddMessage("http:headers", &headers); 182 183 return B_OK; 184 } 185 186 187 /*static*/ BArchivable* 188 BHttpResult::Instantiate(BMessage* archive) 189 { 190 if (!validate_instantiation(archive, "BHttpResult")) 191 return NULL; 192 193 return new BHttpResult(archive); 194 } 195