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,280 @@
/* --- NET_HTTP_HTML.CPP ---
/
/ Written by Phil Himsworth, 2001-2002.
/
/*/
#include <windows.h>
#include "types.h"
#include "main.h"
#include "resource.h"
#include "html.h"
// --------------------------------------------------------------------------------
// *** SOCKET FUNCTIONS ***
// Low level socket writing function - strings
void prints(connection * conn, char * string)
{
if (lstrlen(conn->output) + lstrlen(string) >= BUF_LEN)
flush(conn);
lstrcat(conn->output, string);
}
// Write full buffer down the socket
void flush(connection * conn)
{
int i = lstrlen(conn->output);
if (send(conn->socket,conn->output,i,0) == SOCKET_ERROR)
{
//MessageBox(NULL,"Socket send() error!","gen_httpsrv error",MB_OK);
}
// Clear buffer - set first char to null character
conn->output[0] = 0;
}
// Low level socket writing function - integers
void printsi(connection * conn,int number)
{
char buffer[256];
wsprintf(buffer,"%d",number); // Stick it in a string and call prints()
prints(conn,(char*)&buffer);
}
// Report an error to the client
void ReportError(connection * conn, char * errstring)
{
OpenHTTPHeader(conn,"text/html",0,NULL);
OpenHtmlHeader(conn);
Style(conn);
CloseHeader(conn);
OpenPageBody(conn);
prints(conn,"<h3>Error!</h3>\n");
prints(conn,errstring);
prints(conn,"<p>Back to <a href=\"\\\">main page</a></p>\n");
}
// 400 Bad Request error
void Send400(connection * conn)
{
prints(conn,"HTTP/1.0 400 Bad Request\nConnection: close\nContent-type: \"text/html\"\n\n");
OpenHtmlHeader(conn);
Style(conn);
CloseHeader(conn);
OpenPageBody(conn);
prints(conn,"<h3>403 Bad Request</h3>\n");
prints(conn,"<p>Your browser sent a request that this server could not understand.</p>\n");
prints(conn,"<p>Invalid URI in request ");
prints(conn,conn->http.request);
prints(conn," ");
prints(conn,conn->http.file);
prints(conn," ");
prints(conn,conn->http.http_version);
prints(conn,"</p>\n<hr>\n<address>Wawi - Winamp HTTP Server</address>\n");
CloseBody(conn);
};
// --------------------------------------------------------------------------------
// Receives HTTP header and puts relevant information into http_request structure
bool GetRequest(connection * conn)
{
char buffer[2048];
int buffer_len;
int buffer_filled = 0;
int buffer_left;
bool complete = false;
while(true)
{
// receive data
buffer_len = sizeof(buffer);
buffer_left = buffer_len-buffer_filled;
if (buffer_left <= 0)
buffer_len = 0;
else
buffer_len = recv(conn->socket,buffer + buffer_filled,buffer_len-buffer_filled,0);
if (buffer_len != SOCKET_ERROR && buffer_len != 0)
{
buffer_filled += buffer_len;
// scan for end of header
for (int i=0;i<=buffer_filled;i++)
if (buffer[i]=='\n' && (buffer[i+1]=='\n' || buffer[i+2]=='\n'))
{
buffer[i+1] = 0;
//MessageBox(NULL,buffer,"gen_httpsrv debug", MB_OK);
char * chptr = (char*)&buffer;
chptr = GetAString(chptr,conn->http.request);
chptr = GetAString(chptr,conn->http.file);
chptr = GetAString(chptr,conn->http.http_version);
FindBasicAuth(conn,chptr);
if (StrComp(conn->http.request,"HEAD"))
conn->http.reqID = RID_HEAD;
else
conn->http.reqID = RID_GET;
if (!DecodeUrl(conn))
return false;
//ListArgs(conn);
return true;
}
}
else
{
return false;
}
}
}
// --------------------------------------------------------------------------------
// Faffs around with the URL; splits 'page' from 'file' and places args in array
bool DecodeUrl(connection * conn)
{
lstrcpy(conn->http.page,conn->http.file); // make page = file
conn->http.num_args = 0;
char * chptr = conn->http.file;
while (chptr[0] != '?') // skip past '?' url?name=value
{
if (chptr[0] == 0)
{
//MessageBox(NULL,"No args","decodeurl",MB_TOPMOST | MB_OK);
return true; // no '?', no arguments
}
chptr++;
}
chptr[0] = 0;
lstrcpy(conn->http.page,conn->http.file); // alter page to remove arguments
chptr[0] = '?';
chptr++;
//char temp[100];
int x=0;
while(x < 50) // max name/value pairs; usually stopped by return in loop
{
chptr = GetDelimitedString(chptr,'=',conn->http.pairs[x].name,30);
if (chptr == NULL)
{
//MessageBox(NULL,"no value","decodeurl",MB_TOPMOST | MB_OK);
return false;
}
chptr++;
chptr = GetDelimitedString(chptr,'&',conn->http.pairs[x].value,128);
if (chptr == NULL)
{
//MessageBox(NULL,"All args","decodeurl",MB_TOPMOST | MB_OK);
conn->http.num_args = x+1;
return true;
}
chptr++;
//wsprintf(temp,"name: %s\nvalue: %s",conn->http.pairs[x].name,conn->http.pairs[x].value);
//MessageBox(NULL,temp,"arg",MB_OK | MB_TOPMOST);
x++;
}
return false;
}
// --------------------------------------------------------------------------------
// Test function to list the arguments retrieved from the requested URL
void ListArgs(connection * conn)
{
int x=0;
char string[100];
while (conn->http.pairs[x].name[0] != 0)
{
wsprintf(string,"Name: %s\nValue: %s",conn->http.pairs[x].name,conn->http.pairs[x].value);
MessageBox(NULL,string,"args",MB_OK | MB_TOPMOST);
x++;
}
}
// --------------------------------------------------------------------------------
// Return the value of an argument
bool GetArgValue(connection * conn, char * name, char * value, int len)
{
int x=0;
while(conn->http.pairs[x].name[0] != 0)
{
if (StrComp(name,conn->http.pairs[x].name))
{
//MessageBox(NULL,conn->http.pairs[x].value,"found",MB_OK | MB_TOPMOST);
lstrcpyn(value,conn->http.pairs[x].value,len);
for (int i=0;i<lstrlen(value);i++)
if (value[i]=='+')
value[i] = ' ';
return true;
}
x++;
}
return false;
}
// --------------------------------------------------------------------------------
// Removes '%20's and the like from a string
void Unescape_url(char * url)
{
int x,y;
for(x=0,y=0;url[y];++x,++y) {
if((url[x] = url[y]) == '%')
{
url[x] = x2c(&url[y+1]);
y+=2;
}
}
url[x] = 0;
}
// --------------------------------------------------------------------------------
// Returns a single character from a '%xx' string
char x2c(char *what)
{
char digit;
digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
digit *= 16;
digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
return(digit);
}
// --------------------------------------------------------------------------------
// Formats string into a URL properly
void Escape_url(char * url)
{
char echars[] = " <>#%{}|\\^~[]`;/?:@=&"; // characters which have to be escaped
char eurl[255];
int x=0,y=0;
while (url[x] != 0)
{
if (contains(echars,url[x]))
{
wsprintf(eurl+y,"%%%2x",url[x]);
y+=3;
x++;
}
else
{
eurl[y] = url[x];
y++;
x++;
}
}
eurl[y] = 0;
lstrcpy(url,eurl);
}