Patch done by Christophe Huriaux as part of GSoC 2010 "Services Kit" project:

Integrated the classes in the Network Kit (libbnetapi.so). Only the foundation
classed BUrl, BUrlContext, BNetworkCookie, BNetworkCookieJar and the private
HttpTime code is currently compiled. The BUrlProtocol currently contains some
misplaced BUrlProtocolHttp specific stuff, and the HTTP stuff itself has a
dependency on libcrypto and should live in an add-on instead. I've sprinkled
some TODOs in the code, and I've done some renaming compared to the last
version of the GSoC patch. Any help to bring this further along is appreciated.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39161 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2010-10-27 14:03:31 +00:00
parent 1294543de9
commit 45939109b4
34 changed files with 7746 additions and 1 deletions
+94
View File
@@ -0,0 +1,94 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_HTTP_AUTHENTICATION_H_
#define _B_HTTP_AUTHENTICATION_H_
#include <Url.h>
#include <String.h>
// HTTP authentication method
enum BHttpAuthenticationMethod {
B_HTTP_AUTHENTICATION_NONE = 0,
// No authentication
B_HTTP_AUTHENTICATION_BASIC = 1,
// Basic base64 authentication method (unsecure)
B_HTTP_AUTHENTICATION_DIGEST = 2,
// Digest authentication
B_HTTP_AUTHENTICATION_IE_DIGEST = 4
// Slightly modified digest authentication to mimic old IE one
};
enum BHttpAuthenticationAlgorithm {
B_HTTP_AUTHENTICATION_ALGORITHM_NONE,
B_HTTP_AUTHENTICATION_ALGORITHM_MD5,
B_HTTP_AUTHENTICATION_ALGORITHM_MD5_SESS
};
enum BHttpAuthenticationQop {
B_HTTP_QOP_NONE,
B_HTTP_QOP_AUTH,
B_HTTP_QOP_AUTHINT
};
class BHttpAuthentication {
public:
BHttpAuthentication();
BHttpAuthentication(const BString& username,
const BString& password);
// Field modification
void SetUserName(const BString& username);
void SetPassword(const BString& password);
void SetMethod(
BHttpAuthenticationMethod type);
status_t Initialize(const BString& wwwAuthenticate);
// Field access
const BString& UserName() const;
const BString& Password() const;
BHttpAuthenticationMethod Method() const;
BString Authorization(const BUrl& url,
const BString& method) const;
// Base64 encoding
// TODO: Move to a common place. We may have multiple implementations
// in the Haiku tree...
static BString Base64Encode(const BString& string);
static BString Base64Decode(const BString& string);
private:
BString _DigestResponse(const BString& uri,
const BString& method) const;
// TODO: Rename these? _H seems to return a hash value,
// _KD returns a hash value of the "data" prepended by
// the "secret" string...
BString _H(const BString& value) const;
BString _KD(const BString& secret,
const BString& data) const;
private:
BHttpAuthenticationMethod fAuthenticationMethod;
BString fUserName;
BString fPassword;
BString fRealm;
BString fDigestNonce;
mutable BString fDigestCnonce;
mutable int fDigestNc;
BString fDigestOpaque;
bool fDigestStale;
BHttpAuthenticationAlgorithm fDigestAlgorithm;
BHttpAuthenticationQop fDigestQop;
BString fAuthorizationString;
};
#endif // _B_HTTP_AUTHENTICATION_H_
+192
View File
@@ -0,0 +1,192 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_HTTP_FORM_H_
#define _B_HTTP_FORM_H_
#include <Path.h>
#include <String.h>
#include <map>
enum form_type {
B_HTTP_FORM_URL_ENCODED,
B_HTTP_FORM_MULTIPART
};
enum form_content_type {
B_HTTPFORM_UNKNOWN,
B_HTTPFORM_STRING,
B_HTTPFORM_FILE,
B_HTTPFORM_BUFFER
};
class BHttpFormData {
private:
// Empty constructor is only kept for compatibility with map<>::operator[],
// but never used (see BHttpForm::operator[] which does the necessary
// check up)
BHttpFormData();
friend class std::map<BString, BHttpFormData>;
public:
BHttpFormData(const BString& name,
const BString& value);
BHttpFormData(const BString& name,
const BPath& file);
BHttpFormData(const BString& name,
const void* buffer, ssize_t size);
BHttpFormData(const BHttpFormData& other);
~BHttpFormData();
// Retrieve data informations
bool InitCheck() const;
const BString& Name() const;
const BString& String() const;
const BPath& File() const;
const void* Buffer() const;
ssize_t BufferSize() const;
bool IsFile() const;
const BString& Filename() const;
const BString& MimeType() const;
form_content_type Type() const;
// Change behavior
status_t MarkAsFile(const BString& filename,
const BString& mimeType);
status_t MarkAsFile(const BString& filename);
void UnmarkAsFile();
status_t CopyBuffer();
// Overloaded operators
BHttpFormData& operator=(const BHttpFormData& other);
private:
form_content_type fDataType;
bool fCopiedBuffer;
bool fFileMark;
BString fName;
BString fStringValue;
BPath fPathValue;
const void* fBufferValue;
ssize_t fBufferSize;
BString fFilename;
BString fMimeType;
};
class BHttpForm {
public:
// Nested types
class Iterator;
typedef std::map<BString, BHttpFormData> FormStorage;
public:
BHttpForm();
BHttpForm(const BHttpForm& other);
BHttpForm(const BString& formString);
~BHttpForm();
// Form string parsing
void ParseString(const BString& formString);
BString RawData() const;
// Form add
status_t AddString(const BString& name,
const BString& value);
status_t AddInt(const BString& name, int32 value);
status_t AddFile(const BString& fieldName,
const BPath& file);
status_t AddBuffer(const BString& fieldName,
const void* buffer, ssize_t size);
status_t AddBufferCopy(const BString& fieldName,
const void* buffer, ssize_t size);
// Mark a field as a filename
void MarkAsFile(const BString& fieldName,
const BString& filename,
const BString& mimeType);
void MarkAsFile(const BString& fieldName,
const BString& filename);
void UnmarkAsFile(const BString& fieldName);
// Change form type
void SetFormType(form_type type);
// Form test
bool HasField(const BString& name) const;
// Form retrieve
BString GetMultipartHeader(const BString& fieldName)
const;
form_content_type GetType(const BString& fieldname) const;
// Form informations
form_type GetFormType() const;
const BString& GetMultipartBoundary() const;
BString GetMultipartFooter() const;
ssize_t ContentLength() const;
// Form iterator
Iterator GetIterator();
// Form clear
void Clear();
// Overloaded operators
BHttpFormData& operator[](const BString& name);
private:
void _ExtractNameValuePair(const BString& string,
int32* index);
void _GenerateMultipartBoundary();
BString _GetMultipartHeader(
const BHttpFormData* element) const;
form_content_type _GetType(FormStorage::const_iterator it) const;
void _Erase(FormStorage::iterator it);
private:
friend class Iterator;
FormStorage fFields;
form_type fType;
BString fMultipartBoundary;
};
class BHttpForm::Iterator {
public:
Iterator(const Iterator& other);
BHttpFormData* Next();
bool HasNext() const;
void Remove();
BString MultipartHeader();
Iterator& operator=(const Iterator& other);
private:
Iterator(BHttpForm* form);
void _FindNext();
private:
friend class BHttpForm;
BHttpForm* fForm;
BHttpForm::FormStorage::iterator
fStdIterator;
BHttpFormData* fElement;
BHttpFormData* fPrevElement;
};
#endif // _B_HTTP_FORM_H_
+84
View File
@@ -0,0 +1,84 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_HTTP_HEADERS_H_
#define _B_HTTP_HEADERS_H_
#include <List.h>
#include <String.h>
class BHttpHeader {
public:
BHttpHeader();
BHttpHeader(const char* string);
BHttpHeader(const char* name,
const char* value);
BHttpHeader(const BHttpHeader& copy);
// Header data modification
void SetName(const char* name);
void SetValue(const char* value);
bool SetHeader(const char* string);
// Header data access
const char* Name() const;
const char* Value() const;
const char* Header() const;
// Header data test
bool NameIs(const char* name) const;
// Overloaded members
BHttpHeader& operator=(const BHttpHeader& other);
private:
BString fName;
BString fValue;
mutable BString fRawHeader;
mutable bool fRawHeaderValid;
};
class BHttpHeaders {
public:
BHttpHeaders();
BHttpHeaders(const BHttpHeaders& copy);
~BHttpHeaders();
// Header list access
const char* HeaderValue(const char* name) const;
BHttpHeader& HeaderAt(int32 index) const;
// Header count
int32 CountHeaders() const;
// Header list tests
int32 HasHeader(const char* name) const;
// Header add or replacement
bool AddHeader(const char* line);
bool AddHeader(const char* name,
const char* value);
bool AddHeader(const char* name,
int32 value);
// Header deletion
void Clear();
// Overloaded operators
BHttpHeaders& operator=(const BHttpHeaders& other);
BHttpHeader& operator[](int32 index) const;
const char* operator[](const char* name) const;
private:
void _EraseData();
private:
BList fHeaderList;
};
#endif // _B_HTTP_HEADERS_H_
+126
View File
@@ -0,0 +1,126 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_NETWORK_COOKIE_H_
#define _B_NETWORK_COOKIE_H_
#include <Archivable.h>
#include <DateTime.h>
#include <Message.h>
#include <String.h>
#include <Url.h>
class BNetworkCookie : public BArchivable {
public:
BNetworkCookie(const char* name,
const char* value);
BNetworkCookie(const BNetworkCookie& other);
BNetworkCookie(const BString& cookieString);
BNetworkCookie(const BString& cookieString,
const BUrl& url);
BNetworkCookie(BMessage* archive);
BNetworkCookie();
virtual ~BNetworkCookie();
// Parse a "SetCookie" string, or "name=value"
BNetworkCookie& ParseCookieStringFromUrl(const BString& string,
const BUrl& url);
BNetworkCookie& ParseCookieString(const BString& cookieString);
// Modify the cookie fields
BNetworkCookie& SetComment(const BString& comment);
BNetworkCookie& SetCommentUrl(const BString& commentUrl);
BNetworkCookie& SetDiscard(bool discard);
BNetworkCookie& SetDomain(const BString& domain);
BNetworkCookie& SetMaxAge(int32 maxAge);
BNetworkCookie& SetExpirationDate(time_t expireDate);
BNetworkCookie& SetExpirationDate(BDateTime& expireDate);
BNetworkCookie& SetPath(const BString& path);
BNetworkCookie& SetSecure(bool secure);
BNetworkCookie& SetVersion(int8 version);
BNetworkCookie& SetName(const BString& name);
BNetworkCookie& SetValue(const BString& value);
// Access the cookie fields
const BString& CommentUrl() const;
const BString& Comment() const;
bool Discard() const;
const BString& Domain() const;
int32 MaxAge() const;
time_t ExpirationDate() const;
const BString& ExpirationString() const;
const BString& Path() const;
bool Secure() const;
int8 Version() const;
const BString& Name() const;
const BString& Value() const;
const BString& RawCookie(bool full) const;
bool IsSessionCookie() const;
bool IsValid(bool strict = false) const;
bool IsValidForUrl(const BUrl& url) const;
bool IsValidForDomain(const BString& domain) const;
bool IsValidForPath(const BString& path) const;
// Test if cookie fields are defined
bool HasCommentUrl() const;
bool HasComment() const;
bool HasDiscard() const;
bool HasDomain() const;
bool HasMaxAge() const;
bool HasExpirationDate() const;
bool HasPath() const;
bool HasVersion() const;
bool HasName() const;
bool HasValue() const;
// Test if cookie could be deleted
bool ShouldDeleteAtExit() const;
bool ShouldDeleteNow() const;
// BArchivable members
virtual status_t Archive(BMessage* into,
bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive);
// Overloaded operators
BNetworkCookie& operator=(const BNetworkCookie& other);
BNetworkCookie& operator=(const char* string);
bool operator==(const BNetworkCookie& other);
bool operator!=(const BNetworkCookie& other);
private:
void _Reset();
void _ExtractNameValuePair(
const BString& cookieString, int16* index,
bool parseField = false);
private:
mutable BString fRawCookie;
mutable bool fRawCookieValid;
mutable BString fRawFullCookie;
mutable bool fRawFullCookieValid;
BString fComment;
BString fCommentUrl;
bool fDiscard;
BString fDomain;
BDateTime fExpiration;
mutable BString fExpirationString;
mutable bool fExpirationStringValid;
BString fPath;
bool fSecure;
int8 fVersion;
BString fName;
BString fValue;
bool fHasDiscard;
bool fHasExpirationDate;
bool fSessionCookie;
bool fHasVersion;
};
#endif // _B_NETWORK_COOKIE_H_
+141
View File
@@ -0,0 +1,141 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_NETWORK_COOKIE_JAR_H_
#define _B_NETWORK_COOKIE_JAR_H_
#include <Archivable.h>
#include <Flattenable.h>
#include <List.h>
#include <Message.h>
#include <NetworkCookie.h>
#include <String.h>
#include <Url.h>
typedef BList BNetworkCookieList;
class BNetworkCookieJar : public BArchivable, public BFlattenable {
public:
// Nested types
class Iterator;
class UrlIterator;
struct PrivateIterator;
struct PrivateHashMap;
public:
BNetworkCookieJar();
BNetworkCookieJar(
const BNetworkCookieJar& other);
BNetworkCookieJar(
const BNetworkCookieList& otherList);
BNetworkCookieJar(BMessage* archive);
virtual ~BNetworkCookieJar();
bool AddCookie(const BNetworkCookie& cookie);
bool AddCookie(BNetworkCookie* cookie);
bool AddCookies(
const BNetworkCookieList& cookies);
uint32 DeleteOutdatedCookies();
uint32 PurgeForExit();
// BArchivable members
virtual status_t Archive(BMessage* into,
bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive);
// BFlattenable members
virtual bool IsFixedSize() const;
virtual type_code TypeCode() const;
virtual ssize_t FlattenedSize() const;
virtual status_t Flatten(void* buffer, ssize_t size)
const;
virtual bool AllowsTypeCode(type_code code) const;
virtual status_t Unflatten(type_code code,
const void* buffer, ssize_t size);
// Iterators
Iterator GetIterator() const;
UrlIterator GetUrlIterator(const BUrl& url) const;
private:
void _DoFlatten() const;
private:
friend class Iterator;
friend class UrlIterator;
PrivateHashMap* fCookieHashMap;
mutable BString fFlattened;
};
class BNetworkCookieJar::Iterator {
public:
Iterator(const Iterator& other);
~Iterator();
bool HasNext() const;
BNetworkCookie* Next();
BNetworkCookie* NextDomain();
BNetworkCookie* Remove();
void RemoveDomain();
Iterator& operator=(const Iterator& other);
private:
Iterator(const BNetworkCookieJar* map);
void _FindNext();
private:
friend class BNetworkCookieJar;
BNetworkCookieJar* fCookieJar;
PrivateIterator* fIterator;
BNetworkCookieList* fLastList;
BNetworkCookieList* fList;
BNetworkCookie* fElement;
BNetworkCookie* fLastElement;
int32 fIndex;
};
class BNetworkCookieJar::UrlIterator {
public:
UrlIterator(const UrlIterator& other);
~UrlIterator();
bool HasNext() const;
BNetworkCookie* Next();
BNetworkCookie* Remove();
UrlIterator& operator=(const UrlIterator& other);
private:
UrlIterator(const BNetworkCookieJar* map,
const BUrl& url);
bool _SupDomain();
void _FindNext();
void _FindDomain();
bool _FindPath();
private:
friend class BNetworkCookieJar;
BNetworkCookieJar* fCookieJar;
PrivateIterator* fIterator;
BNetworkCookieList* fList;
BNetworkCookieList* fLastList;
BNetworkCookie* fElement;
BNetworkCookie* fLastElement;
int32 fIndex;
int32 fLastIndex;
BUrl fUrl;
};
#endif // _B_NETWORK_COOKIE_JAR_
+145
View File
@@ -0,0 +1,145 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_URL_H_
#define _B_URL_H_
#include <Archivable.h>
#include <Message.h>
#include <String.h>
class BUrl : public BArchivable {
public:
BUrl(const char* url);
BUrl(BMessage* archive);
BUrl(const BUrl& other);
BUrl();
virtual ~BUrl();
// URL fields modifiers
BUrl& SetUrlString(const BString& url);
BUrl& SetProtocol(const BString& scheme);
BUrl& SetUserName(const BString& user);
BUrl& SetPassword(const BString& password);
BUrl& SetHost(const BString& host);
BUrl& SetPort(int port);
BUrl& SetPath(const BString& path);
BUrl& SetRequest(const BString& request);
BUrl& SetFragment(const BString& fragment);
// URL fields access
const BString& UrlString() const;
const BString& Protocol() const;
const BString& UserName() const;
const BString& Password() const;
const BString& UserInfo() const;
const BString& Host() const;
int Port() const;
const BString& Authority() const;
const BString& Path() const;
const BString& Request() const;
const BString& Fragment() const;
// URL fields tests
bool IsValid() const;
bool HasProtocol() const;
bool HasUserName() const;
bool HasPassword() const;
bool HasUserInfo() const;
bool HasHost() const;
bool HasPort() const;
bool HasAuthority() const;
bool HasPath() const;
bool HasRequest() const;
bool HasFragment() const;
// Url encoding/decoding of needed fields
void UrlEncode(bool strict = false);
void UrlDecode(bool strict = false);
// Url encoding/decoding of strings
static BString UrlEncode(const BString& url,
bool strict = false,
bool directory = false);
static BString UrlDecode(const BString& url,
bool strict = false);
// BArchivable members
virtual status_t Archive(BMessage* into,
bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive);
// URL comparison
bool operator==(BUrl& other) const;
bool operator!=(BUrl& other) const;
// URL assignment
const BUrl& operator=(const BUrl& other);
const BUrl& operator=(const BString& string);
const BUrl& operator=(const char* string);
// URL to string conversion
operator const char*() const;
private:
void _ResetFields();
void _ExplodeUrlString(const BString& urlString);
void _ExtractProtocol(const BString& urlString,
int16* origin);
void _ExtractAuthority(const BString& urlString,
int16* origin);
void _ExtractPath(const BString& urlString,
int16* origin);
void _ExtractRequestAndFragment(
const BString& urlString, int16* origin);
static BString _DoUrlEncodeChunk(const BString& chunk,
bool strict, bool directory = false);
static BString _DoUrlDecodeChunk(const BString& chunk,
bool strict);
bool _IsProtocolValid();
static bool _IsAuthorityTerminator(char c);
static bool _IsPathTerminator(char c);
static bool _IsRequestTerminator(char c);
static bool _IsUnreserved(char c);
static bool _IsGenDelim(char c);
static bool _IsSubDelim(char c);
private:
mutable BString fUrlString;
mutable BString fAuthority;
mutable BString fUserInfo;
BString fProtocol;
BString fUser;
BString fPassword;
BString fHost;
int fPort;
BString fPath;
BString fRequest;
BString fFragment;
mutable bool fUrlStringValid : 1;
mutable bool fAuthorityValid : 1;
mutable bool fUserInfoValid : 1;
bool fBasicUri : 1;
bool fHasProtocol : 1;
bool fHasUserName : 1;
bool fHasPassword : 1;
bool fHasUserInfo : 1;
bool fHasHost : 1;
bool fHasPort : 1;
bool fHasAuthority : 1;
bool fHasPath : 1;
bool fHasRequest : 1;
bool fHasFragment : 1;
};
#endif // _B_URL_H_
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_URL_CONTEXT_H_
#define _B_URL_CONTEXT_H_
#include <NetworkCookieJar.h>
class BUrlContext {
public:
BUrlContext();
// Context modifiers
void SetCookieJar(
const BNetworkCookieJar& cookieJar);
// Context accessors
BNetworkCookieJar& GetCookieJar();
private:
BNetworkCookieJar fCookieJar;
};
#endif // _B_URL_CONTEXT_H_
+139
View File
@@ -0,0 +1,139 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_URL_PROTOCOL_H_
#define _B_URL_PROTOCOL_H_
#include <Url.h>
#include <UrlResult.h>
#include <UrlContext.h>
#include <UrlProtocolListener.h>
#include <OS.h>
class BUrlProtocol {
public:
BUrlProtocol(const BUrl& url,
BUrlProtocolListener* listener,
BUrlContext* context,
BUrlResult* result,
const char* threadName,
const char* protocolName);
// URL protocol required members
// TODO: (stippi) I know it's sometimes appealing to have these
// "simplistic" methods that can do anything, but they remove
// type-safety. Why not overload SetOption with all possible types?
// Like:
// SetOption(uint32 option, bool value);
// SetOption(uint32 option, int8 value);
// SetOption(uint32 option, int16 value);
// SetOption(uint32 option, int32 value);
// ...
// This keeps the calling side even more simple, since it
// don't need to do pointer stuff with the parameters. Also, since
// this method is forced to be implemented in derived classes, why
// is it here at all? Why not have non-virtual setters for specific
// things, where the setter is properly named?
virtual status_t SetOption(uint32 name, void* value) = 0;
// URL protocol thread management
virtual thread_id Run();
virtual status_t Pause();
virtual status_t Resume();
virtual status_t Stop();
// URL protocol parameters modification
status_t SetUrl(const BUrl& url);
status_t SetResult(BUrlResult* result);
status_t SetContext(BUrlContext* context);
status_t SetListener(BUrlProtocolListener* listener);
// URL protocol parameters access
const BUrl& Url() const;
BUrlResult* Result() const;
BUrlContext* Context() const;
BUrlProtocolListener* Listener() const;
const BString& Protocol() const;
// TODO: Does not belong here.
BHttpHeaders& Headers() { return fRequestHeaders; }
// URL protocol informations
bool IsRunning() const;
status_t Status() const;
virtual const char* StatusString(status_t threadStatus)
const;
protected:
static int32 _ThreadEntry(void* arg);
virtual status_t _ProtocolLoop();
virtual void _EmitDebug(BUrlProtocolDebugMessage type,
const char* format, ...);
// URL result parameters access
BMallocIO& _ResultRawData();
BHttpHeaders& _ResultHeaders();
void _SetResultStatusCode(int32 statusCode);
BString& _ResultStatusText();
protected:
BUrl fUrl;
BHttpHeaders fRequestHeaders;
// TODO: Does not belong here.
BUrlResult* fResult;
BUrlContext* fContext;
BUrlProtocolListener* fListener;
bool fQuit;
bool fRunning;
status_t fThreadStatus;
thread_id fThreadId;
BString fThreadName;
BString fProtocol;
};
// TODO: Rename, this is in the global namespace.
enum {
B_PROT_THREAD_STATUS__BASE = 0,
B_PROT_SUCCESS = B_PROT_THREAD_STATUS__BASE,
B_PROT_RUNNING,
B_PROT_PAUSED,
B_PROT_ABORTED,
B_PROT_SOCKET_ERROR,
B_PROT_CONNECTION_FAILED,
B_PROT_CANT_RESOLVE_HOSTNAME,
B_PROT_WRITE_FAILED,
B_PROT_READ_FAILED,
B_PROT_NO_MEMORY,
B_PROT_PROTOCOL_ERROR,
// Thread status over this one are guaranteed to be
// errors
B_PROT_THREAD_STATUS__END
};
namespace BPrivate {
class BUrlProtocolOption {
public:
BUrlProtocolOption(void* value) : fValuePtr(value) { }
bool Bool() const { return *reinterpret_cast<bool*>(fValuePtr); }
int8 Int8() const { return *reinterpret_cast<int8*>(fValuePtr); }
int16 Int16() const { return *reinterpret_cast<int16*>(fValuePtr); }
int32 Int32() const { return *reinterpret_cast<int32*>(fValuePtr); }
char* String() const { return reinterpret_cast<char*>(fValuePtr); }
void* Pointer() const { return fValuePtr; }
private:
void* fValuePtr;
};
} // namespace BPrivate
#endif // _B_URL_PROTOCOL_H_
@@ -0,0 +1,46 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_URL_PROTOCOL_ASYNCHRONOUS_LISTENER_H_
#define _B_URL_PROTOCOL_ASYNCHRONOUS_LISTENER_H_
#include <Handler.h>
#include <Message.h>
#include <UrlProtocolDispatchingListener.h>
class BUrlProtocolAsynchronousListener : public BHandler {
public:
BUrlProtocolAsynchronousListener(
bool transparent = false);
virtual ~BUrlProtocolAsynchronousListener();
virtual void ConnectionOpened(BUrlProtocol* caller);
virtual void HostnameResolved(BUrlProtocol* caller,
const char* ip);
virtual void ResponseStarted(BUrlProtocol* caller);
virtual void HeadersReceived(BUrlProtocol* caller);
virtual void DataReceived(BUrlProtocol* caller,
const char* data, ssize_t size);
virtual void DownloadProgress(BUrlProtocol* caller,
ssize_t bytesReceived, ssize_t bytesTotal);
virtual void UploadProgress(BUrlProtocol* caller,
ssize_t bytesSent, ssize_t bytesTotal);
virtual void RequestCompleted(BUrlProtocol* caller,
bool success);
// Synchronous listener access
BUrlProtocolListener* SynchronousListener();
// BHandler interface
virtual void MessageReceived(BMessage* message);
private:
BUrlProtocolDispatchingListener*
fSynchronousListener;
};
#endif // _B_URL_PROTOCOL_ASYNCHRONOUS_LISTENER_H_
@@ -0,0 +1,66 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_URL_PROTOCOL_DISPATCHING_LISTENER_H_
#define _B_URL_PROTOCOL_DISPATCHING_LISTENER_H_
#include <Messenger.h>
#include <Message.h>
#include <UrlProtocolListener.h>
//! To be in AppTypes.h
enum {
B_URL_PROTOCOL_NOTIFICATION = '_UPN'
};
// Notification types
enum {
B_URL_PROTOCOL_CONNECTION_OPENED,
B_URL_PROTOCOL_HOSTNAME_RESOLVED,
B_URL_PROTOCOL_RESPONSE_STARTED,
B_URL_PROTOCOL_HEADERS_RECEIVED,
B_URL_PROTOCOL_DATA_RECEIVED,
B_URL_PROTOCOL_DOWNLOAD_PROGRESS,
B_URL_PROTOCOL_UPLOAD_PROGRESS,
B_URL_PROTOCOL_REQUEST_COMPLETED
};
class BUrlProtocolDispatchingListener : public BUrlProtocolListener {
public:
BUrlProtocolDispatchingListener(
BHandler* handler);
BUrlProtocolDispatchingListener(
const BMessenger& messenger);
virtual void ConnectionOpened(BUrlProtocol* caller);
virtual void HostnameResolved(BUrlProtocol* caller,
const char* ip);
virtual void ResponseStarted(BUrlProtocol* caller);
virtual void HeadersReceived(BUrlProtocol* caller);
virtual void DataReceived(BUrlProtocol* caller,
const char* data, ssize_t size);
virtual void DownloadProgress(BUrlProtocol* caller,
ssize_t bytesReceived, ssize_t bytesTotal);
virtual void UploadProgress(BUrlProtocol* caller,
ssize_t bytesSent, ssize_t bytesTotal);
virtual void RequestCompleted(BUrlProtocol* caller,
bool success);
virtual void DebugMessage(BUrlProtocol*,
BUrlProtocolDebugMessage,
const char*) { }
private:
void _SendMessage(BMessage* message,
int8 notification, BUrlProtocol* caller);
private:
BMessenger fMessenger;
};
#endif // _B_URL_PROTOCOL_DISPATCHING_LISTENER_H_
+235
View File
@@ -0,0 +1,235 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_URL_PROTOCOL_HTTP_H_
#define _B_URL_PROTOCOL_HTTP_H_
#include <deque>
#include <HttpAuthentication.h>
#include <HttpForm.h>
#include <HttpHeaders.h>
#include <NetEndpoint.h>
#include <NetBuffer.h>
#include <UrlProtocol.h>
class BUrlProtocolHttp : public BUrlProtocol {
public:
BUrlProtocolHttp(BUrl& url,
BUrlProtocolListener* listener = NULL,
BUrlContext* context = NULL,
BUrlResult* result = NULL);
virtual status_t SetOption(uint32 option, void* value);
static bool IsInformationalStatusCode(int16 code);
static bool IsSuccessStatusCode(int16 code);
static bool IsRedirectionStatusCode(int16 code);
static bool IsClientErrorStatusCode(int16 code);
static bool IsServerErrorStatusCode(int16 code);
static int16 StatusCodeClass(int16 code);
virtual const char* StatusString(status_t threadStatus) const;
private:
void _ResetOptions();
status_t _ProtocolLoop();
bool _ResolveHostName();
status_t _MakeRequest();
void _CreateRequest();
void _AddHeaders();
status_t _GetLine(BString& destString);
void _ParseStatus();
void _ParseHeaders();
void _CopyChunkInBuffer(char** buffer,
ssize_t* bytesReceived);
void _AddOutputBufferLine(const char* line);
private:
BNetEndpoint fSocket;
BNetAddress fRemoteAddr;
int8 fRequestMethod;
int8 fHttpVersion;
BString fOutputBuffer;
BNetBuffer fInputBuffer;
BHttpHeaders fHeaders;
BHttpAuthentication fAuthentication;
// Request status
BHttpHeaders fOutputHeaders;
bool fStatusReceived;
bool fHeadersReceived;
bool fContentReceived;
bool fTrailingHeadersReceived;
// Protocol options
uint8 fOptMaxRedirs;
BString fOptReferer;
BString fOptUserAgent;
BString fOptUsername;
BString fOptPassword;
uint32 fOptAuthMethods;
BHttpHeaders* fOptHeaders;
BHttpForm* fOptPostFields;
BDataIO* fOptInputData;
bool fOptSetCookies : 1;
bool fOptFollowLocation : 1;
bool fOptDiscardData : 1;
bool fOptDisableListener : 1;
bool fOptAutoReferer : 1;
};
// ProtocolLoop return status
enum {
B_PROT_HTTP_NOT_FOUND = B_PROT_THREAD_STATUS__END,
B_PROT_HTTP_THREAD_STATUS__END
};
// Request method
enum {
B_HTTP_GET = 1,
B_HTTP_POST,
B_HTTP_PUT,
B_HTTP_HEAD,
B_HTTP_DELETE,
B_HTTP_OPTIONS
};
// HTTP Version
enum {
B_HTTP_10 = 1,
B_HTTP_11
};
// HTTP Protocol options
enum {
B_HTTPOPT_METHOD = 0,
// (int) Request method (see B_HTTP_GET, ...)
B_HTTPOPT_FOLLOWLOCATION,
// (bool) Follow Location: headers
B_HTTPOPT_MAXREDIRS,
// (int) Max relocation
B_HTTPOPT_HEADERS,
// (BHttpHeaders*) Headers to be sent
B_HTTPOPT_REFERER,
// (string) Referer
B_HTTPOPT_USERAGENT,
// (string) User-Agent
B_HTTPOPT_SETCOOKIES,
// (bool) Send cookies from context
B_HTTPOPT_DISCARD_DATA,
// (bool) Discard incoming data (still notified)
B_HTTPOPT_DISABLE_LISTENER,
// (bool) Don't send notification to the listener
B_HTTPOPT_AUTOREFERER,
// (bool) Automatically set the Referer header
B_HTTPOPT_POSTFIELDS,
// (BHttpForm*) POST data to be sent
B_HTTPOPT_INPUTDATA,
// (BDataIO*) Input data to be sent (POST, PUT)
B_HTTPOPT_AUTHUSERNAME,
// (string) Authentication username
B_HTTPOPT_AUTHPASSWORD,
// (string) Authentication password
B_HTTPOPT_AUTHMETHOD,
// (int) Allowed authentication methods (see BHttpAuthenticationMethod)
B_HTTPOPT__OPT_NUM
};
// HTTP status classes
enum http_status_code_class {
B_HTTP_STATUS_CLASS_INVALID = 000,
B_HTTP_STATUS_CLASS_INFORMATIONAL = 100,
B_HTTP_STATUS_CLASS_SUCCESS = 200,
B_HTTP_STATUS_CLASS_REDIRECTION = 300,
B_HTTP_STATUS_CLASS_CLIENT_ERROR = 400,
B_HTTP_STATUS_CLASS_SERVER_ERROR = 500
};
// Known HTTP status codes
enum http_status_code {
// Informational status codes
B_HTTP_STATUS__INFORMATIONAL_BASE = 100,
B_HTTP_STATUS_CONTINUE = B_HTTP_STATUS__INFORMATIONAL_BASE,
B_HTTP_STATUS_SWITCHING_PROTOCOLS,
B_HTTP_STATUS__INFORMATIONAL_END,
// Success status codes
B_HTTP_STATUS__SUCCESS_BASE = 200,
B_HTTP_STATUS_OK = B_HTTP_STATUS__SUCCESS_BASE,
B_HTTP_STATUS_CREATED,
B_HTTP_STATUS_ACCEPTED,
B_HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION,
B_HTTP_STATUS_NO_CONTENT,
B_HTTP_STATUS_RESET_CONTENT,
B_HTTP_STATUS_PARTIAL_CONTENT,
B_HTTP_STATUS__SUCCESS_END,
// Redirection status codes
B_HTTP_STATUS__REDIRECTION_BASE = 300,
B_HTTP_STATUS_MULTIPLE_CHOICE = B_HTTP_STATUS__REDIRECTION_BASE,
B_HTTP_STATUS_MOVED_PERMANENTLY,
B_HTTP_STATUS_FOUND,
B_HTTP_STATUS_SEE_OTHER,
B_HTTP_STATUS_NOT_MODIFIED,
B_HTTP_STATUS_USE_PROXY,
B_HTTP_STATUS_TEMPORARY_REDIRECT,
B_HTTP_STATUS__REDIRECTION_END,
// Client error status codes
B_HTTP_STATUS__CLIENT_ERROR_BASE = 400,
B_HTTP_STATUS_BAD_REQUEST = B_HTTP_STATUS__CLIENT_ERROR_BASE,
B_HTTP_STATUS_UNAUTHORIZED,
B_HTTP_STATUS_PAYMENT_REQUIRED,
B_HTTP_STATUS_FORBIDDEN,
B_HTTP_STATUS_NOT_FOUND,
B_HTTP_STATUS_METHOD_NOT_ALLOWED,
B_HTTP_STATUS_NOT_ACCEPTABLE,
B_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED,
B_HTTP_STATUS_REQUEST_TIMEOUT,
B_HTTP_STATUS_CONFLICT,
B_HTTP_STATUS_GONE,
B_HTTP_STATUS_LENGTH_REQUIRED,
B_HTTP_STATUS_PRECONDITION_FAILED,
B_HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE,
B_HTTP_STATUS_REQUEST_URI_TOO_LARGE,
B_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE,
B_HTTP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE,
B_HTTP_STATUS_EXPECTATION_FAILED,
B_HTTP_STATUS__CLIENT_ERROR_END,
// Server error status codes
B_HTTP_STATUS__SERVER_ERROR_BASE = 500,
B_HTTP_STATUS_INTERNAL_SERVER_ERROR = B_HTTP_STATUS__SERVER_ERROR_BASE,
B_HTTP_STATUS_NOT_IMPLEMENTED,
B_HTTP_STATUS_BAD_GATEWAY,
B_HTTP_STATUS_SERVICE_UNAVAILABLE,
B_HTTP_STATUS_GATEWAY_TIMEOUT,
B_HTTP_STATUS__SERVER_ERROR_END
};
// HTTP default User-Agent
#define B_HTTP_PROTOCOL_USER_AGENT_FORMAT "ServicesKit (%s)"
#endif // _B_URL_PROTOCOL_HTTP_H_
+120
View File
@@ -0,0 +1,120 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_URL_PROTOCOL_LISTENER_H_
#define _B_URL_PROTOCOL_LISTENER_H_
#include <stddef.h>
#include <cstdlib>
class BUrlProtocol;
enum BUrlProtocolDebugMessage {
B_URL_PROTOCOL_DEBUG_TEXT,
B_URL_PROTOCOL_DEBUG_ERROR,
B_URL_PROTOCOL_DEBUG_HEADER_IN,
B_URL_PROTOCOL_DEBUG_HEADER_OUT,
B_URL_PROTOCOL_DEBUG_TRANSFER_IN,
B_URL_PROTOCOL_DEBUG_TRANSFER_OUT
};
class BUrlProtocolListener {
public:
/*
ConnectionOpened()
Frequency: Once
Called when the socket is opened.
*/
virtual void ConnectionOpened(BUrlProtocol* caller);
/*
HostnameResolved(ip)
Frequency: Once
Parameters: ip String representing the IP address of the resource
host.
Called when the final IP is discovered
*/
virtual void HostnameResolved(BUrlProtocol* caller,
const char* ip);
/*
ReponseStarted()
Frequency: Once
Called when the request has been emitted and the server begins to
reply. Typically when the HTTP status code is received.
*/
virtual void ResponseStarted(BUrlProtocol* caller);
/*
HeadersReceived()
Frequency: Once
Called when all the server response metadata (such as headers) have
been read and parsed.
*/
virtual void HeadersReceived(BUrlProtocol* caller);
/*
DataReceived(data, size)
Frequency: Zero or more
Parameters: data Pointer to the data block in memory
size Size of the data block
Called each time a full block of data is received.
*/
virtual void DataReceived(BUrlProtocol* caller,
const char* data, ssize_t size);
/*
DownloadProgress(bytesReceived, bytesTotal)
Frequency: Once or more
Parameters: bytesReceived Number of data bytes received
bytesTotal Total number of data bytes expected
Called each time a data block is received.
*/
virtual void DownloadProgress(BUrlProtocol* caller,
ssize_t bytesReceived, ssize_t bytesTotal);
/*
UploadProgress(bytesSent, bytesTotal)
Frequency: Once or more
Parameters: bytesSent Number of data bytes sent
bytesTotal Total number of data bytes expected
Called each time a data block is emitted.
*/
virtual void UploadProgress(BUrlProtocol* caller,
ssize_t bytesSent, ssize_t bytesTotal);
/*
RequestCompleted(success)
Frequency: Once
Parameters: success true if the resource have been successfully
false if not
Called once the request is complete.
*/
virtual void RequestCompleted(BUrlProtocol* caller,
bool success);
/*
DebugMessage(type, text)
Frequency: zero or more
Parameters: type Type of the verbose message (see BUrlProtocolDebug)
Called each time a debug message is emitted
*/
virtual void DebugMessage(BUrlProtocol* caller,
BUrlProtocolDebugMessage type,
const char* text);
};
#endif // _B_URL_PROTOCOL_LISTENER_H_
+68
View File
@@ -0,0 +1,68 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_URL_REQUEST_H_
#define _B_URL_REQUEST_H_
#include <HttpHeaders.h>
#include <Url.h>
#include <UrlResult.h>
#include <UrlContext.h>
#include <UrlProtocol.h>
#include <UrlProtocolListener.h>
enum {
B_NO_HANDLER_FOR_PROTOCOL = B_ERROR
};
class BUrlRequest {
public:
BUrlRequest(const BUrl& url,
BUrlProtocolListener* listener);
BUrlRequest(const BUrl& url);
BUrlRequest(const BUrlRequest& other);
virtual ~BUrlRequest() { };
// Request parameters modification
status_t SetUrl(const BUrl& url);
void SetContext(BUrlContext* context);
void SetProtocolListener(
BUrlProtocolListener* listener);
bool SetProtocolOption(int32 option,
void* value);
// Request parameters access
const BUrlProtocol* Protocol();
const BUrlResult& Result();
const BUrl& Url();
// Request control
status_t Identify();
virtual status_t Perform();
// TODO: Rename to Run() perhaps? "Perform" is used for FBC stuff.
virtual status_t Pause();
virtual status_t Resume();
virtual status_t Abort();
// Request informations
virtual bool InitCheck() const;
bool IsRunning() const;
status_t Status() const;
// Overloaded members
BUrlRequest& operator=(const BUrlRequest& other);
protected:
BUrlProtocolListener* fListener;
BUrlProtocol* fUrlProtocol;
BUrlResult fResult;
BUrlContext* fContext;
BUrl fUrl;
bool fReady;
};
#endif // _B_URL_REQUEST_H_
+56
View File
@@ -0,0 +1,56 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_URL_RESULT_H_
#define _B_URL_RESULT_H_
#include <iostream>
#include <DataIO.h>
#include <HttpHeaders.h>
#include <String.h>
#include <Url.h>
class BUrlProtocol;
class BUrlResult {
friend class BUrlProtocol;
public:
BUrlResult(const BUrl& url);
BUrlResult(const BUrlResult& other);
// Result parameters modifications
void SetUrl(const BUrl& url);
// Result parameters access
const BUrl& Url() const;
const BMallocIO& RawData() const;
const BHttpHeaders& Headers() const;
const BString& StatusText() const;
int32 StatusCode() const;
// Result tests
bool HasHeaders() const;
// Overloaded members
BUrlResult& operator=(const BUrlResult& other);
friend std::ostream& operator<<(std::ostream& out,
const BUrlResult& result);
private:
BUrl fUrl;
BMallocIO fRawData;
BHttpHeaders fHeaders;
// TODO: HTTP specific stuff should not live here.
int32 fStatusCode;
BString fStatusString;
};
#endif // _B_URL_RESULT_H_
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_URL_SYNCHRONOUS_REQUEST_H_
#define _B_URL_SYNCHRONOUS_REQUEST_H_
#include <UrlRequest.h>
#include <UrlProtocolListener.h>
class BUrlSynchronousRequest : public BUrlRequest, public BUrlProtocolListener {
public:
BUrlSynchronousRequest(BUrl& url);
virtual ~BUrlSynchronousRequest() { };
// Synchronous wait
virtual status_t Perform();
virtual status_t WaitUntilCompletion();
// Protocol hooks
virtual void ConnectionOpened(BUrlProtocol* caller);
virtual void HostnameResolved(BUrlProtocol* caller,
const char* ip);
virtual void ResponseStarted(BUrlProtocol* caller);
virtual void HeadersReceived(BUrlProtocol* caller);
virtual void DataReceived(BUrlProtocol* caller,
const char* data, ssize_t size);
virtual void DownloadProgress(BUrlProtocol* caller,
ssize_t bytesReceived, ssize_t bytesTotal);
virtual void UploadProgress(BUrlProtocol* caller,
ssize_t bytesSent, ssize_t bytesTotal);
virtual void RequestCompleted(BUrlProtocol* caller,
bool success);
protected:
bool fRequestComplete;
};
#endif // _B_URL_SYNCHRONOUS_REQUEST_H_
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_HTTP_TIME_H_
#define _B_HTTP_TIME_H_
#include <ctime>
#include <String.h>
namespace BPrivate {
enum {
B_HTTP_TIME_FORMAT_PARSED = -1,
B_HTTP_TIME_FORMAT_RFC1123 = 0,
B_HTTP_TIME_FORMAT_PREFERRED = B_HTTP_TIME_FORMAT_RFC1123,
B_HTTP_TIME_FORMAT_COOKIE,
B_HTTP_TIME_FORMAT_RFC1036,
B_HTTP_TIME_FORMAT_ASCTIME
};
class BHttpTime {
public:
BHttpTime();
BHttpTime(time_t date);
BHttpTime(const BString& dateString);
// Date modification
void SetString(const BString& string);
void SetDate(time_t date);
// Date conversion
time_t Parse();
BString ToString(int8 format = B_HTTP_TIME_FORMAT_PARSED);
private:
BString fDateString;
time_t fDate;
int8 fDateFormat;
};
}
#endif // _B_HTTP_TIME_H_