diff --git a/CastIt.vcxproj b/CastIt.vcxproj index 84f5f10..acd95ab 100644 --- a/CastIt.vcxproj +++ b/CastIt.vcxproj @@ -97,7 +97,7 @@ Level3 true ProgramDatabase - $(ProjectDir);libxml2-2.4.9/include;curl/include;%(AdditionalIncludeDirectories) + $(ProjectDir);curl/include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) .\Debug\ true @@ -128,7 +128,7 @@ Windows .\Debug\CastIt.exe %(AdditionalLibraryDirectories) - curl/lib/curlstatic.lib;libxml2-2.4.9/win32/libxml2/libxml2_a/libxml2.lib;ws2_32.lib;%(AdditionalDependencies) + curl/lib/curlstatic.lib;ws2_32.lib;msxml6.lib;%(AdditionalDependencies) @@ -142,7 +142,7 @@ MaxSpeed true Level3 - $(ProjectDir);libxml2-2.4.9/include;curl/include;%(AdditionalIncludeDirectories) + $(ProjectDir);curl/include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) .\Release\ true @@ -170,7 +170,7 @@ Windows .\Release\CastIt.exe %(AdditionalLibraryDirectories) - curl/lib/curlstatic.lib;libxml2-2.4.9/win32/libxml2/libxml2_a/libxml2.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;wsock32.lib;%(AdditionalDependencies) + curl/lib/curlstatic.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;wsock32.lib;msxml6.lib;%(AdditionalDependencies) @@ -185,7 +185,7 @@ Level3 true ProgramDatabase - $(ProjectDir);libxml2-2.4.9/include;curl/include;%(AdditionalIncludeDirectories) + $(ProjectDir);curl/include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) .\x64\Debug\ true @@ -216,7 +216,7 @@ Windows .\x64\Debug\CastIt.exe %(AdditionalLibraryDirectories) - curl/lib/curlstatic.lib;libxml2-2.4.9/win32/libxml2/libxml2_a/libxml2.lib;ws2_32.lib;%(AdditionalDependencies) + curl/lib/curlstatic.lib;ws2_32.lib;msxml6.lib;%(AdditionalDependencies) @@ -230,7 +230,7 @@ MaxSpeed true Level3 - $(ProjectDir);libxml2-2.4.9/include;curl/include;%(AdditionalIncludeDirectories) + $(ProjectDir);curl/include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) .\x64\Release\ true @@ -258,7 +258,7 @@ Windows .\x64\Release\CastIt.exe %(AdditionalLibraryDirectories) - curl/lib/curlstatic.lib;libxml2-2.4.9/win32/libxml2/libxml2_a/libxml2.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;wsock32.lib;%(AdditionalDependencies) + curl/lib/curlstatic.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;wsock32.lib;msxml6.lib;%(AdditionalDependencies) diff --git a/README.md b/README.md index 61fd304..6c0346d 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Studio 2022._ 2. Rebuild in Visual Studio 2022 for x86/x64 targets 3. Update dependency paths for: - `libcurl` - - `libxml2` + - `MSXML` - `mysqlclient` 4. Restore and modernize installer pipeline 5. Tag a 2025 re-release binary diff --git a/scastd.cpp b/scastd.cpp index 77a1eb7..a709011 100644 --- a/scastd.cpp +++ b/scastd.cpp @@ -2,7 +2,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -15,9 +16,6 @@ #include #include #endif -#include "libxml2/include/libxml2/libxml/nanohttp.h" -#include "libxml2/include/libxml2/libxml/tree.h" -#include "libxml2/include/libxml2/libxml/parser.h" #include #include @@ -82,15 +80,6 @@ CString URLizeint(int data) return tempString; } -void parseWebdata(xmlNodePtr cur) -{ - - while (cur != NULL) { - fprintf(stdout, "Webdata: %s\n", cur->name); - cur = cur->next; - } - -} void replaceQuote(char *buf) { for (char *p1 = buf;p1 < buf+strlen(buf); p1++) { if (*p1 == '\'') { @@ -151,32 +140,195 @@ char *URLCall(CString URL) return Result.memory; } + +static void GetNodeTextA(IXMLDOMNode* node, char* buf, size_t bufSize) { + if (!node || !buf) { + return; + } + BSTR bstrText = NULL; + if (SUCCEEDED(node->get_text(&bstrText)) && bstrText) { + WideCharToMultiByte(CP_UTF8, 0, bstrText, -1, buf, (int)bufSize, NULL, NULL); + } else { + if (bufSize > 0) { + buf[0] = '\0'; + } + } + if (bstrText) { + SysFreeString(bstrText); + } +} + +static void ParseStatsNode(IXMLDOMNode* node, serverData* pData, CString serverMountpoint) { + if (!node || !pData) { + return; + } + + BSTR bstrName = NULL; + if (FAILED(node->get_nodeName(&bstrName)) || !bstrName) { + return; + } + CString name(bstrName); + SysFreeString(bstrName); + + if (name.CompareNoCase("source") == 0) { + bool processSource = true; + IXMLDOMElement* elem = NULL; + if (SUCCEEDED(node->QueryInterface(IID_IXMLDOMElement, (void**)&elem)) && elem) { + VARIANT var; + VariantInit(&var); + BSTR attr = SysAllocString(L"mount"); + if (SUCCEEDED(elem->getAttribute(attr, &var)) && var.vt == VT_BSTR) { + CString mount(var.bstrVal); + if (mount.CompareNoCase(serverMountpoint) != 0) { + processSource = false; + } + } else { + IXMLDOMNodeList* children = NULL; + if (SUCCEEDED(elem->get_childNodes(&children)) && children) { + long len = 0; + children->get_length(&len); + bool found = false; + for (long i = 0; i < len && !found; ++i) { + IXMLDOMNode* child = NULL; + if (SUCCEEDED(children->get_item(i, &child)) && child) { + BSTR childName = NULL; + child->get_nodeName(&childName); + if (childName && !wcscmp(childName, L"mount")) { + BSTR childText = NULL; + child->get_text(&childText); + if (childText) { + CString value(childText); + if (value.CompareNoCase(serverMountpoint) == 0) { + found = true; + } + SysFreeString(childText); + } + } + if (childName) SysFreeString(childName); + child->Release(); + } + } + children->Release(); + processSource = found; + } + } + VariantClear(&var); + SysFreeString(attr); + elem->Release(); + } + if (!processSource) { + return; + } + } + + char value[1024]; + GetNodeTextA(node, value, sizeof(value)); + if (name.CompareNoCase("server_type") == 0) { + strcpy_s(pData->icecast2_stream_type, sizeof(pData->icecast2_stream_type), value); + } else if (name.CompareNoCase("ice-bitrate") == 0) { + pData->icecast2_bitrate = atoi(value); + } else if (name.CompareNoCase("bitrate") == 0) { + pData->bitrate = atoi(value); + } else if (name.CompareNoCase("ice-quality") == 0) { + pData->icecast2_quality = atoi(value); + } else if (name.CompareNoCase("ice-channels") == 0) { + pData->icecast2_channels = atoi(value); + } else if (name.CompareNoCase("ice-samplerate") == 0) { + pData->icecast2_samplerate = atoi(value); + } else if (name.CompareNoCase("connections") == 0) { + pData->icecast2_connections = atoi(value); + } else if (name.CompareNoCase("listeners") == 0) { + pData->icecast2_listeners = atoi(value); + } else if (name.CompareNoCase("listener_peak") == 0) { + pData->icecast2_peak_listeners = atoi(value); + } else if (name.CompareNoCase("server_description") == 0) { + strcpy_s(pData->icecast2_serverdescription, sizeof(pData->icecast2_serverdescription), value); + } else if (name.CompareNoCase("artist") == 0) { + if (strlen(value) > 0) { + StringCchCatA(pData->songTitle, _countof(pData->songTitle), value); + StringCchCatA(pData->songTitle, _countof(pData->songTitle), " - "); + } + } else if (name.CompareNoCase("genre") == 0) { + strcpy_s(pData->serverGenre, sizeof(pData->serverGenre), value); + } else if (name.CompareNoCase("server_name") == 0) { + strcpy_s(pData->streamName, sizeof(pData->streamName), value); + } else if (name.CompareNoCase("title") == 0) { + if (strlen(value) > 0) { + StringCchCatA(pData->songTitle, _countof(pData->songTitle), value); + } + } else if (name.CompareNoCase("CURRENTLISTENERS") == 0) { + pData->currentListeners = atoi(value); + } else if (name.CompareNoCase("PEAKLISTENERS") == 0) { + pData->peakListeners = atoi(value); + } else if (name.CompareNoCase("MAXLISTENERS") == 0) { + pData->maxListeners = atoi(value); + } else if (name.CompareNoCase("REPORTEDLISTENERS") == 0) { + pData->reportedListeners = atoi(value); + } else if (name.CompareNoCase("AVERAGETIME") == 0) { + pData->avgTime = atoi(value); + } else if (name.CompareNoCase("WEBHITS") == 0) { + pData->webHits = atoi(value); + } else if (name.CompareNoCase("STREAMHITS") == 0) { + pData->streamHits = atoi(value); + } else if (name.CompareNoCase("SERVERTITLE") == 0) { + strcpy_s(pData->streamName, sizeof(pData->streamName), value); + } else if (name.CompareNoCase("SERVERGENRE") == 0) { + strcpy_s(pData->serverGenre, sizeof(pData->serverGenre), value); + } else if (name.CompareNoCase("SONGTITLE") == 0) { + strcpy_s(pData->songTitle, sizeof(pData->songTitle), value); + } else if (name.CompareNoCase("CONTENT") == 0 || name.CompareNoCase("content_type") == 0) { + strcpy_s(pData->sc_content_type, sizeof(pData->sc_content_type), value); + } else if (name.CompareNoCase("unique_nodes") == 0) { + pData->currentListeners = atoi(value); + } else if (name.CompareNoCase("max_nodes") == 0) { + pData->maxListeners = atoi(value); + } else if (name.CompareNoCase("average_connect_time") == 0) { + pData->avgTime = atoi(value); + } else if (name.CompareNoCase("tuneins") == 0) { + pData->streamHits = atoi(value); + } else if (name.CompareNoCase("meta_song") == 0) { + strcpy_s(pData->songTitle, sizeof(pData->songTitle), value); + } else if (name.CompareNoCase("name") == 0) { + strcpy_s(pData->streamName, sizeof(pData->streamName), value); + } else if (name.CompareNoCase("description") == 0) { + strcpy_s(pData->icecast2_serverdescription, sizeof(pData->icecast2_serverdescription), value); + } else if (name.CompareNoCase("url") == 0) { + strcpy_s(pData->serverURL, sizeof(pData->serverURL), value); + } + + IXMLDOMNode* child = NULL; + if (SUCCEEDED(node->get_firstChild(&child)) && child) { + while (child) { + IXMLDOMNode* next = NULL; + child->get_nextSibling(&next); + ParseStatsNode(child, pData, serverMountpoint); + child = next; + } + } + if (child) { + child->Release(); + } +} + int getStats(CString serverURL, CString serverPassword, int serverType, CString serverMountpoint, serverData *pData, char *errorMessage, size_t errorMessageSize) { - xmlDocPtr doc = NULL; - int ret = 0; - char *p1; - xmlNodePtr cur; - xmlNodePtr cur2; - xmlNodePtr cur3; char query[4096] = ""; int port = 0; int sleeptime = 0; CString fullURL; int srvcheck = 0; - - + fullURL = serverURL; - + if (strcpy_s(pData->serverURL, sizeof(pData->serverURL), serverURL) != 0) { LogMessage(LOG_ERROR, "serverURL truncated"); } - + pData->serverType = serverType; if (serverType == 0) { CString tempString = ""; - + tempString.Format("?pass=%s&mode=viewxml", serverPassword); fullURL += "/admin.cgi" + tempString; } @@ -187,362 +339,94 @@ int getStats(CString serverURL, CString serverPassword, int serverType, CString if (serverType == 2) { fullURL += "/status.xml"; } - + char *buffer = URLCall(fullURL); - + if (buffer) { - + if (strstr(buffer, "SHOUTcast Administrator")) { - - if (sprintf_s(errorMessage, errorMessageSize, "Bad password\n(%s)", serverPassword) < 0) { - errorMessage[0] = '\\0'; + + if (sprintf_s(errorMessage, errorMessageSize, "Bad password +(%s)", serverPassword) < 0) { + errorMessage[0] = '\0'; } LogMessage(LOG_ERROR, errorMessage); return 0; } - else { - p1 = buffer; - if (p1) { - doc = xmlParseMemory(p1, strlen(p1)); - if (!doc) { - //commented out for nt service - if (sprintf_s(errorMessage, errorMessageSize, "Bad parse! (%s)", serverURL) < 0) { - errorMessage[0] = '\\0'; - } - LogMessage(LOG_ERROR,"Bad xml parse"); - return 0; - } - - cur = xmlDocGetRootElement(doc); - if (cur == NULL) { - //commented out for nt service - if (sprintf_s(errorMessage, errorMessageSize, "Empty Document! (%s)", serverURL) < 0) { - errorMessage[0] = '\\0'; - } - LogMessage(LOG_ERROR,"Empty Document"); - xmlFreeDoc(doc); - return 0; - } - else {//parse xml stats from servers - memset(pData->songTitle, '\000', sizeof(pData->songTitle)); - cur = cur->xmlChildrenNode; - while (cur != NULL) { - // This is an Icecast 2 XML doc - if (!xmlStrcmp(cur->name, (const xmlChar *) "source")) { - if (!xmlStrcmp(xmlGetProp(cur, (const xmlChar *) "mount"), (const xmlChar *)(LPCSTR)serverMountpoint)) { - cur2 = cur->xmlChildrenNode; - while (cur2 != NULL) { - - if (!xmlStrcmp(cur2->name, (const xmlChar *)"server_type")) { - memset(pData->icecast2_stream_type, '\000', sizeof(pData->icecast2_stream_type)); - char *p1 = (char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1); - if (p1) { - strcpy_s(pData->icecast2_stream_type, sizeof(pData->icecast2_stream_type), p1); - } - } - - if (!xmlStrcmp(cur2->name, (const xmlChar *)"ice-bitrate")) { - pData->icecast2_bitrate = atoi((char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode,1)); - } - - if (!xmlStrcmp(cur2->name, (const xmlChar *)"bitrate")) { - pData->icecast2_bitrate = atoi((char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode,1)); - } - - if (!xmlStrcmp(cur2->name, (const xmlChar *)"ice-quality")) { - pData->icecast2_quality = atoi((char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode,1)); - } - if (!xmlStrcmp(cur2->name, (const xmlChar *)"ice-channels")) { - pData->icecast2_channels = atoi((char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode,1)); - } - if (!xmlStrcmp(cur2->name, (const xmlChar *)"ice-samplerate")) { - pData->icecast2_samplerate = atoi((char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode,1)); - } - - if (!xmlStrcmp(cur2->name, (const xmlChar *)"connections")) { - pData->icecast2_connections = atoi((char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode,1)); - } - if (!xmlStrcmp(cur2->name, (const xmlChar *)"listeners")) { - pData->icecast2_listeners = atoi((char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode,1)); - } - if (!xmlStrcmp(cur2->name, (const xmlChar *)"listener_peak")) { - pData->icecast2_peak_listeners = atoi((char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode,1)); - } - - - - - if (!xmlStrcmp(cur2->name, (const xmlChar *)"server_description")) { - memset(pData->icecast2_serverdescription, '\000', sizeof(pData->icecast2_serverdescription)); - char *p1 = (char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1); - if (p1) { - strcpy_s(pData->icecast2_serverdescription, sizeof(pData->icecast2_serverdescription), p1); - } - } - if (!xmlStrcmp(cur2->name, (const xmlChar *)"artist")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1); - if (p1) { - if (strlen(p1) > 0) { - StringCchCatA(pData->songTitle, _countof(pData->songTitle), p1); - StringCchCatA(pData->songTitle, _countof(pData->songTitle), " - "); - } - } - } - if (!xmlStrcmp(cur2->name, (const xmlChar *)"genre")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1); - if (p1) { - if (strlen(p1) > 0) { - strcpy_s(pData->serverGenre, sizeof(pData->serverGenre), p1); - } - } - } - if (!xmlStrcmp(cur2->name, (const xmlChar *)"server_name")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1); - if (p1) { - if (strlen(p1) > 0) { - strcpy_s(pData->streamName, sizeof(pData->streamName), p1); - } - } - } - if (!xmlStrcmp(cur2->name, (const xmlChar *)"title")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1); - if (p1) { - if (strlen(p1) > 0) { - StringCchCatA(pData->songTitle, _countof(pData->songTitle), p1); - } - } - } - cur2 = cur2->next; - } - } - } - if (!xmlStrcmp(cur->name, (const xmlChar *) "CURRENTLISTENERS")) { - pData->currentListeners = atoi((char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); - } - if (!xmlStrcmp(cur->name, (const xmlChar *) "PEAKLISTENERS")) { - pData->peakListeners = atoi((char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); - } - if (!xmlStrcmp(cur->name, (const xmlChar *) "MAXLISTENERS")) { - pData->maxListeners = atoi((char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); - } - if (!xmlStrcmp(cur->name, (const xmlChar *) "REPORTEDLISTENERS")) { - pData->reportedListeners = atoi((char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); - } - if (!xmlStrcmp(cur->name, (const xmlChar *) "AVERAGETIME")) { - pData->avgTime = atoi((char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); - } - if (!xmlStrcmp(cur->name, (const xmlChar *) "WEBHITS")) { - pData->webHits = atoi((char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); - } - if (!xmlStrcmp(cur->name, (const xmlChar *) "STREAMHITS")) { - pData->streamHits = atoi((char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); - } - if (!xmlStrcmp(cur->name, (const xmlChar *) "BITRATE")) { - pData->bitrate = atoi((char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); - } - - - if (!xmlStrcmp(cur->name, (const xmlChar *) "SERVERTITLE")) { - memset(pData->streamName, '\000', sizeof(pData->streamName)); - char *p1 = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - if (p1) { - strcpy_s(pData->streamName, sizeof(pData->streamName), p1); - } - } - - if (!xmlStrcmp(cur->name, (const xmlChar *) "SERVERGENRE")) { - memset(pData->serverGenre, '\000', sizeof(pData->serverGenre)); - char *p1 = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - if (p1) { - strcpy_s(pData->serverGenre, sizeof(pData->serverGenre), p1); - } - } - - if (!xmlStrcmp(cur->name, (const xmlChar *) "SONGTITLE")) { - memset(pData->songTitle, '\000', sizeof(pData->songTitle)); - char *p1 = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - if (p1) { - strcpy_s(pData->songTitle, sizeof(pData->songTitle), p1); - } - } - if (!xmlStrcmp(cur->name, (const xmlChar *) "CONTENT")) { - memset(pData->sc_content_type, '\000', sizeof(pData->sc_content_type)); - char *p1 = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - if (p1) { - strcpy_s(pData->sc_content_type, sizeof(pData->sc_content_type), p1); - } - } - // This is an Steamcast XML doc - if (!xmlStrcmp(cur->name, (const xmlChar *) "sources")) { - cur2 = cur->xmlChildrenNode; - while (cur2 != NULL) { - if (!xmlStrcmp(cur2->name, (const xmlChar *)"source")) { - bool ourSource = false; - cur3 = cur2->xmlChildrenNode; - while (cur3 != NULL) { - if (!xmlStrcmp(cur3->name, (const xmlChar *) "mount")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - if (!strcmp(p1, (LPCSTR)serverMountpoint)) { - ourSource = true; - break; - } - } - } - cur3 = cur3->next; - } - if (ourSource) { - cur3 = cur2->xmlChildrenNode; - while (cur3 != NULL) { - if (!xmlStrcmp(cur3->name, (const xmlChar *) "mount")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "status")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "name")) { - memset(pData->streamName, '\000', sizeof(pData->streamName)); - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - strcpy_s(pData->streamName, sizeof(pData->streamName), p1); - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "description")) { - memset(pData->icecast2_serverdescription, '\000', sizeof(pData->icecast2_serverdescription)); - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - strcpy_s(pData->icecast2_serverdescription, sizeof(pData->icecast2_serverdescription), p1); - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "genre")) { - memset(pData->serverGenre, '\000', sizeof(pData->serverGenre)); - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - strcpy_s(pData->serverGenre, sizeof(pData->serverGenre), p1); - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "url")) { - memset(pData->serverURL, '\000', sizeof(pData->serverURL)); - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - strcpy_s(pData->serverURL, sizeof(pData->serverURL), p1); - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "bitrate")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - pData->bitrate = atoi((char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "meta_song")) { - memset(pData->songTitle, '\000', sizeof(pData->songTitle)); - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - strcpy_s(pData->songTitle, sizeof(pData->songTitle), p1); - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "meta_url")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "nodes")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "unique_nodes")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - pData->currentListeners = atoi((char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "max_nodes")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - pData->maxListeners = atoi((char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "average_connect_time")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - pData->avgTime = atoi((char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "tuneins")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - pData->streamHits = atoi((char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "connect_time")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "bytes_recv")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "bytes_sent")) { - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - } - } - if (!xmlStrcmp(cur3->name, (const xmlChar *) "content_type")) { - memset(pData->sc_content_type, '\000', sizeof(pData->sc_content_type)); - char *p1 = (char *)xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); - if (p1) { - strcpy_s(pData->sc_content_type, sizeof(pData->sc_content_type), p1); - } - } - cur3 = cur3->next; - } - } - } - cur2 = cur2->next; - } - } - cur = cur->next; - } - - - - - }//end parsing xml stats from servers - if (strlen(pData->songTitle) > 0) { - trimRight(pData->songTitle); - replaceQuote(pData->songTitle); - } + + HRESULT hr = CoInitialize(NULL); + if (FAILED(hr)) { + LogMessage(LOG_ERROR, "Failed to initialize COM"); + return 0; + } + + IXMLDOMDocument* pDoc = NULL; + hr = CoCreateInstance(CLSID_DOMDocument60, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pDoc); + if (FAILED(hr) || !pDoc) { + LogMessage(LOG_ERROR, "Failed to create DOMDocument"); + CoUninitialize(); + return 0; + } + + pDoc->put_async(VARIANT_FALSE); + + BSTR xml = NULL; + int len = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, NULL, 0); + if (len > 0) { + xml = SysAllocStringLen(NULL, len); + MultiByteToWideChar(CP_UTF8, 0, buffer, -1, xml, len); + } + + VARIANT_BOOL loaded = VARIANT_FALSE; + if (xml) { + pDoc->loadXML(xml, &loaded); + } + if (!xml || loaded != VARIANT_TRUE) { + if (sprintf_s(errorMessage, errorMessageSize, "Bad parse! (%s)", serverURL) < 0) { + errorMessage[0] = '\0'; } - else { - - if (sprintf_s(errorMessage, errorMessageSize, "Bad data from %s\n", serverURL) < 0) { - errorMessage[0] = '\\0'; - } - LogMessage(LOG_ERROR,errorMessage); - return 0; + LogMessage(LOG_ERROR, "Bad xml parse"); + if (xml) SysFreeString(xml); + pDoc->Release(); + CoUninitialize(); + return 0; + } + SysFreeString(xml); + + IXMLDOMElement* root = NULL; + pDoc->get_documentElement(&root); + if (!root) { + if (sprintf_s(errorMessage, errorMessageSize, "Empty Document! (%s)", serverURL) < 0) { + errorMessage[0] = '\0'; } + LogMessage(LOG_ERROR, "Empty Document"); + pDoc->Release(); + CoUninitialize(); + return 0; + } + + memset(pData->songTitle, '\000', sizeof(pData->songTitle)); + ParseStatsNode(root, pData, serverMountpoint); + + root->Release(); + pDoc->Release(); + CoUninitialize(); + + if (strlen(pData->songTitle) > 0) { + trimRight(pData->songTitle); + replaceQuote(pData->songTitle); } } - //LOG AND SEND ERROR MESSAGES HERE IF SERVERS ARE DOWN else { - if (sprintf_s(errorMessage, errorMessageSize, "SERVER %s IS DOWN\n", serverURL) < 0) { - errorMessage[0] = '\\0'; + if (sprintf_s(errorMessage, errorMessageSize, "SERVER %s IS DOWN +", serverURL) < 0) { + errorMessage[0] = '\0'; } LogMessage(LOG_ERROR,errorMessage); srvcheck = 1; - - } - //END SENDING ERROR MESSAGES - if (doc) { - xmlFreeDoc(doc); + } return 1; } +