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)
40#if __DCL_HAVE_THIS_FILE__
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++
62 (*it).split(
'=', pair);
63 ByteStringArray::Iterator itPair = pair.begin();
65 if (itPair != pair.end()) {
69 if (itPair != pair.end()) {
73 _results[UTF8Decoder::decode(name)] =
74 UTF8Decoder::decode(value);
80 const ByteString& _queryString,
81 ListedStringToStringArrayMap& _results
86 _queryString.data() + _queryString.length(),
94 ListedStringToStringArrayMap& _results
97 ByteStringArray elements;
98 ByteString::split(_begin, _end,
'&', elements);
100 for(ByteStringArray::Iterator it = elements.begin();
101 it != elements.end(); it++
103 ByteStringArray pair;
107 (*it).split(L
'=', pair);
108 ByteStringArray::Iterator itPair = pair.begin();
110 if (itPair != pair.end()) {
113 if (!name.isEmpty()) {
115 value = itPair != pair.end() ?
118 (_results[UTF8Decoder::decode(name)])
119 .add(UTF8Decoder::decode(value));
126 const char* _contentType
130 && *_contentType !=
'\0');
132 while(isspace((
unsigned int)*_contentType))
135 return ByteString::compareNoCase(
137 "application/x-www-form-urlencoded",
143 const ListedStringToStringArrayMap& _map
146 ByteStringBuilder sb;
148 for(ListedStringToStringArrayMap::ConstIterator it = _map.begin();
149 _map.end() != it; it++
154 const ByteString name = UTF8Encoder::encode((*it).key);
155 const StringArray& values = (*it).value;
156 for(
size_t i = 0; i < values.size(); i++) {
159 sb += UTF8Encoder::encode(values[i]);
168String HttpFormData::PartHeader::toString()
const
171 sb.append(L
"type[").append(type)
172 .append(L
"], name[").append(name)
173 .append(L
"], filename[").append(filename)
174 .append(L
"], contentType[").append(contentType)
182bool HttpFormData::onFileStart(
183 const PartHeader& header,
184 void** ppCallbackData,
185 String& strCallbackError
189 size_t* pTotalSize =
new size_t;
194 *ppCallbackData = pTotalSize;
199bool HttpFormData::onFileData(
203 String& strCallbackError
207 size_t* pTotalSize = (
size_t*)pCallbackData;
208 *pTotalSize += nSize;
213bool HttpFormData::onFileEnd(
214 const PartHeader& header,
217 String& strCallbackError
221 size_t* pTotalSize = (
size_t*)pCallbackData;
223 StringBuilder sb = L
"Warning! name=\"";
224 sb += header.name + L
"\" filename=\"";
225 sb += header.filename + L
"\" ";
226 sb += String::valueOf(*pTotalSize) + L
" bytes";
228 sb += L
", in data error";
229 sb += L
", discarded\n";
231#ifdef __DCL_DEBUG_DELETE
233#define delete(_p) __DCL_DEBUG_DELETE(_p)
236#ifdef __DCL_DEBUG_DELETE
245HttpFormDataDecoderException::HttpFormDataDecoderException(
246 ErrorCode _errorCode,
250 __errorCode = _errorCode;
253HttpFormDataDecoderException::HttpFormDataDecoderException(
254 ErrorCode _errorCode,
255 const String& _message
258 __errorCode = _errorCode;
259 __message = _message;
265 switch(__errorCode) {
266 case ePostReadError :
267 str = L
"HTTP POST read error - See Detail Exception";
269 case eFormDataCallbackError :
270 str = L
"HttpFormData Object callback error";
276 if (!__message.isEmpty()) {
277 str += L
": " + __message;
293 __bufferSize = _bufferSize;
297 __contentDisposition =
"Content-Disposition";
298 __contentType =
"Content-Type";
300 __filename =
"filename";
313 const char* _contentType,
314 size_t _contentLength,
315 ListedStringToStringArrayMap& _mapForm,
323 __contentLength = _contentLength;
324 __remainder = _contentLength;
326 ByteString boundary =
"--";
328 ByteString strOrgBoundary = getBoundary(_contentType);
329 if (strOrgBoundary.isEmpty()) {
330 appendWarning(L
"Error! invalid boundary");
333 boundary = boundary + strOrgBoundary;
336 __DCL_ASSERT(__bufferSize > (
size_t)(boundary.length() + 2));
341 appendWarning(L
"Warning! Input data empty");
345 bool bNextPart = getFirstBoundary(boundary);
348 HttpFormData::PartHeader header;
349 if (!getPartHeader(header)) {
350 appendWarning(L
"Warning! not found boundary delimiter");
362 if (header.filename.isEmpty()) {
364 ByteStringBuilder value;
368 DataState ds = dsNeedMoreData;
369 while((ds = getDataBlock(boundary, _begin, _end)) == dsNeedMoreData) {
371 value.append(_begin, _end);
380 if (ds == dsNeedMoreData) {
384 String strMsg = header.name
385 + L
": invalid data, discarded";
386 appendWarning(strMsg);
395 value.append(_begin, _end);
398 (_mapForm[header.name]).add(UTF8Decoder::decode(value));
400 if (ds == dsBeforeCloseBoundary)
406 void* pCallbackData =
NULL;
407 String strCallbackError;
408 if (!_mapFormFile.onFileStart(
415 HttpFormDataDecoderException::eFormDataCallbackError,
422 DataState ds = dsNeedMoreData;
423 while((ds = getDataBlock(boundary, _begin, _end)) == dsNeedMoreData) {
426 if (!_mapFormFile.onFileData(
433 HttpFormDataDecoderException::eFormDataCallbackError,
446 if (!_mapFormFile.onFileEnd(
452 __DCL_TRACE1(L
"HttpFormData::onFileEnd: %ls\n", strCallbackError.data());
459 if (ds == dsNeedMoreData) {
463 String strMsg = header.name
464 + L
":\"" + header.filename
465 + L
"\": invalid data, discarded";
467 appendWarning(strMsg);
470 if (!_mapFormFile.onFileEnd(
476 __DCL_TRACE1(L
"HttpFormData::onFileEnd: %ls\n", strCallbackError.data());
484 if (!_mapFormFile.onFileData(
491 HttpFormDataDecoderException::eFormDataCallbackError,
497 if (!_mapFormFile.onFileEnd(
504 HttpFormDataDecoderException::eFormDataCallbackError,
509 if (ds == dsBeforeCloseBoundary)
523 char* _begin,
char* _end
527 while (_begin < _end) {
528 if (*_begin ==
CR && *(_begin + 1) ==
LF) {
537 char* _begin,
char* _end,
char _ch
540 while (_begin < _end) {
541 if (*_begin == _ch) {
549HttpFormDataDecoder::DataState
550HttpFormDataDecoder::getDataBlock(
551 const ByteString& _boundary,
562 if (!((__begin + _boundary.length() + 2) <= __end)) {
563 return dsNeedMoreData;
568 _end = _begin = __begin;
575 char* afterCRLF = atCR + 2;
577 if ((afterCRLF + _boundary.length()) <= __end) {
578 if (!memcmp(_boundary.data(), afterCRLF, _boundary.length())) {
579 DataState dsReturn = dsBeforeNextBoundary;
580 afterCRLF += _boundary.length();
581 if (afterCRLF + 2 <= __end
582 && !memcmp(afterCRLF,
"--", 2)) {
584 dsReturn = dsBeforeCloseBoundary;
607 if (__begin == _end) {
615 return dsNeedMoreData;
618bool HttpFormDataDecoder::getLine(
619 char*& _begin,
char*& _end
629 _end = __begin = atCR;
634 while (_begin < _end) {
635 if (!isspace(*_begin)) {
644bool HttpFormDataDecoder::getFirstBoundary(
645 const ByteString& _boundary
650 while(getLine(_begin, _end)) {
651 if (((_begin + _boundary.length()) <= _end)
652 && (!memcmp(_boundary.data(), _begin, _boundary.length()))) {
654 _begin += _boundary.length();
655 if (!ByteString::compare(_begin,
"--", 2)) {
666#define EQUAL_STR(str, p) (!(str).compareNoCase((p), str.length()))
667bool HttpFormDataDecoder::getPartHeader(
668 HttpFormData::PartHeader& header
674 if (!getLine(_begin, _end)) {
677 if (!getLine(_begin, _end))
681 if (!(_begin < _end)) {
691 while(isspace((
byte_t)*(++_value)));
693 if (
EQUAL_STR(__contentDisposition, _begin)) {
695 while(_begin < _end) {
703 while(isspace((
byte_t)*(++_value)));
706 header.name = UTF8Decoder::decode(_value, _next - _value).trim(L
"\"");
708 else if (
EQUAL_STR(__filename, _begin)) {
709 header.filename = UTF8Decoder::decode(_value, _next - _value).trim(L
"\"");
711 size_t index = header.filename.lastIndexOf(L
'\\');
712 if (index != (
size_t)-1) {
713 header.filename = header.filename.mid(index + 1);
717 String s = String::format(L
"unknown property [%ls]",
718 UTF8Decoder::decode(_begin, _end - _begin).data());
724 header.type = UTF8Decoder::decode(_begin, _next - _begin);
728 while (isspace((
byte_t) * (++_next)));
733 else if (
EQUAL_STR(__contentType, _begin)) {
734 header.contentType = UTF8Decoder::decode(_value, _end - _value);
737 String s = String::format(L
"Invalid header [%ls]",
738 UTF8Decoder::decode(_begin, _end - _begin).data());
747bool HttpFormDataDecoder::readInput()
753 __buffer = (
char*)malloc(__bufferSize + 1);
755 *(__buffer + __bufferSize) =
'\0';
761 size_t n = __end - __begin;
763 memmove(__buffer, __begin, n);
765 __end = __buffer + n;
773 size_t nCanRead = __bufferSize - n;
774 if (__remainder < nCanRead)
775 nCanRead = __remainder;
777 size_t nRead = __input->read(__end, nCanRead);
780 __remainder -= nRead;
784 catch(IOException* eCause) {
785 throw new HttpFormDataDecoderException(
786 HttpFormDataDecoderException::ePostReadError,
794void HttpFormDataDecoder::appendWarning(
const String& _warning)
796 if (!__warnings.isEmpty())
799 __warnings += _warning;
803ByteString HttpFormDataDecoder::getBoundary(
804 const char* _contentType
809 ByteStringBuilder sb;
810 const char* p = strstr(_contentType,
"boundary");
815 while(isspace((
byte_t)*(++p)))
825bool HttpFormDataDecoder::isValidType(
const char* _contentType)
828 && *_contentType !=
'\0');
830 while(isspace((
byte_t)*_contentType))
833 return ByteString::compareNoCase(
835 "multipart/form-data",
842BufferedHttpFormData::FileInfo::FileInfo()
847#define __V() ((PointerArray*)__handle)
848BufferedHttpFormData::FileInfo&
849BufferedHttpFormData::FileInfoArray::operator[] (
size_t _index)
853 return *((FileInfo*)((*
__V())[_index]));
856size_t BufferedHttpFormData::FileInfoArray::size()
const
860 return __V()->size();
863bool BufferedHttpFormData::FileInfoArray::isEmpty()
const
867 return __V()->isEmpty();
870BufferedHttpFormData::FileInfoArray::FileInfoArray(
const String& _name)
872 __handle =
new PointerArray();
878BufferedHttpFormData::FileInfoArray::FileInfoArray(
const FileInfo& src)
884BufferedHttpFormData::FileInfoArray::~FileInfoArray()
887 PointerArray* p =
__V();
888 PointerArray& v = *p;
889 for(
size_t i = 0; i < v.size(); i++)
890 delete (FileInfo*)v[i];
895void BufferedHttpFormData::FileInfoArray::add(FileInfo* pNewItem)
898 __V()->add(pNewItem);
903 __handle =
new PointerArray();
910 PointerArray* p =
__V();
911 PointerArray& v = *p;
912 for(
size_t i = 0; i < v.size(); i++)
913 delete (FileInfoArray*)v[i];
921 return __V()->size();
928 return __V()->isEmpty();
931BufferedHttpFormData::FileInfoArray&
935 return *((FileInfoArray*)((*
__V())[_index]));
938BufferedHttpFormData::FileInfoArray&
944 FileInfoArray* pV =
NULL;
945 PointerArray& v = *(PointerArray*)__handle;
946 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 = output;
987 String& strCallbackError
994 output->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 = output->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);
1190 const PartHeader& header,
1191 void** ppCallbackData,
1192 String& strCallbackError
1203 filename = pFile->
path();
1206 if (!filename.isEmpty()) {
1226 *ppCallbackData = cb;
1234 void* pCallbackData,
1235 String& strCallbackError
1242 cb->
output->write(pData, nSize);
1265 const PartHeader& header,
1266 void* pCallbackData,
1268 String& strCallbackError
1276 L
"fileSize: %zd, dataSize: %zd\n",
1297 FileInfo* pInfo =
new FileInfo;
1299 pInfo->filename = header.filename;
1300 pInfo->contentType = header.contentType;
1304 insert(header.name, pInfo);
char * __find_CHAR(char *_begin, char *_end, char _ch)
#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)
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
FileOutputStream * output
static ByteString decode(const char *_begin, const char *_end)
static ByteString encode(const ByteString &_str)