1/*
2 * Copyright 2010-2013 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _B_HTTP_FORM_H_
6#define _B_HTTP_FORM_H_
7
8
9#include <Path.h>
10#include <String.h>
11
12#include <map>
13
14
15namespace BPrivate {
16
17namespace Network {
18
19
20enum form_type {
21	B_HTTP_FORM_URL_ENCODED,
22	B_HTTP_FORM_MULTIPART
23};
24
25
26enum form_content_type {
27	B_HTTPFORM_UNKNOWN,
28	B_HTTPFORM_STRING,
29	B_HTTPFORM_FILE,
30	B_HTTPFORM_BUFFER
31};
32
33
34class BHttpFormData {
35private:
36	// Empty constructor is only kept for compatibility with map<>::operator[],
37	// but never used (see BHttpForm::operator[] which does the necessary
38	// check up)
39								BHttpFormData();
40#if (__GNUC__ >= 6) || defined(__clang__)
41	friend class std::pair<const BString, BHttpFormData>;
42#else
43	friend class std::map<BString, BHttpFormData>;
44#endif
45
46public:
47								BHttpFormData(const BString& name,
48									const BString& value);
49								BHttpFormData(const BString& name,
50									const BPath& file);
51								BHttpFormData(const BString& name,
52									const void* buffer, ssize_t size);
53								BHttpFormData(const BHttpFormData& other);
54								~BHttpFormData();
55
56	// Retrieve data informations
57			bool				InitCheck() const;
58
59			const BString&		Name() const;
60			const BString&		String() const;
61			const BPath&		File() const;
62			const void*			Buffer() const;
63			ssize_t				BufferSize() const;
64
65			bool				IsFile() const;
66			const BString&		Filename() const;
67			const BString&		MimeType() const;
68			form_content_type	Type() const;
69
70	// Change behavior
71			status_t			MarkAsFile(const BString& filename,
72									const BString& mimeType = "");
73			void				UnmarkAsFile();
74			status_t			CopyBuffer();
75
76	// Overloaded operators
77			BHttpFormData&		operator=(const BHttpFormData& other);
78
79private:
80			form_content_type	fDataType;
81			bool				fCopiedBuffer;
82			bool				fFileMark;
83
84			BString				fName;
85			BString				fStringValue;
86			BPath				fPathValue;
87			const void*			fBufferValue;
88			ssize_t				fBufferSize;
89
90			BString				fFilename;
91			BString				fMimeType;
92};
93
94
95class BHttpForm {
96public:
97	// Nested types
98	class Iterator;
99	typedef std::map<BString, BHttpFormData> FormStorage;
100
101public:
102								BHttpForm();
103								BHttpForm(const BHttpForm& other);
104								BHttpForm(const BString& formString);
105								~BHttpForm();
106
107	// Form string parsing
108			void				ParseString(const BString& formString);
109			BString				RawData() const;
110
111	// Form add
112			status_t			AddString(const BString& name,
113									const BString& value);
114			status_t			AddInt(const BString& name, int32 value);
115			status_t			AddFile(const BString& fieldName,
116									const BPath& file);
117			status_t			AddBuffer(const BString& fieldName,
118									const void* buffer, ssize_t size);
119			status_t			AddBufferCopy(const BString& fieldName,
120									const void* buffer, ssize_t size);
121
122	// Mark a field as a filename
123			void				MarkAsFile(const BString& fieldName,
124									const BString& filename,
125									const BString& mimeType);
126			void				MarkAsFile(const BString& fieldName,
127									const BString& filename);
128			void				UnmarkAsFile(const BString& fieldName);
129
130	// Change form type
131			void				SetFormType(form_type type);
132
133	// Form test
134			bool				HasField(const BString& name) const;
135
136	// Form retrieve
137			BString				GetMultipartHeader(const BString& fieldName) const;
138			form_content_type	GetType(const BString& fieldname) const;
139
140	// Form informations
141			form_type			GetFormType() const;
142			const BString&		GetMultipartBoundary() const;
143			BString				GetMultipartFooter() const;
144			ssize_t				ContentLength() const;
145
146	// Form iterator
147			Iterator			GetIterator();
148
149	// Form clear
150			void				Clear();
151
152	// Overloaded operators
153			BHttpFormData&		operator[](const BString& name);
154
155private:
156			void				_ExtractNameValuePair(const BString& string, int32* index);
157			void				_GenerateMultipartBoundary();
158			BString				_GetMultipartHeader(const BHttpFormData* element) const;
159			form_content_type	_GetType(FormStorage::const_iterator it) const;
160			void				_Erase(FormStorage::iterator it);
161
162private:
163	friend	class Iterator;
164
165			FormStorage			fFields;
166			form_type			fType;
167			BString				fMultipartBoundary;
168};
169
170
171class BHttpForm::Iterator {
172public:
173								Iterator(const Iterator& other);
174
175			BHttpFormData*		Next();
176			bool 				HasNext() const;
177			void				Remove();
178			BString				MultipartHeader();
179
180			Iterator& 			operator=(const Iterator& other);
181
182private:
183								Iterator(BHttpForm* form);
184			void				_FindNext();
185
186private:
187	friend	class BHttpForm;
188
189			BHttpForm*			fForm;
190			BHttpForm::FormStorage::iterator
191								fStdIterator;
192			BHttpFormData*		fElement;
193			BHttpFormData*		fPrevElement;
194};
195
196
197} // namespace Network
198
199} // namespace BPrivate
200
201#endif // _B_HTTP_FORM_H_
202