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:
460
Wawi Source/browse.cpp
Normal file
460
Wawi Source/browse.cpp
Normal 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> </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> </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\"> </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\"> </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," ");
|
||||
}
|
||||
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\"> </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," ");
|
||||
}
|
||||
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,"·");
|
||||
printsi(conn,search.fnodes);
|
||||
prints(conn,"</p>\n");
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return ST_CLOSEBODY;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user