Implement XDG compliance, logging, and improved 401 error handling

- Install to ~/.local/bin/winamp-mpris
- Use ~/.local/state/winamp-mpris/bridge.log for logging
- Use $XDG_RUNTIME_DIR/winamp-mpris.pid for PID management
- Add detailed user notification for 401 Unauthorized errors
- Add install.sh for automated, standard-compliant setup
- Include Winamp Web Interface source code and installer in repository
This commit is contained in:
2026-04-08 18:29:40 -04:00
parent 1e9257a27f
commit 22492dbee9
120 changed files with 9092 additions and 10 deletions

View File

@@ -0,0 +1,345 @@
/* --- CONFIG_USERS.CPP ---
/
/ Written by Phil Himsworth, 2001-2002.
/
/*/
#include <windows.h>
#include "types.h"
#include "main.h"
#include "resource.h"
#include "plugin.h"
extern winampGeneralPurposePlugin plugin;
int securepassword;
int pass_debug;
extern HWND UsersWnd;
// --------------------------------------------------------------------------------
// WindowProc for Config dialog
BOOL CALLBACK ConfigUsersWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
int nItem;
HWND hwndList;
UsersWnd = hwndDlg;
char ini_file[MAX_PATH], *p;
hwndList = GetDlgItem(hwndDlg, IDC_USERS);
GetModuleFileName(plugin.hDllInstance,ini_file,sizeof(ini_file));
p=ini_file+lstrlen(ini_file);
while (p >= ini_file && *p != '\\') p--;
if (++p >= ini_file) *p = 0;
lstrcat(ini_file,"gen_httpsrv.ini");
switch (uMsg)
{
case WM_INITDIALOG:
UpdateUserList((char*)&ini_file, hwndList);
PostMessage(hwndList,LB_SETCURSEL,0,0);
UpdateUserInfoBoxes(hwndDlg,hwndList,ini_file,0);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_USERS:
switch (HIWORD(wParam))
{
case LBN_SELCHANGE:
hwndList = GetDlgItem(hwndDlg, IDC_USERS);
nItem = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
UpdateUserInfoBoxes(hwndDlg,hwndList,ini_file,nItem);
break;
}
break;
case IDC_UPDATE:
UpdateDlgUser((char*)&ini_file, hwndDlg, hwndList);
UpdateUserList((char*)&ini_file, hwndList);
break;
case IDC_DELETE:
DeleteDlgUser((char*)&ini_file, hwndDlg, hwndList);
UpdateUserList((char*)&ini_file, hwndList);
UpdateUserInfoBoxes(hwndDlg,hwndList,(char*)&ini_file,0);
break;
}
break;
}
return false;
}
// --------------------------------------------------------------------------------
// Enters use details into relevant boxes
void UpdateUserInfoBoxes(HWND hwndDlg, HWND hwndList, char * ini_file, int item)
{
char userkey[30];
char username[20];
char password[40];
int access;
SendMessage(hwndList,LB_GETTEXT, item, (LPARAM)&username);
SetDlgItemText(hwndDlg,IDC_USERNAME,username);
GetPrivateProfileString("Users",username,"password",(char*)&password,40,ini_file);
if (StrComp(username,"anon"))
SetDlgItemText(hwndDlg,IDC_PASSWORD,"");
else
SetDlgItemText(hwndDlg,IDC_PASSWORD,password);
wsprintf(userkey, "#%s_access", username);
access = GetPrivateProfileInt("Users",userkey,AUTH_ANON,ini_file);
DisplayDlgAccess(hwndDlg,access);
}
// --------------------------------------------------------------------------------
// Marks check boxes according to user access levels
void DisplayDlgAccess(HWND hwndDlg, int access)
{
if (access & AUTH_SERVER)
CheckDlgButton(hwndDlg,IDC_AUTH_SHUTDOWN,BST_CHECKED);
else
CheckDlgButton(hwndDlg,IDC_AUTH_SHUTDOWN,BST_UNCHECKED);
if (access & AUTH_CONTROL)
CheckDlgButton(hwndDlg,IDC_AUTH_CONTROL,BST_CHECKED);
else
CheckDlgButton(hwndDlg,IDC_AUTH_CONTROL,BST_UNCHECKED);
if (access & AUTH_CLEAR)
CheckDlgButton(hwndDlg,IDC_AUTH_CLEAR,BST_CHECKED);
else
CheckDlgButton(hwndDlg,IDC_AUTH_CLEAR,BST_UNCHECKED);
if (access & AUTH_PLAYLIST)
CheckDlgButton(hwndDlg,IDC_AUTH_PLAYLIST,BST_CHECKED);
else
CheckDlgButton(hwndDlg,IDC_AUTH_PLAYLIST,BST_UNCHECKED);
if (access & AUTH_DOWNLOAD)
CheckDlgButton(hwndDlg,IDC_AUTH_DOWNLOAD,BST_CHECKED);
else
CheckDlgButton(hwndDlg,IDC_AUTH_DOWNLOAD,BST_UNCHECKED);
if (access & AUTH_BROWSE)
CheckDlgButton(hwndDlg,IDC_AUTH_BROWSE,BST_CHECKED);
else
CheckDlgButton(hwndDlg,IDC_AUTH_BROWSE,BST_UNCHECKED);
}
// --------------------------------------------------------------------------------
// Retrieves user access from check boxes
int GetDlgAccess(HWND hwndDlg)
{
int access = 0;
if (IsDlgButtonChecked(hwndDlg,IDC_AUTH_BROWSE) == BST_CHECKED)
access += 1;
if (IsDlgButtonChecked(hwndDlg,IDC_AUTH_DOWNLOAD) == BST_CHECKED)
access += 2;
if (IsDlgButtonChecked(hwndDlg,IDC_AUTH_PLAYLIST) == BST_CHECKED)
access += 4;
if (IsDlgButtonChecked(hwndDlg,IDC_AUTH_CLEAR) == BST_CHECKED)
access += 8;
if (IsDlgButtonChecked(hwndDlg,IDC_AUTH_CONTROL) == BST_CHECKED)
access += 16;
if (IsDlgButtonChecked(hwndDlg,IDC_AUTH_SERVER) == BST_CHECKED)
access += 32;
return access;
}
// --------------------------------------------------------------------------------
// Builds a list of usernames from the ini file
user * RetrieveUsers(user * users, char * ini_file)
{
bool anon = false;
int userslen, uptr, tptr;
char t_users[10000];
userslen = GetPrivateProfileSection("Users",(char*)t_users,10000,ini_file);
uptr = 0;
tptr = 0;
while(uptr < userslen) // until we're done
{
// weedle through to the end, replacing the equals sign as we go.
tptr = uptr;
//MessageBox(NULL,users+uptr,"start of section",MB_OK | MB_TOPMOST);
while(t_users[tptr] != 0)
{
if (t_users[tptr] == '=') // equals - make it a null
t_users[tptr] = 0;
tptr++;
}
if (StrComp("anon",t_users+uptr))
anon = true;
user * newuser = new user;
lstrcpy(newuser->name,t_users+uptr);
newuser->next = users;
users = newuser;
tptr++; // move to char after null
//if (users[tptr] == 0) // if it's null too, that's the lot; end
// break;
if (t_users[tptr] == '#') // if it's a hash, it's the access level - skip it
{
while(t_users[tptr] != 0)
tptr++;
tptr++;
// if (users[tptr] == 0) // if that's null it's the end
// break;
}
uptr = tptr; // move on to next
}
if (!anon) // anonymous user has not been added; add it
{
user * anonuser = new user;
lstrcpy(anonuser->name,"anon");
anonuser->next = users;
users = anonuser;
}
return users;
}
// --------------------------------------------------------------------------------
// Enters usernames into the dialog box list
void UpdateUserList(char * ini_file, HWND hwndList)
{
SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
user * users = NULL;
users = RetrieveUsers(users, ini_file); // fill list 'users' with usernames
user * current = users; // pointer to start of list
while(current != NULL)
{
SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) (current->name)); // add it
current = current->next;
delete users;
users = current;
}
}
// --------------------------------------------------------------------------------
// Updates user information in the ini file
void UpdateDlgUser(char * ini_file, HWND hwndDlg, HWND hwndList)
{
char username[20];
char password[40];
int access = GetDlgAccess(hwndDlg);
GetDlgItemText(hwndDlg,IDC_USERNAME,(char*)&username,20);
GetDlgItemText(hwndDlg,IDC_PASSWORD,(char*)&password,40);
if (StrComp(password,"password"))
{
MessageBox(hwndDlg,"Choosing a slightly better password than 'password' provides better security.","WAWI User Config",MB_OK | MB_ICONINFORMATION);
return;
}
UpdateUser(ini_file,username,password,access);
}
// --------------------------------------------------------------------------------
// Adds/updates user with passed-in information
void UpdateUser(char * ini_file,char * username, char * password, int access)
{
char debugtemp[100];
char oldmd5password[40];
char md5password[40];
char userkey[30];
char str_access[5];
wsprintf(str_access,"%d",access);
if (pass_debug == 1)
{
wsprintf(debugtemp,"User: %s\nPassword: %s\nAccess: %d",username,password,access);
MessageBox(NULL,debugtemp,"WAWI Password Debug",MB_OK | MB_TOPMOST);
}
wsprintf(userkey,"#%s_access",username);
if (securepassword == 1)
{
MD5(password,(char*)&md5password,40);
if (pass_debug == 1)
{
wsprintf(debugtemp,"MD5 encoded: %s",md5password);
MessageBox(NULL,debugtemp,"WAWI Password Debug",MB_OK | MB_TOPMOST);
}
}
else
{
ToBase64(password,(char*)&md5password);
if (pass_debug == 1)
{
wsprintf(debugtemp,"Base64 encoded: %s",md5password);
MessageBox(NULL,debugtemp,"WAWI Password Debug",MB_OK | MB_TOPMOST);
}
}
GetPrivateProfileString("Users",username,"password",(char*)&oldmd5password,40,ini_file);
if (pass_debug == 1)
{
wsprintf(debugtemp,"Previous password (or 'password' if none):\n%s",oldmd5password);
MessageBox(NULL,debugtemp,"WAWI Password Debug",MB_OK | MB_TOPMOST);
}
if (!StrComp(password,oldmd5password))
{
WritePrivateProfileString("Users",username,md5password,ini_file);
if (pass_debug == 1)
{
wsprintf(debugtemp,"Written to gen_httpsrv.ini - \nUser: %s\nPassword: %s",username,md5password);
MessageBox(NULL,debugtemp,"WAWI Password Debug",MB_OK | MB_TOPMOST);
}
}
WritePrivateProfileString("Users",userkey,str_access,ini_file);
}
// --------------------------------------------------------------------------------
// Deletes a user from the user dialog
void DeleteDlgUser(char * ini_file, HWND hwndDlg, HWND hwndList)
{
char username[20];
GetDlgItemText(hwndDlg,IDC_USERNAME,(char*)&username,20);
DeleteUser(ini_file,username);
}
// --------------------------------------------------------------------------------
// Deletes a user
void DeleteUser(char * ini_file, char * username)
{
char userkey[30];
wsprintf(userkey,"#%s_access",username);
WritePrivateProfileString("Users",username,NULL,ini_file);
WritePrivateProfileString("Users",userkey,NULL,ini_file);
}