aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Input/in_flv/AMFObject.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/Input/in_flv/AMFObject.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Plugins/Input/in_flv/AMFObject.cpp')
-rw-r--r--Src/Plugins/Input/in_flv/AMFObject.cpp319
1 files changed, 319 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_flv/AMFObject.cpp b/Src/Plugins/Input/in_flv/AMFObject.cpp
new file mode 100644
index 00000000..a0c5be38
--- /dev/null
+++ b/Src/Plugins/Input/in_flv/AMFObject.cpp
@@ -0,0 +1,319 @@
+#include "AMFObject.h"
+#include <strsafe.h>
+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;i<spaces;i++)
+ StringCchCopyEx(str, len, L" ", &str, &len,0);
+
+ if (itr->first.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;s<spaces;s++)
+ StringCchCopyEx(str, len, L" ", &str, &len,0);
+ StringCchPrintfEx(str, len, &str, &len, 0, L"%u: ", i);
+ array[i]->DebugPrint(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);
+}