diff --git a/headers/os/net/HttpForm.h b/headers/os/net/HttpForm.h index ec27253f4c..b4eba439de 100644 --- a/headers/os/net/HttpForm.h +++ b/headers/os/net/HttpForm.h @@ -1,5 +1,5 @@ /* - * Copyright 2010 Haiku Inc. All rights reserved. + * Copyright 2010-2013 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef _B_HTTP_FORM_H_ @@ -33,9 +33,9 @@ private: // check up) BHttpFormData(); friend class std::map; - + public: - BHttpFormData(const BString& name, + BHttpFormData(const BString& name, const BString& value); BHttpFormData(const BString& name, const BPath& file); @@ -43,27 +43,27 @@ public: 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, + status_t MarkAsFile(const BString& filename, const BString& mimeType = ""); void UnmarkAsFile(); status_t CopyBuffer(); - + // Overloaded operators BHttpFormData& operator=(const BHttpFormData& other); @@ -71,13 +71,13 @@ 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; }; @@ -88,28 +88,28 @@ public: // Nested types class Iterator; typedef std::map 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, + status_t AddString(const BString& name, const BString& value); status_t AddInt(const BString& name, int32 value); - status_t AddFile(const BString& fieldName, + 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, @@ -117,52 +117,48 @@ public: 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; + 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 _ExtractNameValuePair(const BString& string, int32* index); void _GenerateMultipartBoundary(); - BString _GetMultipartHeader( - const BHttpFormData* element) const; + 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); @@ -171,7 +167,7 @@ public: bool HasNext() const; void Remove(); BString MultipartHeader(); - + Iterator& operator=(const Iterator& other); private: @@ -179,7 +175,7 @@ private: void _FindNext(); private: - friend class BHttpForm; + friend class BHttpForm; BHttpForm* fForm; BHttpForm::FormStorage::iterator diff --git a/src/kits/network/libnetapi/HttpForm.cpp b/src/kits/network/libnetapi/HttpForm.cpp index 1fdc971dd1..ce2b3eb6ee 100644 --- a/src/kits/network/libnetapi/HttpForm.cpp +++ b/src/kits/network/libnetapi/HttpForm.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010 Haiku Inc. All rights reserved. + * Copyright 2010-2013 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -7,22 +7,24 @@ */ +#include + #include #include #include #include -#include #include #include #include + static int32 kBoundaryRandomSize = 16; using namespace std; -// #pragma mark -- BHttpFormData +// #pragma mark - BHttpFormData BHttpFormData::BHttpFormData() @@ -62,7 +64,7 @@ BHttpFormData::BHttpFormData(const BString& name, const BPath& file) } -BHttpFormData::BHttpFormData(const BString& name, const void* buffer, +BHttpFormData::BHttpFormData(const BString& name, const void* buffer, ssize_t size) : fDataType(B_HTTPFORM_BUFFER), @@ -91,9 +93,9 @@ BHttpFormData::~BHttpFormData() if (fCopiedBuffer) delete[] reinterpret_cast(fBufferValue); } - -// #pragma mark Retrieve data informations + +// #pragma mark - Retrieve data informations bool @@ -101,7 +103,7 @@ BHttpFormData::InitCheck() const { if (fDataType == B_HTTPFORM_BUFFER) return fBufferValue != NULL; - + return true; } @@ -169,17 +171,19 @@ BHttpFormData::Type() const } -// #pragma mark Change behavior +// #pragma mark - Change behavior + + status_t BHttpFormData::MarkAsFile(const BString& filename, const BString& mimeType) { if (fDataType == B_HTTPFORM_UNKNOWN || fDataType == B_HTTPFORM_FILE) return B_ERROR; - + fFilename = filename; fMimeType = mimeType; fFileMark = true; - + return B_OK; } @@ -198,15 +202,15 @@ BHttpFormData::CopyBuffer() { if (fDataType != B_HTTPFORM_BUFFER) return B_ERROR; - + char* copiedBuffer = new char[fBufferSize]; if (copiedBuffer == NULL) return B_NO_MEMORY; - + memcpy(copiedBuffer, fBufferValue, fBufferSize); fBufferValue = copiedBuffer; fCopiedBuffer = true; - + return B_OK; } @@ -224,31 +228,34 @@ BHttpFormData::operator=(const BHttpFormData& other) fBufferSize = other.fBufferSize; fFilename = other.fFilename; fMimeType = other.fMimeType; - + if (other.fCopiedBuffer) CopyBuffer(); - + return *this; } -// #pragma mark -- BHttpForm +// #pragma mark - BHttpForm BHttpForm::BHttpForm() - : fType(B_HTTP_FORM_URL_ENCODED) + : + fType(B_HTTP_FORM_URL_ENCODED) { } -BHttpForm::BHttpForm(const BHttpForm&) - : fType(B_HTTP_FORM_URL_ENCODED) +BHttpForm::BHttpForm(const BHttpForm& other) + : + fType(B_HTTP_FORM_URL_ENCODED) { } BHttpForm::BHttpForm(const BString& formString) - : fType(B_HTTP_FORM_URL_ENCODED) + : + fType(B_HTTP_FORM_URL_ENCODED) { ParseString(formString); } @@ -260,17 +267,16 @@ BHttpForm::~BHttpForm() } -// #pragma mark Form string parsing +// #pragma mark - Form string parsing void BHttpForm::ParseString(const BString& formString) { int32 index = 0; - - while (index < formString.Length()) { + + while (index < formString.Length()) _ExtractNameValuePair(formString, &index); - } } @@ -278,87 +284,87 @@ BString BHttpForm::RawData() const { BString result; - + if (fType == B_HTTP_FORM_URL_ENCODED) { for (FormStorage::const_iterator it = fFields.begin(); it != fFields.end(); it++) { const BHttpFormData* currentField = &it->second; - + switch (currentField->Type()) { case B_HTTPFORM_UNKNOWN: break; - + case B_HTTPFORM_STRING: - result << '&' << BUrl::UrlEncode(currentField->Name()) + result << '&' << BUrl::UrlEncode(currentField->Name()) << '=' << BUrl::UrlEncode(currentField->String()); break; - + case B_HTTPFORM_FILE: break; - + case B_HTTPFORM_BUFFER: // Send the buffer only if its not marked as a file if (!currentField->IsFile()) { - result << '&' << BUrl::UrlEncode(currentField->Name()) + result << '&' << BUrl::UrlEncode(currentField->Name()) << '='; result.Append( - reinterpret_cast(currentField->Buffer()), + reinterpret_cast(currentField->Buffer()), currentField->BufferSize()); } break; } } - + result.Remove(0, 1); - } else if (fType == B_HTTP_FORM_MULTIPART) { - // Very slow and memory consuming method since we're caching the + } else if (fType == B_HTTP_FORM_MULTIPART) { + // Very slow and memory consuming method since we're caching the // file content, this should be preferably handled by the protocol for (FormStorage::const_iterator it = fFields.begin(); it != fFields.end(); it++) { const BHttpFormData* currentField = &it->second; result << _GetMultipartHeader(currentField); - + switch (currentField->Type()) { case B_HTTPFORM_UNKNOWN: break; - + case B_HTTPFORM_STRING: result << currentField->String(); break; - - case B_HTTPFORM_FILE: - { - BFile upFile(currentField->File().Path(), B_READ_ONLY); - char readBuffer[1024]; - ssize_t readSize; + case B_HTTPFORM_FILE: + { + BFile upFile(currentField->File().Path(), B_READ_ONLY); + char readBuffer[1024]; + ssize_t readSize; + + readSize = upFile.Read(readBuffer, 1024); + + while (readSize > 0) { + result.Append(readBuffer, readSize); readSize = upFile.Read(readBuffer, 1024); - - while (readSize > 0) { - result.Append(readBuffer, readSize); - readSize = upFile.Read(readBuffer, 1024); - } } break; - + } + case B_HTTPFORM_BUFFER: result.Append( - reinterpret_cast(currentField->Buffer()), + reinterpret_cast(currentField->Buffer()), currentField->BufferSize()); break; } - + result << "\r\n"; } - + result << "--" << fMultipartBoundary << "--\r\n"; } - + return result; } -// #pragma mark Form add +// #pragma mark - Form add status_t @@ -367,7 +373,7 @@ BHttpForm::AddString(const BString& fieldName, const BString& value) BHttpFormData formData(fieldName, value); if (!formData.InitCheck()) return B_ERROR; - + fFields.insert(pair(fieldName, formData)); return B_OK; } @@ -378,7 +384,7 @@ BHttpForm::AddInt(const BString& fieldName, int32 value) { BString strValue; strValue << value; - + return AddString(fieldName, strValue); } @@ -389,9 +395,9 @@ BHttpForm::AddFile(const BString& fieldName, const BPath& file) BHttpFormData formData(fieldName, file); if (!formData.InitCheck()) return B_ERROR; - + fFields.insert(pair(fieldName, formData)); - + if (fType != B_HTTP_FORM_MULTIPART) SetFormType(B_HTTP_FORM_MULTIPART); return B_OK; @@ -405,7 +411,7 @@ BHttpForm::AddBuffer(const BString& fieldName, const void* buffer, BHttpFormData formData(fieldName, buffer, size); if (!formData.InitCheck()) return B_ERROR; - + fFields.insert(pair(fieldName, formData)); return B_OK; } @@ -418,17 +424,17 @@ BHttpForm::AddBufferCopy(const BString& fieldName, const void* buffer, BHttpFormData formData(fieldName, buffer, size); if (!formData.InitCheck()) return B_ERROR; - - // Copy the buffer of the inserted form data copy to + + // Copy the buffer of the inserted form data copy to // avoid an unneeded copy of the buffer upon insertion pair insertResult = fFields.insert(pair(fieldName, formData)); - + return insertResult.first->second.CopyBuffer(); } -// #pragma mark Mark a field as a filename +// #pragma mark - Mark a field as a filename void @@ -436,10 +442,10 @@ BHttpForm::MarkAsFile(const BString& fieldName, const BString& filename, const BString& mimeType) { FormStorage::iterator it = fFields.find(fieldName); - + if (it == fFields.end()) return; - + it->second.MarkAsFile(filename, mimeType); if (fType != B_HTTP_FORM_MULTIPART) SetFormType(B_HTTP_FORM_MULTIPART); @@ -457,28 +463,28 @@ void BHttpForm::UnmarkAsFile(const BString& fieldName) { FormStorage::iterator it = fFields.find(fieldName); - + if (it == fFields.end()) return; - + it->second.UnmarkAsFile(); } -// #pragma mark Change form type +// #pragma mark - Change form type void BHttpForm::SetFormType(form_type type) { fType = type; - + if (fType == B_HTTP_FORM_MULTIPART) _GenerateMultipartBoundary(); } -// #pragma mark Form test +// #pragma mark - Form test bool @@ -488,17 +494,17 @@ BHttpForm::HasField(const BString& name) const } -// #pragma mark Form retrieve +// #pragma mark - Form retrieve BString BHttpForm::GetMultipartHeader(const BString& fieldName) const { FormStorage::const_iterator it = fFields.find(fieldName); - + if (it == fFields.end()) return BString(""); - + return _GetMultipartHeader(&it->second); } @@ -528,43 +534,43 @@ BHttpForm::GetMultipartFooter() const ssize_t BHttpForm::ContentLength() const -{ +{ if (fType == B_HTTP_FORM_URL_ENCODED) return RawData().Length(); - + ssize_t contentLength = 0; - + for (FormStorage::const_iterator it = fFields.begin(); it != fFields.end(); it++) { const BHttpFormData* c = &it->second; contentLength += _GetMultipartHeader(c).Length(); - + switch (c->Type()) { case B_HTTPFORM_UNKNOWN: break; - + case B_HTTPFORM_STRING: contentLength += c->String().Length(); break; - + case B_HTTPFORM_FILE: - { - BFile upFile(c->File().Path(), B_READ_ONLY); - upFile.Seek(0, SEEK_END); - contentLength += upFile.Position(); - } + { + BFile upFile(c->File().Path(), B_READ_ONLY); + upFile.Seek(0, SEEK_END); + contentLength += upFile.Position(); break; - + } + case B_HTTPFORM_BUFFER: contentLength += c->BufferSize(); break; } - + contentLength += 2; - } - + } + contentLength += fMultipartBoundary.Length() + 6; - + return contentLength; } @@ -579,7 +585,7 @@ BHttpForm::GetIterator() } -// #pragma mark Form clear +// #pragma mark - Form clear void @@ -589,7 +595,7 @@ BHttpForm::Clear() } -// #pragma mark Overloaded operators +// #pragma mark - Overloaded operators BHttpFormData& @@ -597,28 +603,28 @@ BHttpForm::operator[](const BString& name) { if (!HasField(name)) AddString(name, ""); - + return fFields[name]; } - + void BHttpForm::_ExtractNameValuePair(const BString& formString, int32* index) { // Look for a name=value pair int16 firstAmpersand = formString.FindFirst("&", *index); int16 firstEqual = formString.FindFirst("=", *index); - + BString name; BString value; - + if (firstAmpersand == -1) { if (firstEqual != -1) { formString.CopyInto(name, *index, firstEqual - *index); formString.CopyInto(value, firstEqual + 1, formString.Length() - firstEqual - 1); } else - formString.CopyInto(value, *index, + formString.CopyInto(value, *index, formString.Length() - *index); *index = formString.Length() + 1; @@ -641,17 +647,17 @@ void BHttpForm::_GenerateMultipartBoundary() { fMultipartBoundary = "----------------------------"; - + srand(time(NULL)); // TODO: Maybe a more robust way to seed the random number // generator is needed? - + for (int32 i = 0; i < kBoundaryRandomSize; i++) fMultipartBoundary << (char)(rand() % 10 + '0'); } -// #pragma mark Field information access by std iterator +// #pragma mark - Field information access by std iterator BString @@ -661,32 +667,33 @@ BHttpForm::_GetMultipartHeader(const BHttpFormData* element) const result << "--" << fMultipartBoundary << "\r\n"; result << "Content-Disposition: form-data; name=\"" << element->Name() << '"'; - + switch (element->Type()) { case B_HTTPFORM_UNKNOWN: break; - + case B_HTTPFORM_FILE: - { - result << "; filename=\"" << element->File().Leaf() << '"'; - - BNode fileNode(element->File().Path()); - BNodeInfo fileInfo(&fileNode); - - result << "\r\nContent-Type: "; - char tempMime[128]; - if (fileInfo.GetType(tempMime) == B_OK) - result << tempMime; - else - result << "application/octet-stream"; - } + { + result << "; filename=\"" << element->File().Leaf() << '"'; + + BNode fileNode(element->File().Path()); + BNodeInfo fileInfo(&fileNode); + + result << "\r\nContent-Type: "; + char tempMime[128]; + if (fileInfo.GetType(tempMime) == B_OK) + result << tempMime; + else + result << "application/octet-stream"; + break; - + } + case B_HTTPFORM_STRING: case B_HTTPFORM_BUFFER: if (element->IsFile()) { result << "; filename=\"" << element->Filename() << '"'; - + if (element->MimeType().Length() > 0) result << "\r\nContent-Type: " << element->MimeType(); else @@ -694,17 +701,19 @@ BHttpForm::_GetMultipartHeader(const BHttpFormData* element) const } break; } - + result << "\r\n\r\n"; + return result; } -// #pragma mark -- Iterator +// #pragma mark - Iterator BHttpForm::Iterator::Iterator(BHttpForm* form) - : fElement(NULL) + : + fElement(NULL) { fForm = form; fStdIterator = form->fFields.begin(); @@ -747,25 +756,25 @@ BHttpForm::Iterator::MultipartHeader() { return fForm->_GetMultipartHeader(fPrevElement); } - -BHttpForm::Iterator& + +BHttpForm::Iterator& BHttpForm::Iterator::operator=(const Iterator& other) { fForm = other.fForm; fStdIterator = other.fStdIterator; fElement = other.fElement; fPrevElement = other.fPrevElement; - + return *this; } void BHttpForm::Iterator::_FindNext() -{ +{ fPrevElement = fElement; - + if (fStdIterator != fForm->fFields.end()) { fElement = &fStdIterator->second; fStdIterator++;