13#if __DCL_HAVE_ALLOC_DEBUG
14#undef __DCL_ALLOC_LEVEL
15#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
31#define __DCL_TRACE1_N __DCL_TRACE1
32#define __DCL_TRACE2_N __DCL_TRACE2
33#define __DCL_TRACE3_N __DCL_TRACE3
35#define __DCL_TRACE1_N(fmt, arg)
36#define __DCL_TRACE2_N(fmt, arg1, arg2)
37#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
48 const ByteString& _contents,
49 ListedStringToStringMap& _results
52 ByteStringArray elements;
53 _contents.split(
';', elements);
55 for(ByteStringArray::Iterator it = elements.begin();
56 it != elements.end(); it++) {
61 (*it).split(
'=', pair);
62 ByteStringArray::Iterator itPair = pair.begin();
64 if (itPair != pair.end()) {
68 if (itPair != pair.end()) {
72 _results[UTF8Decoder::decode(name)] =
73 UTF8Decoder::decode(value);
79 const ByteString& _queryString,
80 ListedStringToStringArrayMap& _results
85 _queryString.data() + _queryString.length(),
93 ListedStringToStringArrayMap& _results
96 ByteStringArray elements;
97 ByteString::split(_begin, _end,
'&', elements);
99 for(ByteStringArray::Iterator it = elements.begin();
100 it != elements.end(); it++)
102 ByteStringArray pair;
106 (*it).split(L
'=', pair);
107 ByteStringArray::Iterator itPair = pair.begin();
109 if (itPair != pair.end()) {
112 if (!name.isEmpty()) {
114 value = itPair != pair.end() ?
117 (_results[UTF8Decoder::decode(name)])
118 .add(UTF8Decoder::decode(value));
125 const char* _contentType
129 && *_contentType !=
'\0');
131 while(isspace((wint_t)*_contentType))
134 return ByteString::compareNoCase(
136 "application/x-www-form-urlencoded",
142 const ListedStringToStringArrayMap& _map
145 ByteStringBuilder sb;
147 for(ListedStringToStringArrayMap::ConstIterator it = _map.begin();
148 _map.end() != it; it++)
153 const ByteString name = UTF8Encoder::encode((*it).key);
154 const StringArray& values = (*it).value;
155 for(
size_t i = 0; i < values.size(); i++) {
158 sb += UTF8Encoder::encode(values[i]);
167String HttpFormData::PartHeader::toString()
const
170 sb.append(L
"type[").append(type)
171 .append(L
"], name[").append(name)
172 .append(L
"], filename[").append(filename)
173 .append(L
"], contentType[").append(contentType)
181bool HttpFormData::onFileStart(
182 const PartHeader& header,
183 void** ppCallbackData,
184 String& strCallbackError
188 size_t* pTotalSize =
new size_t;
193 *ppCallbackData = pTotalSize;
198bool HttpFormData::onFileData(
202 String& strCallbackError
206 size_t* pTotalSize = (
size_t*)pCallbackData;
207 *pTotalSize += nSize;
212bool HttpFormData::onFileEnd(
213 const PartHeader& header,
216 String& strCallbackError
220 size_t* pTotalSize = (
size_t*)pCallbackData;
222 StringBuilder sb = L
"Warning! name=\"";
223 sb += header.name + L
"\" filename=\"";
224 sb += header.filename + L
"\" ";
225 sb += String::valueOf(*pTotalSize) + L
" bytes";
227 sb += L
", in data error";
228 sb += L
", discarded\n";
237HttpFormDataDecoderException::HttpFormDataDecoderException(
243 m_errorCode = errorCode;
246HttpFormDataDecoderException::HttpFormDataDecoderException(
252 m_errorCode = errorCode;
259 switch(m_errorCode) {
260 case ePostReadError :
261 str = L
"HTTP POST read error - See Detail Exception";
263 case eFormDataCallbackError :
264 str = L
"HttpFormData Object callback error";
270 if (!m_strMsg.isEmpty()) {
271 str += L
": " + m_strMsg;
287 __bufferSize = _bufferSize;
291 __contentDisposition =
"Content-Disposition";
292 __contentType =
"Content-Type";
294 __filename =
"filename";
307 const char* _contentType,
308 size_t _contentLength,
309 ListedStringToStringArrayMap& _mapForm,
317 __contentLength = _contentLength;
318 __remainder = _contentLength;
320 ByteString boundary =
"--";
322 ByteString strOrgBoundary = getBoundary(_contentType);
323 if (strOrgBoundary.isEmpty()) {
324 appendWarning(L
"Error! invalid boundary");
327 boundary = boundary + strOrgBoundary;
330 __DCL_ASSERT(__bufferSize > (
size_t)(boundary.length() + 2));
335 appendWarning(L
"Warning! Input data empty");
339 bool bNextPart = getFirstBoundary(boundary);
342 HttpFormData::PartHeader header;
343 if (!getPartHeader(header)) {
344 appendWarning(L
"Warning! not found boundary delimiter");
356 if (header.filename.isEmpty()) {
358 ByteStringBuilder value;
362 DataState ds = dsNeedMoreData;
363 while((ds = getDataBlock(boundary, _begin, _end)) == dsNeedMoreData) {
365 value.append(_begin, _end);
374 if (ds == dsNeedMoreData) {
378 String strMsg = header.name
379 + L
": invalid data, discarded";
380 appendWarning(strMsg);
389 value.append(_begin, _end);
392 (_mapForm[header.name]).add(UTF8Decoder::decode(value));
394 if (ds == dsBeforeCloseBoundary)
400 void* pCallbackData =
NULL;
401 String strCallbackError;
402 if (!_mapFormFile.onFileStart(
410 HttpFormDataDecoderException::eFormDataCallbackError,
417 DataState ds = dsNeedMoreData;
418 while((ds = getDataBlock(boundary, _begin, _end)) == dsNeedMoreData) {
421 if (!_mapFormFile.onFileData(
428 HttpFormDataDecoderException::eFormDataCallbackError,
441 if (!_mapFormFile.onFileEnd(
447 __DCL_TRACE1(L
"HttpFormData::onFileEnd: %ls\n", strCallbackError.data());
454 if (ds == dsNeedMoreData) {
458 String strMsg = header.name
459 + L
":\"" + header.filename
460 + L
"\": invalid data, discarded";
462 appendWarning(strMsg);
465 if (!_mapFormFile.onFileEnd(
471 __DCL_TRACE1(L
"HttpFormData::onFileEnd: %s\n", strCallbackError.data());
479 if (!_mapFormFile.onFileData(
487 HttpFormDataDecoderException::eFormDataCallbackError,
493 if (!_mapFormFile.onFileEnd(
501 HttpFormDataDecoderException::eFormDataCallbackError,
506 if (ds == dsBeforeCloseBoundary)
520 char* _begin,
char* _end
524 while (_begin < _end) {
525 if (*_begin ==
CR && *(_begin + 1) ==
LF) {
534 char* _begin,
char* _end,
char _ch
537 while (_begin < _end) {
538 if (*_begin == _ch) {
546HttpFormDataDecoder::DataState
547HttpFormDataDecoder::getDataBlock(
548 const ByteString& _boundary,
559 if (!((__begin + _boundary.length() + 2) <= __end)) {
560 return dsNeedMoreData;
565 _end = _begin = __begin;
572 char* afterCRLF = atCR + 2;
574 if ((afterCRLF + _boundary.length()) <= __end) {
575 if (!memcmp(_boundary.data(), afterCRLF, _boundary.length())) {
576 DataState dsReturn = dsBeforeNextBoundary;
577 afterCRLF += _boundary.length();
578 if (afterCRLF + 2 <= __end
579 && !memcmp(afterCRLF,
"--", 2)) {
581 dsReturn = dsBeforeCloseBoundary;
604 if (__begin == _end) {
612 return dsNeedMoreData;
615bool HttpFormDataDecoder::getLine(
616 char*& _begin,
char*& _end
626 _end = __begin = atCR;
631 while (_begin < _end) {
632 if (!isspace(*_begin)) {
641bool HttpFormDataDecoder::getFirstBoundary(
642 const ByteString& _boundary
647 while(getLine(_begin, _end)) {
648 if (((_begin + _boundary.length()) <= _end)
649 && (!memcmp(_boundary.data(), _begin, _boundary.length()))) {
651 _begin += _boundary.length();
652 if (!ByteString::compare(_begin,
"--", 2)) {
663#define EQUAL_STR(str, p) (!(str).compareNoCase((p), str.length()))
664bool HttpFormDataDecoder::getPartHeader(
665 HttpFormData::PartHeader& header
671 if (!getLine(_begin, _end)) {
674 if (!getLine(_begin, _end))
678 if (!(_begin < _end)) {
688 while(isspace((
byte_t)*(++_value)));
690 if (
EQUAL_STR(__contentDisposition, _begin)) {
692 while(_begin < _end) {
700 while(isspace((
byte_t)*(++_value)));
703 header.name = UTF8Decoder::decode(_value, _next - _value).trim(L
"\"");
705 else if (
EQUAL_STR(__filename, _begin)) {
706 header.filename = UTF8Decoder::decode(_value, _next - _value).trim(L
"\"");
708 size_t index = header.filename.lastIndexOf(L
'\\');
709 if (index != (
size_t)-1) {
710 header.filename = header.filename.mid(index + 1);
714 String s = String::format(L
"unknown property [%ls]",
715 UTF8Decoder::decode(_begin, _end - _begin).data());
721 header.type = UTF8Decoder::decode(_begin, _next - _begin);
725 while (isspace((
byte_t) * (++_next)));
730 else if (
EQUAL_STR(__contentType, _begin)) {
731 header.contentType = UTF8Decoder::decode(_value, _end - _value);
734 String s = String::format(L
"Invalid header [%ls]",
735 UTF8Decoder::decode(_begin, _end - _begin).data());
744bool HttpFormDataDecoder::readInput()
750 __buffer = (
char*)malloc(__bufferSize + 1);
752 *(__buffer + __bufferSize) =
'\0';
758 size_t n = __end - __begin;
760 memmove(__buffer, __begin,
n);
762 __end = __buffer +
n;
770 size_t nCanRead = __bufferSize -
n;
771 if (__remainder < nCanRead)
772 nCanRead = __remainder;
774 size_t nRead = __input->read(__end, nCanRead);
777 __remainder -= nRead;
781 catch(IOException* eCause) {
782 throw new HttpFormDataDecoderException(
783 HttpFormDataDecoderException::ePostReadError,
791void HttpFormDataDecoder::appendWarning(
const String& _warning)
794 if (!__warnings.isEmpty())
797 __warnings += _warning;
801ByteString HttpFormDataDecoder::getBoundary(
802 const char* _contentType
807 ByteStringBuilder sb;
809 const char* p = strstr(_contentType,
"boundary");
814 while(isspace((
byte_t)*(++p)))
824bool HttpFormDataDecoder::isValidType(
const char* _contentType)
827 && *_contentType !=
'\0');
829 while(isspace((
byte_t)*_contentType))
832 return ByteString::compareNoCase(
834 "multipart/form-data",
841BufferedHttpFormData::FileInfo::FileInfo()
846#define __V() ((PointerArray*)__handle)
847BufferedHttpFormData::FileInfo&
848BufferedHttpFormData::FileInfoArray::operator[] (
size_t _index)
852 return *((FileInfo*)((*
__V())[_index]));
855size_t BufferedHttpFormData::FileInfoArray::size()
const
859 return __V()->size();
862bool BufferedHttpFormData::FileInfoArray::isEmpty()
const
866 return __V()->isEmpty();
869BufferedHttpFormData::FileInfoArray::FileInfoArray(
const String& _name)
871 __handle =
new PointerArray();
877BufferedHttpFormData::FileInfoArray::FileInfoArray(
const FileInfo& src)
883BufferedHttpFormData::FileInfoArray::~FileInfoArray()
886 PointerArray* p =
__V();
887 PointerArray& v = *p;
888 for(
size_t i = 0; i < v.size(); i++)
889 delete (FileInfo*)v[i];
894void BufferedHttpFormData::FileInfoArray::add(FileInfo* pNewItem)
897 __V()->add(pNewItem);
902 __handle =
new PointerArray();
909 PointerArray* p =
__V();
910 PointerArray& v = *p;
911 for(
size_t i = 0; i < v.size(); i++)
912 delete (FileInfoArray*)v[i];
920 return __V()->size();
927 return __V()->isEmpty();
930BufferedHttpFormData::FileInfoArray&
934 return *((FileInfoArray*)((*
__V())[_index]));
937BufferedHttpFormData::FileInfoArray&
943 FileInfoArray* pV =
NULL;
944 PointerArray& v = *(PointerArray*)__handle;
945 for(
size_t i = 0; i < v.size(); i++)
947 pV = (FileInfoArray*)(v[i]);
948 if (pV->__name == _name)
952 pV =
new FileInfoArray(_name);
957void BufferedHttpFormData::insert(
964 FileInfoArray& v =
byName(_name);
970 const PartHeader& header,
971 void** ppCallbackData,
972 String& strCallbackError
978 *ppCallbackData = pOut;
987 String& strCallbackError
994 pOut->write(pData, nSize);
1008 const PartHeader& header,
1009 void* pCallbackData,
1011 String& strCallbackError
1018 FileInfo* pInfo =
new FileInfo;
1020 pInfo->filename = header.filename;
1021 pInfo->contentType = header.contentType;
1022 pInfo->fileData = pOut->toByteString();
1026 insert(header.name, pInfo);
1035#define __V() ((PointerArray*)__handle)
1037StoredHttpFormData::FileInfo::FileInfo()
1042StoredHttpFormData::FileInfo::FileInfo(
const FileInfo& str)
1047StoredHttpFormData::FileInfo::~FileInfo()
1053 catch(IOException* e) {
1059StoredHttpFormData::FileInfo&
1060StoredHttpFormData::FileInfoArray::operator[] (
size_t _index)
1064 return *((FileInfo*)((*
__V())[_index]));
1067size_t StoredHttpFormData::FileInfoArray::size()
const
1070 return __V()->size();
1073bool StoredHttpFormData::FileInfoArray::isEmpty()
const
1076 return __V()->isEmpty();
1079StoredHttpFormData::FileInfoArray::FileInfoArray(
const String& _name)
1081 __handle =
new PointerArray;
1087StoredHttpFormData::FileInfoArray::FileInfoArray(
const FileInfo& src)
1093StoredHttpFormData::FileInfoArray::~FileInfoArray()
1096 PointerArray* p =
__V();
1097 PointerArray& v = *p;
1098 for(
size_t i = 0; i < v.size(); i++)
1099 delete (FileInfo*)v[i];
1104void StoredHttpFormData::FileInfoArray::add(FileInfo* pNewItem)
1107 __V()->add(pNewItem);
1114 __tempDir = strTempDir;
1116 __handle =
new PointerArray;
1123 PointerArray* p =
__V();
1124 PointerArray& v = *p;
1125 for(
size_t i = 0; i < v.size(); i++)
1126 delete (FileInfoArray*)v[i];
1134 return __V()->size();
1140 return __V()->isEmpty();
1143StoredHttpFormData::FileInfoArray&
1147 return *((FileInfoArray*)((*
__V())[_index]));
1150StoredHttpFormData::FileInfoArray&
1156 FileInfoArray* pV =
NULL;
1157 PointerArray& v = *(PointerArray*)__handle;
1158 for(
size_t i = 0; i < v.size(); i++) {
1159 pV = (FileInfoArray*)(v[i]);
1160 if (pV->__name == _name)
1164 pV =
new FileInfoArray(_name);
1169void StoredHttpFormData::insert(
1170 const String& _name,
1176 FileInfoArray& v =
byName(_name);
1188 const PartHeader& header,
1189 void** ppCallbackData,
1190 String& strCallbackError
1201 filename = pFile->
path();
1204 if (!filename.isEmpty()) {
1224 *ppCallbackData = pCB;
1232 void* pCallbackData,
1233 String& strCallbackError
1240 pCB->
output->write(pData, nSize);
1263 const PartHeader& header,
1264 void* pCallbackData,
1266 String& strCallbackError
1275 L
"fileSize: %zd, dataSize: %zd\n",
1298 FileInfo* pInfo =
new FileInfo;
1302 pInfo->filename = header.filename;
1303 pInfo->contentType = header.contentType;
1307 insert(header.name, pInfo);
char * __find_CHAR(char *_begin, char *_end, char _ch)
struct _STORED_CALLBACK_DATA STORED_CALLBACK_DATA
#define EQUAL_STR(str, p)
char * __find_CRLF(char *_begin, char *_end)
#define __DCL_TRACE1_N(fmt, arg)
#define __DCL_TRACE2_N(fmt, arg1, arg2)
#define __DCL_TRACE0(psz)
#define __DCL_TRACE1(fmt, arg1)
#define __DCL_ASSERT(expr)
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
void CharsetConvertException *size_t n
static String decode(const char *_mbs, size_t _mbslen=(size_t) -1)
virtual String toString() const
static File * openTempFile(const String &_dirname, const String &_prefix, unsigned int _mode=0666) __DCL_THROWS1(IOException *)
const String & path() const
static bool exists(const String &_path)
static uint64_t size(const String &_path) __DCL_THROWS1(IOException *)
static void unlink(const String &_path) __DCL_THROWS1(IOException *)
static void decode(const ByteString &_contents, ListedStringToStringMap &_results)
static void decode(const ByteString &_queryString, ListedStringToStringArrayMap &_results)
static bool isValidType(const char *_contentType)
static String encode(const ListedStringToStringArrayMap &_map)
virtual String toString() const
static ByteString decode(const char *_begin, const char *_end)
static ByteString encode(const ByteString &_str)
FileOutputStream * output