aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/JSAPI2_Security.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/Winamp/JSAPI2_Security.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Winamp/JSAPI2_Security.cpp')
-rw-r--r--Src/Winamp/JSAPI2_Security.cpp255
1 files changed, 255 insertions, 0 deletions
diff --git a/Src/Winamp/JSAPI2_Security.cpp b/Src/Winamp/JSAPI2_Security.cpp
new file mode 100644
index 00000000..3e8706b1
--- /dev/null
+++ b/Src/Winamp/JSAPI2_Security.cpp
@@ -0,0 +1,255 @@
+#include "api.h"
+#include "JSAPI2_Security.h"
+#include "JSAPI2_svc_apicreator.h"
+#include <bfc/platform/types.h>
+#include "main.h"
+#include "resource.h"
+#include "language.h"
+#include <api/service/waservicefactory.h>
+#include <shlwapi.h>
+#include <strsafe.h>
+
+JSAPI2::Security::~Security()
+{
+ for(NameMap::iterator iter = names.begin(); iter != names.end(); iter++)
+ {
+ if (NULL != iter->second)
+ free(iter->second);
+ }
+}
+
+int JSAPI2::Security::GetActionAuthorization( const wchar_t *group, const wchar_t *action, const wchar_t *authorization_key, JSAPI::ifc_info *info, int default_authorization, AuthorizationData *data )
+{
+ // TODO: benski> we should build a cache table, as we may hit this function repeatedly and it incurs a file lock
+ // but for now it will get the ball rolling
+ if ( action )
+ {
+ wchar_t group_action[ 256 ] = { 0 };
+ StringCbPrintfW( group_action, sizeof( group_action ), L"%s@%s", action, group );
+ int authorization = GetPrivateProfileIntW( authorization_key, group_action, api_security::ACTION_UNDEFINED, JSAPI2_INIFILE );
+ if ( authorization != api_security::ACTION_UNDEFINED )
+ return authorization;
+ }
+ if ( group )
+ {
+ int authorization = GetPrivateProfileIntW( authorization_key, group, api_security::ACTION_UNDEFINED, JSAPI2_INIFILE );
+ if ( authorization != api_security::ACTION_UNDEFINED )
+ return authorization;
+ }
+
+ int authorization = GetPrivateProfileIntW( authorization_key, authorization_key, default_authorization, JSAPI2_INIFILE );
+
+ if ( ( ACTION_UNDEFINED == authorization || ACTION_PROMPT == authorization ) &&
+ false != IsAuthorizationBypassed( authorization_key ) )
+ {
+ authorization = ACTION_ALLOWED;
+ }
+
+ if ( ( authorization == ACTION_UNDEFINED || authorization == ACTION_PROMPT )/* if we have to prompt */
+ && default_authorization != ACTION_UNDEFINED /* clients pass ACTION_UNDEFINED, API's don't */
+ && group )
+ {
+ waServiceFactory *sf = 0;
+ int n = 0;
+ do
+ {
+ sf = WASABI_API_SVC->service_enumService( JSAPI2::svc_apicreator::getServiceType(), n++ );
+ if ( !sf )
+ break;
+
+ if ( sf )
+ {
+ JSAPI2::svc_apicreator *creator = (JSAPI2::svc_apicreator *)sf->getInterface();
+ if ( creator )
+ {
+ HWND parent = 0;
+ if ( info )
+ parent = info->GetHWND();
+ if ( !parent )
+ parent = this->GetAssociation( authorization_key );
+
+ int prompt = creator->PromptForAuthorization( parent, group, action, authorization_key, data );
+ if ( ( prompt & JSAPI2::svc_apicreator::AUTHORIZATION_MASK ) != JSAPI2::svc_apicreator::AUTHORIZATION_UNDEFINED )
+ {
+ sf->releaseInterface( creator );
+ int new_authorization = 0;
+ switch ( prompt & JSAPI2::svc_apicreator::AUTHORIZATION_MASK )
+ {
+ case JSAPI2::svc_apicreator::AUTHORIZATION_ALLOW:
+ new_authorization = ACTION_ALLOWED;
+ break;
+ case JSAPI2::svc_apicreator::AUTHORIZATION_DENY:
+ new_authorization = ACTION_DISALLOWED;
+ break;
+ default:
+ return default_authorization;
+ }
+ if ( prompt & JSAPI2::svc_apicreator::AUTHORIZATION_FLAG_GROUP_ONLY )
+ action = 0;
+ if ( prompt & JSAPI2::svc_apicreator::AUTHORIZATION_FLAG_ALWAYS )
+ SetActionAuthorization( group, action, authorization_key, new_authorization );
+ if ( prompt & JSAPI2::svc_apicreator::AUTHORIZATION_FLAG_ALWAYS_FOR_SERVICE )
+ SetActionAuthorization( 0, 0, authorization_key, new_authorization );
+
+ return new_authorization;
+ }
+ }
+
+ sf->releaseInterface( creator );
+ }
+ } while ( sf );
+ }
+
+ return authorization;
+}
+
+int JSAPI2::Security::SetActionAuthorization(const wchar_t *group, const wchar_t *action, const wchar_t *authorization_key, int authorization)
+{
+ // TODO: benski> we should build a cache table, as we may hit this function repeatedly and it incurs a file lock
+ // but for now it will get the ball rolling
+ wchar_t intval[64] = {0};
+ _itow(authorization, intval, 10);
+ if (action)
+ {
+ wchar_t group_action[256] = {0};
+ StringCbPrintfW(group_action, sizeof(group_action), L"%s@%s", action, group);
+ WritePrivateProfileStringW(authorization_key, group_action, intval, JSAPI2_INIFILE);
+ }
+ else if (group)
+ WritePrivateProfileStringW(authorization_key, group, intval, JSAPI2_INIFILE);
+ else
+ WritePrivateProfileStringW(authorization_key, authorization_key, intval, JSAPI2_INIFILE);
+
+ return JSAPI2::api_security::SUCCESS;
+}
+
+void JSAPI2::Security::Associate(const wchar_t *authorization_key, HWND hwnd)
+{
+ unsigned long key;
+ if (FALSE == StrToIntExW(authorization_key, STIF_DEFAULT, (int*)&key))
+ return;
+
+ associations[key] = (void *)hwnd;
+}
+
+HWND JSAPI2::Security::GetAssociation(const wchar_t *authorization_key)
+{
+ unsigned long key;
+ if (FALSE == StrToIntExW(authorization_key, STIF_DEFAULT, (int*)&key))
+ return NULL;
+
+ AssociationMap::iterator iter = associations.find(key);
+ return (HWND)((iter != associations.end()) ? iter->second : NULL);
+}
+
+
+INT_PTR JSAPI2_SecurityPrompt(HWND hParent, LPCWSTR pszCaption, LPCWSTR pszTitle, LPCWSTR pszMessage, UINT flags);
+
+int JSAPI2::Security::SecurityPrompt(HWND parent, const wchar_t *title_string, const wchar_t *display_string, int flags)
+{
+ return (INT_PTR)JSAPI2_SecurityPrompt(parent, NULL, title_string, display_string, flags);
+}
+
+void JSAPI2::Security::AssociateName(const wchar_t *authorization_key, const wchar_t *name)
+{
+ unsigned long key;
+ if (FALSE == StrToIntExW(authorization_key, STIF_DEFAULT, (int*)&key))
+ return;
+
+ NameMap::iterator iter = names.find(key);
+ if (NULL != name)
+ {
+ if (iter != names.end())
+ {
+ if (NULL != iter->second) free(iter->second);
+ iter->second = _wcsdup(name);
+ }
+ else
+ {
+ names.insert({key, _wcsdup(name)});
+ }
+ }
+ else
+ {
+ if (iter != names.end())
+ {
+ if (NULL != iter->second)
+ {
+ free(iter->second);
+ iter->second = NULL;
+ }
+ names.erase(iter);
+ }
+ }
+}
+
+const wchar_t *JSAPI2::Security::GetAssociatedName(const wchar_t *authorization_key)
+{
+ unsigned long key;
+ if (FALSE == StrToIntExW(authorization_key, STIF_DEFAULT, (int*)&key))
+ return NULL;
+
+ NameMap::iterator iter = names.find(key);
+ return (iter != names.end()) ? iter->second : NULL;
+}
+
+void JSAPI2::Security::ResetAuthorization(const wchar_t *authorization_key)
+{
+ const wchar_t empty[2] = {0, 0};
+ WritePrivateProfileSectionW(authorization_key, empty, JSAPI2_INIFILE);
+}
+
+void JSAPI2::Security::SetBypass(const wchar_t *authorization_key, bool enable_bypass)
+{
+ size_t index = bypassList.size();
+
+ unsigned long key;
+ if (FALSE == StrToIntExW(authorization_key, STIF_DEFAULT, (int*)&key))
+ return;
+
+ while(index--)
+ {
+ if (bypassList[index] == key)
+ {
+ if (false == enable_bypass)
+ bypassList.erase(bypassList.begin() + index);
+ return;
+ }
+ }
+
+ if (false != enable_bypass)
+ bypassList.push_back(key);
+}
+
+bool JSAPI2::Security::IsAuthorizationBypassed(const wchar_t *authorization_key)
+{
+ size_t index = bypassList.size();
+ if (0 == index) return false;
+
+ unsigned long key;
+ if (FALSE == StrToIntExW(authorization_key, STIF_DEFAULT, (int*)&key))
+ return false;
+
+ while(index--)
+ {
+ if (bypassList[index] == key)
+ return true;
+ }
+ return false;
+}
+
+JSAPI2::Security JSAPI2::security;
+
+#define CBCLASS JSAPI2::Security
+START_DISPATCH;
+CB(JSAPI2_API_SECURITY_GETACTIONAUTHORIZATION, GetActionAuthorization);
+CB(JSAPI2_API_SECURITY_SETACTIONAUTHORIZATION, SetActionAuthorization);
+VCB(JSAPI2_API_SECURITY_ASSOCIATE, Associate);
+CB(JSAPI2_API_SECURITY_GETASSOCIATION, GetAssociation);
+CB(JSAPI2_API_SECURITY_SECURITYPROMPT, SecurityPrompt);
+VCB(JSAPI2_API_SECURITY_ASSOCIATENAME, AssociateName);
+CB(JSAPI2_API_SECURITY_GETASSOCIATEDNAME, GetAssociatedName);
+VCB(JSAPI2_API_SECURITY_RESETAUTHORIZATION, ResetAuthorization);
+VCB(JSAPI2_API_SECURITY_SETBYPASS, SetBypass);
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file