#include "AMFObject.h" #include void AMFMixedArray::DebugPrint(int spaces, wchar_t *&str, size_t &len) { AMFTypeList::iterator itr; StringCchCopyEx(str, len, L"Mixed Array [\n", &str, &len, 0); for (itr=array.begin();itr!=array.end();itr++) { for (int i=0;ifirst.c_str() != 0 && itr->first.c_str()[0]) StringCchPrintfEx(str, len, &str, &len, 0, L"%s: ", itr->first.c_str()); if (itr->second) itr->second->DebugPrint(spaces+1, str, len); else StringCchCopyEx(str, len, L"(null)\n", &str, &len, 0); } StringCchCopyEx(str, len, L"]\n", &str, &len, 0); } size_t AMFMixedArray::Read(uint8_t *data, size_t size) { size_t read = 0; uint32_t maxIndex = FLV::Read32(data); // TODO? array.reserve(maxIndex); data += 4; size -= 4; read += 4; while (size) { AMFString amfString; size_t skip = amfString.Read(data, size); data += skip; size -= skip; read += skip; uint8_t type = *data; data++; size--; read++; AMFType *obj = MakeObject(type); if (obj) { obj->type = type; size_t skip = obj->Read(data, size); data += skip; size -= skip; read += skip; array[amfString.str] = obj; } else break; if (type == TYPE_TERMINATOR) break; } return read; } AMFMixedArray::~AMFMixedArray() { for (AMFTypeList::iterator itr=array.begin();itr!=array.end();itr++) { delete itr->second; } } void AMFObj::DebugPrint(int spaces, wchar_t *&str, size_t &len) { StringCchCopyEx(str, len, L"Object (TODO)\n", &str, &len, 0); } size_t AMFObj::Read(uint8_t *data, size_t size) { size_t read = 0; while (size) { AMFString amfString; size_t skip = amfString.Read(data, size); data += skip; size -= skip; read += skip; uint8_t type = *data; data++; size--; read++; AMFType *obj = MakeObject(type); if (obj) { obj->type = type; size_t skip = obj->Read(data, size); data += skip; size -= skip; read += skip; } else return false; if (type == TYPE_TERMINATOR) break; } return read; } void AMFArray::DebugPrint(int spaces, wchar_t *&str, size_t &len) { StringCchCopyEx(str, len, L"Array [\n", &str, &len, 0); for (size_t i=0;i!=array.size();i++) { for (int s=0;sDebugPrint(spaces+1, str, len); } StringCchCopyEx(str, len, L"]\n", &str, &len, 0); } size_t AMFArray::Read(uint8_t *data, size_t size) { size_t read = 0; uint32_t arrayLength = FLV::Read32(data); array.reserve(arrayLength); data += 4; read += 4; size -= 4; for (uint32_t i=0;i!=arrayLength;i++) { uint8_t type = *data; data++; read++; size--; AMFType *obj = MakeObject(type); size_t skip = obj->Read(data, size); //array[i]=obj; array.push_back(obj); data += skip; read += skip; size -= skip; } return read; } AMFArray::~AMFArray() { for (size_t i=0;i!=array.size();i++) { delete array[i]; } } /* --- String --- */ AMFString::AMFString() : str(0) {} AMFString::~AMFString() { free(str); } void AMFString::DebugPrint(int spaces, wchar_t *&str, size_t &len) { StringCchPrintfEx(str, len, &str, &len, 0, L"%s\n", this->str); } size_t AMFString::Read(uint8_t *data, size_t size) { if (size < 2) return 0; unsigned __int16 strlength = FLV::Read16(data); data += 2; size -= 2; if (strlength > size) return 0; char *utf8string = (char *)calloc(strlength, sizeof(char)); memcpy(utf8string, data, strlength); int wideLen = MultiByteToWideChar(CP_UTF8, 0, utf8string, strlength, 0, 0); str = (wchar_t *)calloc(wideLen + 2, sizeof(wchar_t)); MultiByteToWideChar(CP_UTF8, 0, utf8string, strlength, str, wideLen); str[wideLen] = 0; free(utf8string); return strlength + 2; } /* --- Long String --- */ AMFLongString::AMFLongString() : str(0) {} AMFLongString::~AMFLongString() { free(str); } void AMFLongString::DebugPrint(int spaces, wchar_t *&str, size_t &len) { StringCchPrintfEx(str, len, &str, &len, 0, L"%s\n", this->str); } size_t AMFLongString::Read(uint8_t *data, size_t size) { if (size < 4) return 0; uint32_t strlength = FLV::Read32(data); data += 4; size -= 4; if (strlength > size) return 0; char *utf8string = (char *)calloc(strlength, sizeof(char)); memcpy(utf8string, data, strlength); int wideLen = MultiByteToWideChar(CP_UTF8, 0, utf8string, strlength, 0, 0); str = (wchar_t *)calloc(wideLen + 2, sizeof(wchar_t)); MultiByteToWideChar(CP_UTF8, 0, utf8string, strlength, str, wideLen); str[wideLen] = 0; free(utf8string); return strlength + 4; } /* --- Double --- */ void AMFDouble::DebugPrint(int spaces, wchar_t *&str, size_t &len) { StringCchPrintfEx(str, len, &str, &len, 0, L"%f\n", val); } /* --- Boolean --- */ void AMFBoolean::DebugPrint(int spaces, wchar_t *&str, size_t &len) { StringCchPrintfEx(str, len, &str, &len, 0, L"%s\n", boolean?L"true":L"false"); } /* --- Time --- */ static size_t MakeDateString(__time64_t convertTime, wchar_t *dest, size_t destlen) { SYSTEMTIME sysTime; tm *newtime = _localtime64(&convertTime); dest[0] = 0; // so we can bail out easily if (newtime) { sysTime.wYear = (WORD)(newtime->tm_year + 1900); sysTime.wMonth = (WORD)(newtime->tm_mon + 1); sysTime.wDayOfWeek = (WORD)newtime->tm_wday; sysTime.wDay = (WORD)newtime->tm_mday; sysTime.wHour = (WORD)newtime->tm_hour; sysTime.wMinute = (WORD)newtime->tm_min; sysTime.wSecond = (WORD)newtime->tm_sec; sysTime.wMilliseconds = 0; int charsWritten = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &sysTime, NULL, dest, (int)destlen); if (charsWritten) { size_t dateSize = charsWritten-1; dest += dateSize; destlen -= dateSize; if (destlen) { *dest++ = L' '; destlen--; dateSize++; } int charsWritten2 = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &sysTime, NULL, dest, (int)destlen); if (charsWritten2) { dateSize+=(charsWritten2-1); } return dateSize; } } return 1; } void AMFTime::DebugPrint(int spaces, wchar_t *&str, size_t &len) { size_t written = MakeDateString((__time64_t)val, str, len); str+=written; len-=written; if (len>=2) { str[0]='\n'; str[1]=0; len--; str++; } } /* --- Terminator --- */ void AMFTerminator::DebugPrint(int spaces, wchar_t *&str, size_t &len) { StringCchCopyEx(str, len, L"array terminator\n", &str, &len, 0); } /* --- Reference --- */ void AMFReference::DebugPrint(int spaces, wchar_t *&str, size_t &len) { StringCchPrintfEx(str, len, &str, &len, 0, L"%u\n", val); }