winamp/Src/Winamp/JSAPI2_Security.cpp
2024-09-24 14:54:57 +02:00

255 lines
7.6 KiB
C++

#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