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

460
Wawi Source/browse.cpp Normal file
View File

@@ -0,0 +1,460 @@
/* --- BROWSE.CPP ---
/
/ Written by Phil Himsworth, 2001-2002.
/
/ Contains everything for the "Browse Music Collection" pages.
/*/
#include <windows.h>
#include "types.h"
#include "main.h"
#include "resource.h"
#include "html.h"
/* All this lot made obsolete by using all local vars instead -
Should make it more thread-safe, anyway (even if it seems to
work anyway...)
int dnodes=0;
int fnodes=0;
char tempstring[200];
fileinfo * firstfile;
fileinfo * firstdir;
*/
extern int show_other_files, dl_other_files, dl_wa_files, frames;
extern char filetypes[255];
extern char mp3root[MAX_PATH];
// --------------------------------------------------------------------------------
// Removes the topmost directory to go to parent directory
void UpDirectory(char * mp3path, char * mp3pathout)
{
int c=0;
while(mp3path[c] != 0) // increment c until it is at end of mp3path
c++;
c-=2; // c is now character before last slash
while(mp3path[c] != '\\') // decrement c to find second to last slash
c--;
c++;
mp3pathout[c] = 0;
c--; // c now points at last required character
while(c>=0)
{
mp3pathout[c] = mp3path[c]; // copy rest of string across
c--;
}
}
// --------------------------------------------------------------------------------
// Tests whether the current name is a Winamp-readable file or not (by file extension)
bool IsWinampFile(fileinfo * file)
{
file->playlist = false; // clear playlist flag - it's random otherwise
file->urlsct = false;
char * xtn; // eXTensioN
int c=0;
while(file->name[c] != 0) // increment c until it is at end of mp3path
c++;
while(file->name[c] != '.') // decrement c to find last period
c--;
xtn = &file->name[c+1]; // extension should now be 'mp3', 'wav' etc.
if (StrComp("m3u",xtn)) // one-off check to see if the file is a playlist
file->playlist=true; // mark as a playlist.
if (StrComp("url",xtn)) // check if the file is a URL shortcut
file->urlsct = true; // mark as such
// It could return here, but then m3u/url files would be unblockable
int ptr = 0; // pointer within 'filetypes'
while(filetypes[ptr] != 0)
{
if (StartString(xtn,filetypes+ptr)) // Check xtn with current filetype in list
return true;
else // No match; next type in list
{
while(filetypes[ptr] != 0 && filetypes[ptr] != ' ')
ptr++;
if (filetypes[ptr] == ' ')
ptr++; // Space; move pointer to next type
}
}
return false; // Should never reach here!
}
// --------------------------------------------------------------------------------
// Wrapper around above for just doing filenames, not fileinfo structures
bool IsWinampFile(char * filename)
{
int strlength=0;
while(filename[strlength] != 0)
strlength++;
fileinfo file;
ZeroMemory(&file,sizeof(file));
CopyMemory(file.name,filename,strlength);
return IsWinampFile(&file);
}
// --------------------------------------------------------------------------------
// Adds a file / directory etc. to the appropriate list
void AddFileToList(connection * conn,WIN32_FIND_DATA *find, char* mp3path, filesearch * search)
{
char mp3pathout[MAX_PATH];
fileinfo *currentfile = search->firstfile;
fileinfo *currentdir = search->firstdir;
// Directories
if ((find->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) // dir
{
// Current directory '.'
if (StrComp(find->cFileName,".")) // this directory; do nothing
return;
// Parent Directory '..'
if (StrComp(find->cFileName,"..")) // parent directory
{
if (mp3path[1]==0) // already at root directory
return;
UpDirectory(mp3path, (char*)&mp3pathout);
prints(conn, "<b><font color=red>[</font><a href=\"/browse?path=");
prints(conn, mp3pathout);
prints(conn, "\">Up</a><font color=red>]</font></b><br>\n");
return;
}
// Hidden directory
if ((find->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == FILE_ATTRIBUTE_HIDDEN)
{
return;
}
// System directory? Eh? *** Look at this ***
if ((find->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM)
{
return;
}
// normal directory
fileinfo *newfile = new fileinfo;
search->dnodes++;
CopyMemory(&newfile->path,mp3path,MAX_PATH);
CopyMemory(&newfile->name,find->cFileName,MAX_PATH);
newfile->next = NULL;
newfile->prev = NULL;
// No entries in list
if (!search->firstdir)
{
search->firstdir = newfile;
return;
}
else // already entries in list
{
if (GoesBefore(newfile->name,search->firstdir->name))
{
search->firstdir->prev = newfile;
newfile->next = search->firstdir;
search->firstdir = newfile;
}
else // not first in list
{
Insert(newfile,search->firstdir);
}
}
}
else
{
// files
/*
This new version with linked lists NO LONGER checks for Winamp files here!
All files are added to the list in the correct order.
*/
fileinfo *newfile = new fileinfo;
search->fnodes++;
CopyMemory(&newfile->path,mp3path,MAX_PATH);
CopyMemory(&newfile->name,find->cFileName,MAX_PATH);
newfile->next = NULL;
newfile->prev = NULL;
// No entries in list
if (!search->firstfile)
{
search->firstfile = newfile;
return;
}
else // already entries in list
{
if (GoesBefore(newfile->name,search->firstfile->name))
{
search->firstfile->prev = newfile;
newfile->next = search->firstfile;
search->firstfile = newfile;
}
else // new file should not be first in list
{
Insert(newfile,search->firstfile);
}
}
}
}
// --------------------------------------------------------------------------------
// Checks for ../ to ensure selected directory cannot be higher than mp3root
bool GoodPath(char* mp3path)
{
int i=0;
while (mp3path[i] != 0 && i<MAX_PATH)
{
if (mp3path[i]=='.' && i<(MAX_PATH-2))
if (mp3path[i+1]=='.' && mp3path[i+2]=='\\')
return false;
i++;
}
return true;
}
// --------------------------------------------------------------------------------
// Lists selected directory
int Browse(connection * conn,char * mp3path)
{
filesearch search;
search.firstfile = NULL;
search.firstdir = NULL;
Unescape_url(mp3path);
char mp3cd[MAX_PATH]; // when it's finished with...
wsprintf(mp3cd,"%s%s",mp3root,mp3path);
OpenHTTPHeader(conn,"text/html",0,NULL);
if (conn->http.reqID == RID_HEAD)
return ST_CLOSE;
OpenHtmlHeader(conn);
Style(conn);
CloseHeader(conn);
OpenPageBody(conn);
if (frames == 1)
LinkBar(conn);
prints(conn,"<h3>\n<i>\n... Music Collection ...\n</i></h3>\n");
prints(conn,"<h3>");
prints(conn,mp3path);
prints(conn,"</h3>\n");
WIN32_FIND_DATA find;
HANDLE file;
if (!GoodPath(mp3path))
{
prints(conn,"<p><b>Error!</b></p>\n<p>The path requested is illegal.</p>\n<p>It contains the <b>..</b> directory, which could present a security risk.</p>\n");
prints(conn,"<p>&nbsp;</p>\n");
}
else
{
if (!SetCurrentDirectory(mp3cd))
{
prints(conn,"<p><b>Error!</b></p>\n<p>Couldn't open directory. Ensure you haven't mistyped the path, and that the Music Collection root directory is correct.</p>\n");
prints(conn,"<p>&nbsp;</p>\n");
}
else
{
char temp[MAX_PATH], temp2[MAX_PATH];
// Build linked list
file = FindFirstFile("*", &find);
if (file != INVALID_HANDLE_VALUE)
{
AddFileToList(conn,&find,mp3path,&search);
int done = 1;
while (done != 0)
{
done = FindNextFile(file, &find);
if (done != 0)
AddFileToList(conn,&find,mp3path,&search);
}
FindClose(file);
// Print out the linked list
prints(conn,"<p>\n\n");
// table format?
prints(conn,"<table border=\"0\" width=\"100%\" cellspacing=\"2\">\n");
fileinfo *oldnode = NULL;
fileinfo *currentdir = search.firstdir;
while (currentdir != NULL)
{
wsprintf(temp,"%s%s",currentdir->path,currentdir->name);
Escape_url(temp);
prints(conn,"<tr>\n");
// gap on the left
prints(conn,"<td width=\"50\">&nbsp;</td>\n");
prints(conn,"<td width=\"20\">");
wsprintf(temp2,"/ld?path=%s", temp);
ImgLink(conn,temp2,IDR_PLAYDIR,"Load this directory",0,0,T_BOTTOM);
prints(conn,"</td>\n");
prints(conn,"<td width=\"20\">"); // <a href="/browse?path= mp3path cFileName">cFileName</a><br>
wsprintf(temp2,"/browse?path=%s%%5c",temp);
ImgLink(conn,temp2,IDR_DIRECTORY,"Explore this directory",0,0,T_MAIN);
prints(conn,"</td>\n<td width=\"520\"><a href=\"/browse?path=");
prints(conn,temp); // mp3path + name
prints(conn,"%5c\"><b>");
prints(conn,currentdir->name);
prints(conn,"</b></a></td>\n");
prints(conn,"</tr>\n");
oldnode = currentdir;
currentdir = currentdir->next;
delete oldnode;
search.dnodes--;
}
oldnode = NULL;
fileinfo *currentfile = search.firstfile;
while (currentfile != NULL)
{
wsprintf(temp,"%s%s",currentfile->path,currentfile->name);
Escape_url(temp);
if (IsWinampFile(currentfile))
{
prints(conn,"<tr>\n");
// gap on the left
prints(conn,"<td width=\"50\">&nbsp;</td>\n");
// Download link - disk picture
prints(conn,"<td width=\"20\">");
if (dl_wa_files == 1)
{
wsprintf(temp2,"/dl?file=%s",temp);
ImgLink(conn,temp2,IDR_DOWNLOAD,"Download this file",0,0,T_MAIN);
}
else
{
prints(conn,"&nbsp;");
}
prints(conn,"</td>\n");
// Play link - WA file picture
prints(conn,"<td width=\"20\">");
wsprintf(temp2,"/ld?path=%s",temp);
if (currentfile->playlist)
ImgLink(conn,temp2,IDR_PLAYLIST,"Load this playlist",0,0,T_BOTTOM);
else
if (currentfile->urlsct)
ImgLink(conn,temp2,IDR_URLSCT,"Load this URL",0,0,T_BOTTOM);
else
ImgLink(conn,temp2,IDR_WAFILE,"Load this track",0,0,T_BOTTOM);
// Play link - text name
wsprintf(temp2,"</td>\n<td width=\"520\"><a href=\"/ld?path=%s",temp);
prints(conn,temp2);
if (frames == 3)
prints(conn,"\" target=\"bottom\">");
else
prints(conn,"\">");
prints(conn,currentfile->name);
prints(conn,"</a></td>\n");
prints(conn,"</tr>\n");
}
else // not a winamp file
{
if (show_other_files == 1)
{
prints(conn,"<tr>\n");
// gap on the left
prints(conn,"<td width=\"50\">&nbsp;</td>\n");
prints(conn,"<td width=\"20\">");
if (dl_other_files == 1)
{
wsprintf(temp2,"/dl?file=%s",temp);
ImgLink(conn,temp2,IDR_DOWNLOAD,"Download this file",0,0,T_MAIN);
}
else
{
prints(conn,"&nbsp;");
}
prints(conn,"</td>\n");
prints(conn,"<td width=\"20\">");
Img(conn,IDR_FILE,"This is not a winamp file",0,0);
prints(conn,"</td>\n<td width=\"*\"><font color=\"#A0A0A0\">"); // non-winamp file - display greyed out
prints(conn,currentfile->name);
prints(conn,"</font></td>\n");
prints(conn,"</tr>\n");
}
}
oldnode = currentfile;
currentfile = currentfile->next;
delete oldnode;
search.fnodes--;
}
prints(conn,"</table>");
prints(conn,"\n</p>\n");
/*
// Undeleted nodes count
prints(conn,"<p>");
printsi(conn,search.dnodes);
prints(conn,"&middot;");
printsi(conn,search.fnodes);
prints(conn,"</p>\n");
*/
}
}
}
return ST_CLOSEBODY;
}