diff options
Diffstat (limited to 'Src/Plugins/Library/ml_wire/PCastURIHandler.cpp')
-rw-r--r-- | Src/Plugins/Library/ml_wire/PCastURIHandler.cpp | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/Src/Plugins/Library/ml_wire/PCastURIHandler.cpp b/Src/Plugins/Library/ml_wire/PCastURIHandler.cpp new file mode 100644 index 00000000..4b32c9c3 --- /dev/null +++ b/Src/Plugins/Library/ml_wire/PCastURIHandler.cpp @@ -0,0 +1,258 @@ +#include "main.h" +#include "./pcasturihandler.h" +#include "./Feeds.h" +#include "./FeedUtil.h" +#include "../nu/AutoLock.h" +#include "./wire.h" +#include "./errors.h" +//#include "../Agave/URIHandler/svc_urihandler.h" +//#include <api/service/waservicefactory.h> +#include "api__ml_wire.h" +#include "./cloud.h" +#include "./SubscriptionView.h" +#include "./resource.h" +#include "navigation.h" +#include "..\..\General\gen_ml/ml_ipc_0313.h" +#include <strsafe.h> + +using namespace Nullsoft::Utility; + +extern ChannelList channels; +extern Cloud cloud; + + +static uint8_t quickhex(wchar_t c) +{ + int hexvalue = c; + if (hexvalue & 0x10) + hexvalue &= ~0x30; + else + { + hexvalue &= 0xF; + hexvalue += 9; + } + return hexvalue; +} + +static uint8_t DecodeEscape(const wchar_t *&str) +{ + uint8_t a = quickhex(*++str); + uint8_t b = quickhex(*++str); + str++; + return a * 16 + b; +} + +static void DecodeEscapedUTF8(wchar_t *&output, const wchar_t *&input) +{ + uint8_t utf8_data[1024] = {0}; // hopefully big enough!! + int num_utf8_words=0; + bool error=false; + + while (input && *input == '%' && num_utf8_words < sizeof(utf8_data)) + { + if (iswxdigit(input[1]) && iswxdigit(input[2])) + { + utf8_data[num_utf8_words++]=DecodeEscape(input); + } + else if (input[1] == '%') + { + input+=2; + utf8_data[num_utf8_words++]='%'; + } + else + { + error = true; + break; + } + } + + int len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)utf8_data, num_utf8_words, 0, 0); + MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)utf8_data, num_utf8_words, output, len); + output += len; + + if (error) + { + *output++ = *input++; + } +} + +static void UrlDecode(const wchar_t *input, wchar_t *output, size_t len) +{ + const wchar_t *stop = output+len-4; // give ourself a cushion large enough to hold a full UTF-16 sequence + const wchar_t *itr = input; + while (itr && *itr) + { + if (output >= stop) + { + *output=0; + return; + } + + switch (*itr) + { + case '%': + DecodeEscapedUTF8(output, itr); + break; + case '&': + *output = 0; + return; + default: + *output++ = *itr++; + break; + } + } + *output = 0; +} +// first parameter has param name either null or = terminated, second is null terminated +static bool ParamCompare(const wchar_t *url_param, const wchar_t *param_name) +{ + while (url_param && *url_param && *param_name && *url_param!=L'=') + { + if (*url_param++ != *param_name++) + return false; + } + return true; +} + +static bool get_request_parm(const wchar_t *params, const wchar_t *param_name, wchar_t *value, size_t value_len) +{ + size_t param_name_len = wcslen(param_name); + const wchar_t *t=params; + while (t && *t && *t != L'?') // find start of parameters + t++; + + while (t && *t) + { + t++; // skip ? or & + if (ParamCompare(t, param_name)) + { + while (t && *t && *t != L'=' && *t != '&') // find start of value + t++; + switch(*t) + { + case L'=': + UrlDecode(++t, value, value_len); + return true; + case 0: + case L'&': // no value + *value=0; + return true; + default: // shouldn't get here + return false; + } + } + while (t && *t && *t != L'&') // find next parameter + t++; + } + + return false; +} + +int PCastURIHandler::ProcessFilename(const wchar_t *filename) +{ + if ( + (wcsnicmp(filename, L"pcast://", 8)) == 0 || + (wcsnicmp(filename, L"feed://", 7) == 0) || + (wcsnicmp(filename, L"winamp://Podcast/Subscribe", 26) == 0) || + (wcsnicmp(filename, L"winamp://Podcast/Search", 23) == 0) + ) + { + wchar_t *tempFilename = NULL; + wchar_t url[1024] = {0}; + if (wcsnicmp(filename, L"winamp://Podcast/Subscribe", 26) == 0) + { + // extract/decode and use the url= parameter + if (get_request_parm(filename, L"url", url, 1024) && url[0]) + { + tempFilename = wcsdup(url); + } + else + { + // did not find a url parameter + return NOT_HANDLED; + } + } + else if (wcsnicmp(filename, L"winamp://Podcast/Search", 23) == 0) + { +// TODO: maybe: if (get_request_parm(filename, L"url", url, 1024) && url[0]) + { + HNAVITEM hItem = Navigation_FindService(SERVICE_PODCAST, NULL, NULL); + MLNavItem_Select(plugin.hwndLibraryParent, hItem); + return HANDLED; + } + /* + else + { + // did not find a url parameter + return NOT_HANDLED; + } + */ + } + else + { + // Use the full filename + tempFilename = wcsdup(filename); + } + + // subscription confirmation + WCHAR szText[1024] = {0}, szBuffer[1024] = {0}; + WASABI_API_LNGSTRINGW_BUF(IDS_PODCAST_SUBSCRIPTION_PROMP, szBuffer, ARRAYSIZE(szBuffer)); + StringCchPrintf(szText, ARRAYSIZE(szText), szBuffer, tempFilename); + + WASABI_API_LNGSTRINGW_BUF(IDS_PODCAST_SUBSCRIPTION_HEADER, szBuffer, ARRAYSIZE(szBuffer)); + + if (IDYES == MessageBox(plugin.hwndLibraryParent, szText, szBuffer, MB_YESNO | MB_ICONQUESTION | MB_TOPMOST | MB_SETFOREGROUND) ) + { + // add feed to channels, pulse the cloud, refresh the UI pane. + Channel newFeed; + newFeed.SetURL(tempFilename); + if (DownloadFeedInformation(newFeed)==DOWNLOAD_SUCCESS) + { + channels.channelGuard.Lock(); + channels.AddChannel(newFeed); + channels.channelGuard.Unlock(); + cloud.Pulse(); + HWND hView = SubscriptionView_FindWindow(); + if (NULL != hView) + { + SubscriptionView_RefreshChannels(hView, TRUE); + } + else + { + HNAVITEM myItem = Navigation_FindService(SERVICE_PODCAST, NULL, NULL); + HNAVITEM podcastItem = MLNavItem_GetChild(plugin.hwndLibraryParent, myItem); + HNAVITEM subscriptionItem = Navigation_FindService(SERVICE_SUBSCRIPTION, podcastItem, NULL); + MLNavItem_Select(plugin.hwndLibraryParent, subscriptionItem); + } + } + free(tempFilename); + + return HANDLED; + + } + else + free(tempFilename); + } + return NOT_HANDLED; +} + +int PCastURIHandler::IsMine(const wchar_t *filename) +{ + int i = 0; + if ( + (wcsnicmp(filename, L"pcast://", 8)) == 0 || + (wcsnicmp(filename, L"feed://", 7) == 0) || + (wcsnicmp(filename, L"winamp://Podcast/Subscribe", 26) == 0) || + (wcsnicmp(filename, L"winamp://Podcast/Search", 23) == 0) + ) + return HANDLED; + else + return NOT_HANDLED; +} + +#define CBCLASS PCastURIHandler +START_DISPATCH; +CB(PROCESSFILENAME, ProcessFilename); +CB(ISMINE, IsMine); +END_DISPATCH; +#undef CBCLASS
\ No newline at end of file |