Compare commits

...

10 Commits

Author SHA1 Message Date
475794f95b Merge remote main and resolve README.md conflict 2026-04-08 18:36:53 -04:00
22492dbee9 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
2026-04-08 18:29:40 -04:00
1e9257a27f Add Volume control and OpenUri support
- Implement MPRIS Volume property (readwrite) with 0-10 mapping for Winamp
- Implement MPRIS OpenUri method using the discovered /url?p& endpoint
- Add Volume to PropertiesChanged signal notifications
- Update D-Bus XML interface definition
2026-03-31 12:50:19 -04:00
33d76dad99 Implement Shuffle and Repeat (LoopStatus) support
- Add Shuffle and LoopStatus readwrite properties to WinampMPRIS
- Robust regex-based parsing of Repeat/Random status from Web UI
- Dynamic property change notifications via PropertiesChanged signal
- Optimized update_loop to track and reflect playback mode changes
2026-03-21 10:51:49 -04:00
7fa164f462 Fix position synchronization, add album art fetching, and document busctl usage
- Use Web UI as authoritative time source for better MPRIS position sync
- Implement album art fetching via iTunes Search API
- Optimize window title parsing to focus on metadata
- Add busctl testing commands to README and GEMINI.md
2026-03-19 05:31:11 -04:00
21afe7650a Add D-Bus command logging and notify-send alerts for failed commands 2026-03-19 04:06:46 -04:00
06f43992d6 Finalize winamp_mpris.py with window title and web UI hybrid logic 2026-03-19 04:00:57 -04:00
e59380c929 Add comprehensive README with Winamp setup and plugin details 2026-03-19 04:00:14 -04:00
853a451d0a Add systemd user service and enhance offline robustness 2026-03-19 03:00:47 -04:00
f597c9656c Initial commit: Functional Winamp MPRIS bridge with Plasma 6 fixes 2026-03-19 02:50:17 -04:00
123 changed files with 9757 additions and 2 deletions

93
GEMINI.md Normal file
View File

@@ -0,0 +1,93 @@
# Winamp MPRIS Bridge
A Python-based bridge that provides an MPRIS2 interface for Winamp on Linux, specifically optimized for KDE Plasma 6. It allows Linux desktop environments to control Winamp and display track metadata by interacting with the Winamp Web Interface plugin.
## Project Overview
- **Purpose:** Bridges Winamp's Web Interface to the Linux MPRIS2 D-Bus specification.
- **Technologies:**
- **Python 3**: Core logic.
- **pydbus**: D-Bus communication.
- **requests**: Communicating with the Winamp Web Interface.
- **BeautifulSoup4**: Scraping metadata from the Web Interface's HTML.
- **PyGObject (GLib)**: Main event loop and signal handling.
- **Architecture:** The script runs a background thread that polls the Winamp Web Interface (default: `http://localhost:5666`) every 2 seconds, parses the HTML for metadata, and updates the D-Bus properties.
## Building and Running
### Prerequisites
Ensure you have the following Python libraries installed:
```bash
pip install requests pydbus beautifulsoup4 pygobject
```
You also need the `Winamp Web Interface` plugin installed and running in Winamp, configured with:
- **Base URL:** `http://localhost:5666`
- **Username:** `winamp`
- **Password:** `llama` (These are the current defaults in `winamp_mpris.py`)
### Running the Bridge
### Manual Run
To start the bridge manually, run:
```bash
python3 winamp_mpris.py
```
### Running as a systemd User Service
A systemd service file is provided to allow the bridge to run automatically in the background.
1. **Install the service file**:
```bash
mkdir -p ~/.config/systemd/user/
cp winamp-mpris.service ~/.config/systemd/user/
```
2. **Reload systemd and enable the service**:
```bash
systemctl --user daemon-reload
systemctl --user enable --now winamp-mpris.service
```
3. **Check the status**:
```bash
systemctl --user status winamp-mpris.service
```
The bridge will publish itself on D-Bus as `org.mpris.MediaPlayer2.winamp`. It gracefully handles Winamp being offline, automatically reconnecting when the web interface becomes available.
### Testing and Debugging
You can use `busctl` to interact with the MPRIS interface:
```bash
# Get playback status
busctl --user get-property org.mpris.MediaPlayer2.winamp /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player PlaybackStatus
# Get current position (in microseconds)
busctl --user get-property org.mpris.MediaPlayer2.winamp /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player Position
# Get metadata
busctl --user get-property org.mpris.MediaPlayer2.winamp /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player Metadata
# Send commands
busctl --user call org.mpris.MediaPlayer2.winamp /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player PlayPause
busctl --user call org.mpris.MediaPlayer2.winamp /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player Next
```
## Key Files
- **`winamp_mpris.py`**: The main bridge script. Includes optimizations for Plasma 6 property change detection, live position tracking, and robust error handling.
- **`winamp-mpris.service`**: Systemd user service unit file.
- **`winamp_mpris_old.py`**: A previous iteration of the bridge.
- **`sample_Winamp Web Interface.html`**: A sample of the HTML returned by the Winamp Web Interface, used for reference in parsing logic.
## Development Conventions
- **D-Bus Interface:** Defined via XML introspection string within the `WinampMPRIS` class.
- **Polling:** Metadata is updated by polling the web interface every 2 seconds in a daemon thread.
- **Property Changes:** Uses the `PropertiesChanged` signal to notify the desktop environment of track or status updates.
- **Error Handling:** Basic try-except blocks handle network timeouts or parsing errors, defaulting to "Stopped" or "Offline" states.

View File

@@ -1,3 +1,86 @@
# winamp-mpris # Winamp MPRIS Bridge
Daemon for integrating Winamp/WACUP with mpris media controls on Linux (KDE). A Python-based bridge that provides an MPRIS2 interface for Winamp/WACUP on Linux (running via Wine/Proton). This allows Linux desktop environments (like KDE Plasma, GNOME, or any MPRIS-compatible media widget) to control playback and display track metadata.
## Features
- **Metadata Extraction**: Primarily uses the Winamp window title for high-fidelity metadata (Artist, Album, Title).
- **Playback Controls**: Supports Play, Pause, Next, Previous, and Stop via the Winamp Web Interface.
- **Live Position Tracking**: Extrapolates playback position for smooth progress bars in your desktop's media widget.
- **Robustness**: Gracefully handles Winamp being offline and automatically reconnects when it starts.
- **Systemd Integration**: Can be run as a background user service conforming to XDG standards.
- **XDG Compliance**: Installs to `~/.local/bin`, logs to `~/.local/state/winamp-mpris/`, and stores PID in `$XDG_RUNTIME_DIR`.
## Prerequisites
### 1. Winamp Web Interface Plugin
The bridge communicates with Winamp through the **Winamp Web Interface** plugin.
- **Download**: [Winamp Web Interface v7.5.10](https://winampheritage.com/plugin/winamp-web-interface/92511) (Source included in repository).
- **Installation**: Install the plugin in Winamp/WACUP.
- **Configuration**:
1. Open Winamp Preferences -> Plug-ins -> General Purpose.
2. Configure "Winamp Web Interface".
3. Set a **Username** (default: `winamp`) and **Password** (default: `llama`).
4. Ensure the server is running (default port: `5666`).
5. In the **Users** tab, ensure the user has **Play** permissions.
### 2. Winamp/WACUP Title Formatting
To ensure the bridge can extract correct metadata, you must configure Winamp to show specific information in its window title.
- Open Winamp Preferences -> Titles.
- Set the Taskbar/Window title format to:
```text
%artist%%album%%title% | %playback_time%/%length% - Winamp
```
*(Note: The separator between Artist, Album, and Title should be an en-dash `` or a simple dash `-`)*.
### 3. Linux Dependencies
Install the required Python libraries, `wmctrl`, and `libnotify` (for notifications):
```bash
# Python dependencies
pip install requests pydbus beautifulsoup4 pygobject
# System tools
sudo dnf install wmctrl libnotify # or sudo apt install wmctrl libnotify
```
## Installation & Setup
The project includes an XDG-compliant installer:
```bash
chmod +x install.sh
./install.sh
```
This will:
1. Install the script to `~/.local/bin/winamp-mpris`.
2. Install and enable the systemd user service `winamp-mpris.service`.
3. Start the bridge immediately.
### Logs and Monitoring
- **Logs**: `tail -f ~/.local/state/winamp-mpris/bridge.log`
- **Systemd Logs**: `journalctl --user -u winamp-mpris.service -f`
- **PID File**: `$XDG_RUNTIME_DIR/winamp-mpris.pid`
### Testing with busctl
You can manually interact with the MPRIS interface:
```bash
# Get playback status
busctl --user get-property org.mpris.MediaPlayer2.winamp /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player PlaybackStatus
# Send commands
busctl --user call org.mpris.MediaPlayer2.winamp /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player PlayPause
```
## Technical Details
- **D-Bus Bus**: `org.mpris.MediaPlayer2.winamp`
- **Object Path**: `/org/mpris/MediaPlayer2`
- **Polling Rate**: 1 second (updates metadata from window title and checks Web UI for status).
## Troubleshooting
- **401 Unauthorized**: Ensure the Winamp Web Interface credentials match those in `winamp-mpris` and that the user has "Play" permissions in the plugin's Users tab.
- **Controls not working**: Ensure the Winamp Web Interface is accessible at `http://localhost:5666`.
- **No Metadata**: Ensure `wmctrl -l` can see the Winamp window and the title matches the expected format.
- **KDE Plasma 6**: If using Plasma 6 on Wayland, you may need to grant "Remote Control" permissions when prompted.

View File

@@ -0,0 +1,541 @@
/* --- CLIENTCONNECTION.CPP ---
/
/ Written by Phil Himsworth, 2001-2002.
/
/*/
#include <windows.h>
#include "types.h"
#include "wamessage.h"
#include "main.h"
#include "op_winamp.h"
#include "html.h"
#include "plugin.h"
#include "resource.h"
extern char mp3root[MAX_PATH], logfiledir[MAX_PATH];
extern int dl_wa_files, dl_other_files, frames, title_refresh;
extern char szAppVer[];
extern char pagetitle[255];
extern winampGeneralPurposePlugin plugin;
bool loglocked = false;
char realm_server[] = "Wawi Server Control";
char realm_control[] = "Wawi Playback Control";
char realm_clear[] = "Wawi Playlist Clear Control";
char realm_playlist[] = "Wawi Playlist Control";
char realm_download[] = "Wawi Downloads";
char realm_browse[] = "Wawi Music Collection";
CControl Control;
// --------------------------------------------------------------------------------
// Thread called for each connection
DWORD WINAPI ClientConnection(LPVOID socket_param) // new thread for a new client.
{
bool matched = false;
connection conn; // structure to hold request details
ZeroMemory(&conn,sizeof(conn));
conn.http.auth = AUTH_ANON;
wsprintf(conn.http.user,"anon");
conn.log = true;
conn.state = ST_NONE;
conn.http.responsecode = 200;
conn.socket = (SOCKET)socket_param; // convert param into socket
int rhost_len = sizeof(conn.remote_host);
getpeername(conn.socket,(sockaddr*)&conn.remote_host,&rhost_len);
if (!GetRequest(&conn))
{
//MessageBox(NULL,conn.http.file,"400",MB_TOPMOST | MB_OK);
conn.http.responsecode = 400;
Send400(&conn);
shutdown(conn.socket,0);
closesocket(conn.socket);
MakeLogEntry(&conn);
return true;
}
// ------------- Images ------------------
// Of the form /img?image=n where 'n' is the id of the image, eg. IDR_DIRECTORY.
if (StrComp(conn.http.page,"/img"))
{
//MessageBox(NULL,conn.http.file,"File",MB_OK | MB_TOPMOST);
//MessageBox(NULL,conn.http.page,"Page",MB_OK | MB_TOPMOST);
conn.log = false;
conn.state = Control.Image(&conn,IMG_GIF);
}
// ------------- Favicon.ico!!!-----------
// Sent the same as a img resource but with a different header
if (StrComp(conn.http.page,"/favicon.ico"))
{
//conn.log = false;
wsprintf(conn.http.file,"/img?%d",IDR_ICO_WINAMP);
conn.state = Control.Image(&conn,IMG_ICO);
}
// ------------ Top -----------------
if (StrComp(conn.http.page,"/top"))
{
conn.log = false;
conn.state = Control.TopFrame(&conn);
}
// ------------- Small Title ------------
// No page formatting at all; just the song info.
if (StrComp(conn.http.page,"/smalltitle"))
conn.state = Control.SmallTitle(&conn);
// -------------- Title ----------------
if (StrComp(conn.http.page,"/title"))
{
conn.log = false;
conn.state = Control.Title(&conn);
}
// ---------- Shutdown Computer -------------
if (StrComp(conn.http.page,"/shutdown"))
{
if (!(conn.http.auth & AUTH_SERVER))
conn.state = SendBasic401(&conn,realm_server);
else
conn.state = Control.Shutdown(&conn);
}
// ---------- Clear Playlist -----
if (StrComp(conn.http.page,"/clear"))
{
if (!(conn.http.auth & AUTH_CLEAR))
conn.state = SendBasic401(&conn,realm_playlist);
else
conn.state = Control.Clear(&conn);
}
// ---------- Sort playlist ----------
if (StrComp(conn.http.page,"/sort"))
{
if (!(conn.http.auth & AUTH_PLAYLIST))
conn.state = SendBasic401(&conn,realm_playlist);
else
conn.state = Control.Sort(&conn);
}
// ------------ Browse -----------
if (StrComp(conn.http.page,"/browse"))
{
if (!(conn.http.auth & AUTH_BROWSE))
conn.state = SendBasic401(&conn,realm_browse);
else
{
char mp3path[MAX_PATH];
if (GetArgValue(&conn,"path",(char*)&mp3path,MAX_PATH) == false)
wsprintf(mp3path,"%%5c");
ReplaceSlashes(mp3path);
conn.state = Browse(&conn, mp3path);
if (frames == 1)
LinkBar(&conn);
}
}
// ------------ Download ---------
if (StrComp(conn.http.page,"/dl"))
if (!(conn.http.auth & AUTH_DOWNLOAD))
conn.state = SendBasic401(&conn,realm_download);
else
conn.state = Control.Download(&conn);
// ------------ Load -------------
if (StrComp(conn.http.page,"/ld")) // ld = load
{
if (!(conn.http.auth & AUTH_PLAYLIST))
conn.state = SendBasic401(&conn,realm_playlist);
else
conn.state = Control.Load(&conn);
}
// ------------ List -------------
if (StrComp(conn.http.page,"/list"))
conn.state = Control.List(&conn);
// ------------ Next -------------
if (StrComp(conn.http.page,"/next")) // Next track
{
if (!(conn.http.auth & AUTH_CONTROL))
conn.state = SendBasic401(&conn,realm_control);
else
conn.state = Control.Next(&conn);
}
// ------------ Prev -------------
if (StrComp(conn.http.page,"/prev")) // Previous track
{
if (!(conn.http.auth & AUTH_CONTROL))
conn.state = SendBasic401(&conn,realm_control);
else
conn.state = Control.Prev(&conn);
}
// ------------ Play -------------
if (StrComp(conn.http.page,"/play"))
// Play (or play?xxxx)
{
if (!(conn.http.auth & AUTH_CONTROL))
conn.state = SendBasic401(&conn,realm_control);
else
conn.state = Control.Play(&conn);
}
// ------------ Stop -------------
if (StrComp(conn.http.page,"/stop"))
{
if (!(conn.http.auth & AUTH_CONTROL))
conn.state = SendBasic401(&conn,realm_control);
else
conn.state = Control.Stop(&conn);
}
// ----------- Stop slowly -----------
if (StrComp(conn.http.page,"/stopslow"))
{
if (!(conn.http.auth & AUTH_CONTROL))
conn.state = SendBasic401(&conn,realm_control);
else
conn.state = Control.StopSlow(&conn);
}
// ------------ Pause ------------
if (StrComp(conn.http.page,"/pause"))
{
if (!(conn.http.auth & AUTH_CONTROL))
conn.state = SendBasic401(&conn,realm_control);
else
conn.state = Control.Pause(&conn);
}
// ------------ Volume -----------
if (StrComp(conn.http.page,"/vol"))
{
if (!(conn.http.auth & AUTH_CONTROL))
conn.state = SendBasic401(&conn,realm_control);
else
conn.state = Control.Volume(&conn);
}
// ----------- Random / Repeat --------------
if (StrComp(conn.http.page,"/playmode"))
{
if (!(conn.http.auth & AUTH_CONTROL))
conn.state = SendBasic401(&conn,realm_control);
else
conn.state = Control.Playmode(&conn);
}
// ------------- Login/out---------------
if (StrComp(conn.http.page,"/login"))
conn.state = SendBasic401(&conn,"Winamp Web Interface");
// ------------ About ----------------
if (StrComp(conn.http.page,"/about"))
{
conn.state = Control.About(&conn);
}
// ---------- Delete playlist entry ----
if (StrComp(conn.http.page,"/delete"))
{
if (!(conn.http.auth & AUTH_CLEAR))
conn.state = SendBasic401(&conn,realm_clear);
else
conn.state = Control.Delete(&conn);
}
// ---------- Stylesheet -------------
if (StrComp(conn.http.page,"/wawi.css"))
{
conn.log = false;
conn.state = Control.UserStyle(&conn);
}
// ------------ Main page ----------------
if (StrComp(conn.http.page,"/main"))
{
conn.state = Control.Main(&conn);
}
// ------------ PDA Page ----------------
if (StrComp(conn.http.page,"/pda"))
{
conn.state = Control.pda(&conn);
}
// ------------ Admin ------------------
if (StrComp(conn.http.page,"/admin"))
{
if (!(conn.http.auth & AUTH_SERVER))
conn.state = SendBasic401(&conn,realm_server);
else
conn.state = Control.WebAdmin(&conn);
}
if (StrComp(conn.http.page,"/apply"))
{
if (!(conn.http.auth & AUTH_SERVER))
conn.state = SendBasic401(&conn,realm_server);
else
conn.state = Control.ApplyAdmin(&conn);
}
// -------------- Users -----------------
if (StrComp(conn.http.page,"/user"))
{
if (!(conn.http.auth & AUTH_SERVER))
conn.state = SendBasic401(&conn,realm_server);
else
conn.state = Control.User(&conn);
}
// ------ Set user permissions ------------
if (StrComp(conn.http.page,"/setuser"))
{
if (!(conn.http.auth & AUTH_SERVER))
conn.state = SendBasic401(&conn,realm_server);
else
conn.state = Control.SetUser(&conn);
}
// ------ Save playlist ------------
if (StrComp(conn.http.page,"/save"))
{
if (!(conn.http.auth & AUTH_PLAYLIST))
conn.state = SendBasic401(&conn,realm_playlist);
else
conn.state = Control.SavePlaylist(&conn);
}
// ------ Page redirect - page?page=(main|list|browse)
if (StrComp(conn.http.page,"/page"))
{
char page[10];
GetArgValue(&conn,"page",page,10);
if (!(StrComp(page,"main") || StrComp(page,"list") || StrComp(page,"browse")))
wsprintf(page,"main");
prints(&conn,"HTTP/1.0 302 Temporarily Moved\nLocation: /");
prints(&conn,page);
prints(&conn,"\nConnection: close\nContent-type: text/html\n\n");
prints(&conn,"<html>\n<head>\n<title>Winamp Web Interface</title>\n</head>\n");
prints(&conn,"<body>\n<p><a href=\"/");
prints(&conn,page);
prints(&conn,"\">Winamp Web Interface</a></p>\n</body>\n</html>\n\n");
conn.state = ST_CLOSE;
}
if (StrComp(conn.http.page,"/winamp"))
{
OpenHTTPHeader(&conn,"text/html",0,NULL);
if (conn.http.reqID == RID_HEAD)
conn.state = ST_CLOSE;
else
{
char reqpage[10];
GetArgValue(&conn,"page",reqpage,10);
if (!(StrComp(reqpage,"main") || StrComp(reqpage,"list") || StrComp(reqpage,"browse")))
wsprintf(reqpage,"main");
OpenHtmlHeader(&conn);
Style(&conn);
CloseHeader(&conn);
if (frames == 3)
{
prints(&conn,"<frameset border=\"0\" frameborder=\"0\" rows=\"35,1*,27\">\n<frame name=\"top\" src=\"/top\" noresize marginheight=\"0\" marginwidth=\"0\">\n<frame name=\"main\" src=\"/page?page=");
prints(&conn,reqpage);
prints(&conn,"\" noresize>\n<frame name=\"bottom\" src=\"title\" noresize marginheight=\"1\" marginwidth=\"5\">\n");
prints(&conn,"<noframes><p><b>Frames are required for this site!<b></p><p>If no-frames operation is required, check the <b>No Frames Mode</b> box in the Options screen.</p>\n");
prints(&conn,"</frameset>\n");
}
else
{
prints(&conn,"<frameset border=\"0\" frameborder=\"0\" rows=\"35,1*\">\n<frame name=\"top\" src=\"/top\" noresize marginheight=\"0\" marginwidth=\"0\">\n<frame name=\"main\" src=\"/page?page=");
prints(&conn,reqpage);
prints(&conn,"\" noresize>\n");
prints(&conn,"<noframes><p><b>Frames are required for this site!<b></p><p>If no-frames operation is required, check the <b>No Frames Mode</b> box in the Options screen.</p>\n");
prints(&conn,"</frameset>\n");
}
conn.state = ST_CLOSEBODY;
}
}
if (conn.state == ST_NONE) // something else, including '/'
{ // 302 to /winamp?page=frames
if (frames == 1)
{
prints(&conn,"HTTP/1.0 302 Temporarily Moved\nLocation: /page?page=main\nConnection: close\nContent-type: text/html\n\n");
prints(&conn,"<html>\n<head>\n<title>Winamp Web Interface</title>\n</head>\n");
prints(&conn,"<body>\n<p><a href=\"/page?page=main\">Winamp Web Interface</a></p>\n</body>\n</html>\n\n");
}
else
{
prints(&conn,"HTTP/1.0 302 Temporarily Moved\nLocation: /winamp?page=main\nConnection: close\nContent-type: text/html\n\n");
prints(&conn,"<html>\n<head>\n<title>Winamp Web Interface</title>\n</head>\n");
prints(&conn,"<body>\n<p><a href=\"/winamp?page=main\">Winamp Web Interface</a></p>\n</body>\n</html>\n\n");
}
//conn.log = false;
conn.state = ST_CLOSE;
}
if (conn.state == ST_CLOSEBODY)
CloseBody(&conn); // end html
flush(&conn);
closesocket(conn.socket); // close connection
if (conn.log)
MakeLogEntry(&conn);
return true;
};
/*
struct HOSTENT FAR * gethostbyaddr (
const char FAR * addr,
int len,
int type
);
*/
// --------------------------------------------------------------------------------
// Adds entry in log
void MakeLogEntry(connection * conn)
{
int logbuffer_len;
SYSTEMTIME time;
GetSystemTime(&time);
char timestr[100]; // "[DD/MM/YYYY HH:MM:SS]"
wsprintf(timestr,"[%02d.%02d.%04d %02d:%02d:%02d]",time.wDay, time.wMonth, time.wYear, time.wHour, time.wMinute, time.wSecond);
char logbuffer[2048];
ZeroMemory(&logbuffer,sizeof(logbuffer));
logbuffer_len = wsprintf(logbuffer,"%s %s %s %d %s %s\r\n",timestr, (char*)inet_ntoa(conn->remote_host.sin_addr), conn->http.user, conn->http.responsecode, conn->http.request, conn->http.file);
// Find log file, in winamp plugin directory (same dir as gen_httpsrv.dll)
char logfilepath[MAX_PATH], *p;
char logfile[MAX_PATH];
if (lstrlen(logfiledir) == 0)
{
GetModuleFileName(plugin.hDllInstance,logfilepath,sizeof(logfilepath));
p=logfilepath+lstrlen(logfilepath);
while (p >= logfilepath && *p != '\\') p--;
if (++p >= logfilepath) *p = 0;
wsprintf(logfile,"%shttpsrv.log",logfilepath);
}
else
{
lstrcpy(logfilepath,logfiledir);
wsprintf(logfile,"%s\\httpsrv.log",logfilepath);
}
//lstrcat(logfile,"gen_httpsrv_log.log);
//MessageBox(NULL,logfile,"Logfile",MB_OK| MB_TOPMOST);
while(loglocked == true) // wait for log file to be free
Sleep(50);
loglocked = true; // lock it
HANDLE hLog = CreateFile( logfile,
GENERIC_WRITE,
0,
0,
OPEN_ALWAYS,
0,
0);
if (hLog == NULL)
{
//MessageBox(NULL,"Couldn't open log file","gen_httpSrv debug", MB_OK);
return;
}
DWORD dwSize = GetFileSize(hLog, NULL);
//MessageBox(NULL,logfilename,"logfile size",MB_OK);
SetFilePointer(hLog,(LONG)dwSize,NULL,FILE_BEGIN);
unsigned long written;
WriteFile(hLog,&logbuffer,logbuffer_len,&written,NULL);
CloseHandle(hLog);
if (dwSize >= 50000) // rename log file to something else to start a new one
{
char logfilename[MAX_PATH];
bool name_used = true;
int letter = 1;
while(name_used)
{ // loop through acceptable names, find first unused one of form httpsrv_dd-dd-yyyy_n.log
wsprintf(logfilename,"%shttpsrv_%d-%d-%d_%d.log",logfilepath,time.wDay,time.wMonth,time.wYear,letter);
//MessageBox(NULL,logfilename,"Logfilename",MB_OK | MB_TOPMOST);
if (GetFileAttributes(logfilename) == 0xFFFFFFFF)
{
name_used = false;
MoveFile(logfile,logfilename);
}
else
{
letter++;
}
}
}
loglocked = false; // release log file
}

535
Wawi Source/Config.cpp Normal file
View File

@@ -0,0 +1,535 @@
/* --- CONFIG.CPP ---
/
/ Written by Phil Himsworth, 2001-2002.
/
/*/
#include <windows.h>
#include <prsht.h>
#include "types.h"
#include "main.h"
#include "resource.h"
#include "plugin.h"
extern int con_port, hide_error, frames, securepassword, pass_debug;
extern int show_other_files, dl_wa_files, dl_other_files, title_refresh;
extern char mp3root[MAX_PATH], playlistdir[MAX_PATH], filetypes[255], pagetitle[255], logfiledir[MAX_PATH];
extern char szAppVer[], szAppName[];
extern winampGeneralPurposePlugin plugin;
HWND ConfigWnd = NULL; // To ensure only one config window appears at once
HWND UsersWnd = NULL;
// --------------------------------------------------------------------------------
// Server options window proc
BOOL CALLBACK ConfigServerWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char TempString[10];
int port_temp;
switch(uMsg)
{
case WM_INITDIALOG:
wsprintf(TempString,"%d",con_port);
SetDlgItemText(hwndDlg,IDC_PORT_EDIT,TempString);
CheckDlgButton(hwndDlg,IDC_SECUREPASSWORD,securepassword);
CheckDlgButton(hwndDlg,IDC_PASS_DEBUG,pass_debug);
CheckDlgButton(hwndDlg,IDC_HIDE_ERROR,hide_error);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_SECUREPASSWORDHELP:
MessageBox(hwndDlg,"Secure Passwords...\n\nWawi is able to encrypt passwords in the config file using the MD5 algorithm, or they can just be stored as jumbled but potentially retrievable strings using the Base64 algorithm.\n\nLeave this checked unless you have problems. Note that changing between secure and insecure passwords will require entering all passwords in again.\n\nThe \"debug\" option is in case of further trouble. This will make message boxes pop up telling you what it is doing when saving a password; if it doesn't work let me know what these say and I'll see what I can do. Ta...","Winamp Web Interface Help",MB_OK);
break;
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_APPLY: port_temp = GetDlgItemInt(hwndDlg,IDC_PORT_EDIT,NULL,false);
if (port_temp > 0 && port_temp < 65536)
{
con_port = port_temp;
hide_error = IsDlgButtonChecked(hwndDlg,IDC_HIDE_ERROR);
securepassword = IsDlgButtonChecked(hwndDlg,IDC_SECUREPASSWORD);
pass_debug = IsDlgButtonChecked(hwndDlg,IDC_PASS_DEBUG);
}
else
{
MessageBox(hwndDlg,"Port must be from 1 to 65535!","Winamp Web Interface",MB_OK);
SetDlgItemInt(hwndDlg,IDC_PORT_EDIT,con_port,false);
SetWindowLong(hwndDlg,DWL_MSGRESULT,true);
return true;
}
break;
}
break;
}
return false;
}
// --------------------------------------------------------------------------------
// Web page options window proc
BOOL CALLBACK ConfigWebPageWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char TempString[10];
HANDLE img;
switch(uMsg)
{
case WM_INITDIALOG:
wsprintf(TempString,"%d",title_refresh);
SetDlgItemText(hwndDlg,IDC_REFRESH,TempString);
SetDlgItemText(hwndDlg,IDC_PAGETITLE,pagetitle);
/*
LONG SendDlgItemMessage(
HWND hDlg, // handle of dialog box
int nIDDlgItem, // identifier of control
UINT Msg, // message to send
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
*/
switch(frames)
{
case 1: CheckDlgButton(hwndDlg,IDC_NOFRAMES,1);
img = LoadImage(plugin.hDllInstance,MAKEINTRESOURCE(IDB_FRAMES_ONE),IMAGE_BITMAP,0,0,0);
SendDlgItemMessage(hwndDlg,IDC_FRAMEIMG,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM)img);
CloseHandle(img);
break;
case 3: CheckDlgButton(hwndDlg,IDC_THREEFRAMES,1);
img = LoadImage(plugin.hDllInstance,MAKEINTRESOURCE(IDB_FRAMES_THREE),IMAGE_BITMAP,0,0,0);
SendDlgItemMessage(hwndDlg,IDC_FRAMEIMG,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM)img);
CloseHandle(img);
break;
default: CheckDlgButton(hwndDlg,IDC_TWOFRAMES,1);
img = LoadImage(plugin.hDllInstance,MAKEINTRESOURCE(IDB_FRAMES_TWO),IMAGE_BITMAP,0,0,0);
SendDlgItemMessage(hwndDlg,IDC_FRAMEIMG,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM)img);
CloseHandle(img);
break;
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_PAGETITLEHELP:
MessageBox(hwndDlg,"Page Title...\n\nThis text is what appears as the title on the main page on a user's browser. It can be up to 255 characters long, but should be made to fit into the width of a page in the browser.\n\nHTML tags can be included.","Winamp Web Interface Help",MB_OK);
break;
case IDC_NOFRAMES:
if (HIWORD(wParam) == BN_CLICKED)
{
//MessageBox(hwndDlg,"No frames","wawi",MB_OK| MB_TOPMOST);
img = LoadImage(plugin.hDllInstance,MAKEINTRESOURCE(IDB_FRAMES_ONE),IMAGE_BITMAP,0,0,0);
SendDlgItemMessage(hwndDlg,IDC_FRAMEIMG,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM)img);
CloseHandle(img);
}
break;
case IDC_TWOFRAMES:
if (HIWORD(wParam) == BN_CLICKED)
{
//MessageBox(hwndDlg,"Two frames","wawi",MB_OK| MB_TOPMOST);
img = LoadImage(plugin.hDllInstance,MAKEINTRESOURCE(IDB_FRAMES_TWO),IMAGE_BITMAP,0,0,0);
SendDlgItemMessage(hwndDlg,IDC_FRAMEIMG,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM)img);
CloseHandle(img);
}
break;
case IDC_THREEFRAMES:
if (HIWORD(wParam) == BN_CLICKED)
{
//MessageBox(hwndDlg,"Three frames","wawi",MB_OK| MB_TOPMOST);
img = LoadImage(plugin.hDllInstance,MAKEINTRESOURCE(IDB_FRAMES_THREE),IMAGE_BITMAP,0,0,0);
SendDlgItemMessage(hwndDlg,IDC_FRAMEIMG,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM)img);
CloseHandle(img);
}
break;
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_APPLY: GetDlgItemText(hwndDlg,IDC_PAGETITLE,(char*)pagetitle,255);
title_refresh = GetDlgItemInt(hwndDlg,IDC_REFRESH,NULL,false);
if (IsDlgButtonChecked(hwndDlg,IDC_NOFRAMES))
frames = 1;
else
if (IsDlgButtonChecked(hwndDlg,IDC_THREEFRAMES))
frames = 3;
else
frames = 2;
break;
}
break;
}
return false;
}
// --------------------------------------------------------------------------------
// Browse options window proc
BOOL CALLBACK ConfigBrowseWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int length;
switch(uMsg)
{
case WM_INITDIALOG:
CheckDlgButton(hwndDlg,IDC_WA_FILES_SHOW,1);
CheckDlgButton(hwndDlg,IDC_OTHER_FILES_SHOW,show_other_files);
CheckDlgButton(hwndDlg,IDC_WA_FILES_DL,dl_wa_files);
CheckDlgButton(hwndDlg,IDC_OTHER_FILES_DL,dl_other_files);
SetDlgItemText(hwndDlg,IDC_MP3_ROOT,mp3root);
SetDlgItemText(hwndDlg,IDC_FILETYPES,filetypes);
SetDlgItemText(hwndDlg,IDC_PLAYLISTDIR,playlistdir);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_ROOTDIRHELP:
MessageBox(hwndDlg,"Root Music Directory...\n\nEnter the path of the directory you want users to be able to browse. Any files and folders within this folder will appear in the Music Collection. Files and folders outside this folder will not be accessible.","Winamp Web Interface Help",MB_OK);
break;
case IDC_FILETYPEHELP:
MessageBox(hwndDlg,"Loadable Filetypes...\n\nEnter file extensions of files that winamp can play, separated by spaces. For example, entering \"mp3 wav mid\" will enable files with those extensions to be clicked on and played from the browser.\n\nIncluding 'url' will enable Wawi to follow internet shortcuts to load songs or streams rather than just treat them as non-winamp files.","Winamp Web Interface Help",MB_OK);
break;
case IDC_PLAYLISTDIRHELP:
MessageBox(hwndDlg,"Playlist Directory...\n\nWhen a playlist is saved from the web interface it is saved in this directory. The name given here is relative to the Root Music Directory; for example if the root directory is \"c:\\mp3\" and the playlist directory is \"playlists\", saved playlists will be stored in \"c:\\mp3\\playlists\\\".\n\nEnsure the directory exists before saving playlists into it!", "Winamp Web Interface Help", MB_OK);
break;
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_APPLY: show_other_files = IsDlgButtonChecked(hwndDlg,IDC_OTHER_FILES_SHOW);
dl_other_files = IsDlgButtonChecked(hwndDlg,IDC_OTHER_FILES_DL);
dl_wa_files = IsDlgButtonChecked(hwndDlg,IDC_WA_FILES_DL);
GetDlgItemText(hwndDlg,IDC_FILETYPES,(char*)filetypes,255);
length = GetDlgItemText(hwndDlg,IDC_MP3_ROOT,(char*)mp3root,MAX_PATH);
if (mp3root[length-1] == '\\')
mp3root[length-1] = 0; // chop off trailing '\'
else
mp3root[length] = 0; // make null terminated
length = GetDlgItemText(hwndDlg,IDC_PLAYLISTDIR,(char*)playlistdir,MAX_PATH);
if (playlistdir[length-1] == '\\')
playlistdir[length-1] = 0; // chop off trailing '\'
else
playlistdir[length] = 0; // make null terminated
break;
}
break;
}
return false;
}
// --------------------------------------------------------------------------------
// Log options window proc
BOOL CALLBACK ConfigLogWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int length;
switch(uMsg)
{
case WM_INITDIALOG:
SetDlgItemText(hwndDlg,IDC_LOGFILEPATH,logfiledir);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_VIEWLOG: ViewLog();
break;
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_APPLY: length = GetDlgItemText(hwndDlg,IDC_LOGFILEPATH,(char*)logfiledir,MAX_PATH);
if (logfiledir[length-1] == '\\')
logfiledir[length-1] = 0; // chop off trailing '\'
else
logfiledir[length] = 0; // make null terminated
break;
}
break;
}
return false;
}
// --------------------------------------------------------------------------------
// About options window proc
BOOL CALLBACK ConfigAboutWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HANDLE img;
char title[100];
switch(uMsg)
{
case WM_INITDIALOG:
ConfigWnd = (HWND) (((NMHDR FAR *) lParam)->hwndFrom);
img = LoadImage(plugin.hDllInstance,MAKEINTRESOURCE(IDB_TITLE),IMAGE_BITMAP,0,0,0);
SendDlgItemMessage(hwndDlg,IDC_MAINIMAGE,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM)img);
CloseHandle(img);
wsprintf(title,"Winamp Web Interface %s",szAppVer);
SetDlgItemText(hwndDlg,IDC_ABOUT_TITLE,title);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK: break;
default: break;
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_APPLY:
break;
}
break;
}
return false;
}
// --------------------------------------------------------------------------------
// Loading / Saving of config
void config_read()
{
char ini_file[MAX_PATH], *p;
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");
con_port = GetPrivateProfileInt(szAppName,"Port",80,ini_file);
hide_error = GetPrivateProfileInt(szAppName,"HideErrors",0,ini_file);
frames = GetPrivateProfileInt(szAppName,"Frames",2,ini_file);
securepassword = GetPrivateProfileInt(szAppName,"SecurePassword",1,ini_file);
pass_debug = GetPrivateProfileInt(szAppName,"PassDebug",0,ini_file);
show_other_files = GetPrivateProfileInt(szAppName,"ShowOtherFiles",0,ini_file);
dl_wa_files = GetPrivateProfileInt(szAppName,"DLWaFiles",0,ini_file);
dl_other_files = GetPrivateProfileInt(szAppName,"DLOtherFiles",0,ini_file);
title_refresh = GetPrivateProfileInt(szAppName,"TitleRefresh",60,ini_file);
GetPrivateProfileString(szAppName,"filetypes","mp3 wav m3u url",(char*)&filetypes,255,ini_file);
GetPrivateProfileString(szAppName,"pagetitle","... Winamp Web Interface ...",(char*)&pagetitle,255,ini_file);
GetPrivateProfileString(szAppName,"logfiledir","",(char*)&logfiledir,MAX_PATH,ini_file);
GetPrivateProfileString(szAppName,"playlistdir","",(char*)&playlistdir,MAX_PATH,ini_file);
int length = GetPrivateProfileString(szAppName,"mp3root","c:\\",(char*)&mp3root,MAX_PATH,ini_file);
if (mp3root[length-1] == '\\')
mp3root[length-1] = 0; // chop off trailing '\'
else
mp3root[length] = 0; // make null terminated
}
void config_write()
{
char ini_file[MAX_PATH], *p;
char string[32];
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");
wsprintf(string,"%d",con_port);
WritePrivateProfileString(szAppName,"Port",string,ini_file);
wsprintf(string,"%d",hide_error);
WritePrivateProfileString(szAppName,"HideErrors",string,ini_file);
wsprintf(string,"%d",frames);
WritePrivateProfileString(szAppName,"Frames",string,ini_file);
wsprintf(string,"%d",securepassword);
WritePrivateProfileString(szAppName,"Securepassword",string,ini_file);
wsprintf(string,"%d",pass_debug);
WritePrivateProfileString(szAppName,"PassDebug",string,ini_file);
wsprintf(string,"%d",title_refresh);
WritePrivateProfileString(szAppName,"TitleRefresh",string,ini_file);
wsprintf(string,"%d",show_other_files);
WritePrivateProfileString(szAppName,"ShowOtherFiles",string,ini_file);
wsprintf(string,"%d",dl_other_files);
WritePrivateProfileString(szAppName,"DLOtherFiles",string,ini_file);
wsprintf(string,"%d",dl_wa_files);
WritePrivateProfileString(szAppName,"DLWaFiles",string,ini_file);
WritePrivateProfileString(szAppName,"mp3root",mp3root,ini_file);
WritePrivateProfileString(szAppName,"pagetitle",pagetitle,ini_file);
WritePrivateProfileString(szAppName,"filetypes",filetypes,ini_file);
WritePrivateProfileString(szAppName,"logfiledir",logfiledir,ini_file);
WritePrivateProfileString(szAppName,"playlistdir",playlistdir,ini_file);
}
// --------------------------------------------------------------------------------
// Open log in user's favourite text editor - Registry! Aaargh!
void ViewLog()
{
/*
'log' files might not have an association, so open it with whatever
program opens text files.
- enumerate keys until '.log' is found
- if it's not, look for '.txt'
- find filetype (eg. txtfile)
- enumerate keys until 'filetype' is found
- read filetype\open\command
- if that goes arse over tit, just run 'notepad.exe <logfile>', but that's cheating.
*/
// Ah, sod it, let's just run notepad!
// Find log file, in winamp plugin directory (same dir as gen_httpsrv.dll)
char logfilepath[MAX_PATH], *p;
if (lstrlen(logfiledir) == 0)
{
GetModuleFileName(plugin.hDllInstance,logfilepath,sizeof(logfilepath));
p=logfilepath+lstrlen(logfilepath);
while (p >= logfilepath && *p != '\\') p--;
if (++p >= logfilepath) *p = 0;
}
else
{
lstrcpy(logfilepath,logfiledir);
lstrcat(logfilepath,"\\");
}
char logfilecmd[MAX_PATH];
//lstrcat(logfile,"gen_httpsrv_log.log);
wsprintf(logfilecmd,"notepad.exe %shttpsrv.log",logfilepath);
WinExec(logfilecmd,SW_SHOWDEFAULT);
}
BOOL CALLBACK NewConfigWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
return false;
}
// --------------------------------------------------------------------------------
// Entry point for new Config window, using Property Sheets instead of a single dialog.
void NewConfig()
{
PROPSHEETPAGE psp[6];
PROPSHEETHEADER psh;
psp[0].dwSize = sizeof(PROPSHEETPAGE);
psp[0].dwFlags = PSP_USEICONID | PSP_USETITLE;
psp[0].hInstance = plugin.hDllInstance;
psp[0].pszTemplate = MAKEINTRESOURCE(IDD_ABOUT);
psp[0].pszIcon = MAKEINTRESOURCE(IDI_WINAMP);
psp[0].pfnDlgProc = ConfigAboutWndProc;
psp[0].pszTitle = "About WAWI";
psp[0].lParam = 0;
psp[0].pfnCallback = NULL;
psp[1].dwSize = sizeof(PROPSHEETPAGE);
psp[1].dwFlags = PSP_USEICONID | PSP_USETITLE;
psp[1].hInstance = plugin.hDllInstance;
psp[1].pszTemplate = MAKEINTRESOURCE(IDD_SERVER);
psp[1].pszIcon = MAKEINTRESOURCE(IDI_SERVER);
psp[1].pfnDlgProc = ConfigServerWndProc;
psp[1].pszTitle = "Server";
psp[1].lParam = 0;
psp[1].pfnCallback = NULL;
psp[2].dwSize = sizeof(PROPSHEETPAGE);
psp[2].dwFlags = PSP_USEICONID | PSP_USETITLE;
psp[2].hInstance = plugin.hDllInstance;
psp[2].pszTemplate = MAKEINTRESOURCE(IDD_USERS);
psp[2].pszIcon = MAKEINTRESOURCE(IDI_USERS);
psp[2].pfnDlgProc = ConfigUsersWndProc;
psp[2].pszTitle = "Users";
psp[2].lParam = 0;
psp[2].pfnCallback = NULL;
psp[3].dwSize = sizeof(PROPSHEETPAGE);
psp[3].dwFlags = PSP_USEICONID | PSP_USETITLE;
psp[3].hInstance = plugin.hDllInstance;
psp[3].pszTemplate = MAKEINTRESOURCE(IDD_WEBPAGE);
psp[3].pszIcon = MAKEINTRESOURCE(IDI_WEBPAGE);
psp[3].pfnDlgProc = ConfigWebPageWndProc;
psp[3].pszTitle = "Web Page";
psp[3].lParam = 0;
psp[3].pfnCallback = NULL;
psp[4].dwSize = sizeof(PROPSHEETPAGE);
psp[4].dwFlags = PSP_USEICONID | PSP_USETITLE;
psp[4].hInstance = plugin.hDllInstance;
psp[4].pszTemplate = MAKEINTRESOURCE(IDD_BROWSE);
psp[4].pszIcon = MAKEINTRESOURCE(IDI_BROWSE);
psp[4].pfnDlgProc = ConfigBrowseWndProc;
psp[4].pszTitle = "Music Collection";
psp[4].lParam = 0;
psp[4].pfnCallback = NULL;
psp[5].dwSize = sizeof(PROPSHEETPAGE);
psp[5].dwFlags = PSP_USEICONID | PSP_USETITLE;
psp[5].hInstance = plugin.hDllInstance;
psp[5].pszTemplate = MAKEINTRESOURCE(IDD_LOG);
psp[5].pszIcon = MAKEINTRESOURCE(IDI_LOG);
psp[5].pfnDlgProc = ConfigLogWndProc;
psp[5].pszTitle = "Log";
psp[5].lParam = 0;
psp[5].pfnCallback = NULL;
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE;
psh.hwndParent = plugin.hwndParent;
psh.hInstance = plugin.hDllInstance;
psh.pszIcon = NULL;
psh.pszCaption = "Winamp Web Interface Config";
psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
psh.nStartPage = 0;
psh.ppsp = (LPCPROPSHEETPAGE) &psp;
psh.pfnCallback = NULL;
PropertySheet(&psh);
config_write();
ConfigWnd = NULL;
return;
}

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);
}

View File

@@ -0,0 +1,231 @@
/* --- DELETEPLAYLISTENTRY.CPP ---
/
/ Written by Phil Himsworth, 2001-2002.
/
/*/
#include <windows.h>
#include "types.h"
#include "main.h"
#include "html.h"
#include "plugin.h"
#include "wamessage.h"
// --------------------------------------------------------------------------------
// Delete a playlist entry by manipulating the playlist file.
// No longer used; replaced by DeletePlaylistEntry2 (below) which is much shorter and easier!
int DeletePlaylistEntry(int track)
{
// Get current position and save playlist to winamp.m3u
int plcount = SendMessage(WAwnd(),WM_USER,0,WAU_PLCOUNT);
int plpos = SendMessage(WAwnd(),WM_USER,0,WAU_PLSAVE);
// Find winamp.m3u; it's in the same dir as exe of current process.
DWORD wapid = GetWindowThreadProcessId(WAwnd(),NULL);
HMODULE hMod = (HMODULE)OpenProcess(PROCESS_ALL_ACCESS,false,wapid);
char playlistfile[MAX_PATH], *p;
GetModuleFileName(hMod,playlistfile,sizeof(playlistfile));
CloseHandle(hMod);
// Make \path\winamp.exe into \path\winamp.m3u
p=playlistfile+lstrlen(playlistfile);
while (p >= playlistfile && *p != '\\') p--;
if (++p >= playlistfile) *p = 0;
lstrcat(playlistfile,"winamp.m3u");
/* Right then, that's the playlist file extracted and found.
- read playlist into memory - linked list
- scan through list writing back to playlist file
- don't write back track to delete
- reload playlist. As easy as that...
*/
HANDLE hFile = CreateFile( playlistfile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
return DPE_NOREAD;
// Put entire file into a char array
DWORD dwSize = GetFileSize(hFile, NULL);
char * cplaylist = new char[dwSize];
DWORD read;
ReadFile(hFile,cplaylist,dwSize,&read,NULL);
CloseHandle(hFile);
// playlist file is now in cplaylist; scan through and put in a 'playlist' structure
char * chptr = cplaylist;
char temp[MAX_PATH];
playlistitem * startitem = NULL;
playlistitem * currentitem = startitem;
for (int i=1;i<=plcount;i++)
{
playlistitem * newitem = new playlistitem;
newitem->next = NULL;
newitem->number = i;
// skip '#EXTINF:'
chptr = GetDelimitedString(chptr,':',temp,MAX_PATH);
chptr++;
// get time
chptr = GetDelimitedString(chptr,',',newitem->time,10);
chptr++;
// get title
chptr = GetDelimitedString(chptr,'\r',newitem->name,MAX_PATH);
chptr++;
chptr++;
// get path
chptr = GetDelimitedString(chptr,'\r',newitem->path,MAX_PATH);
if (startitem == NULL)
{
startitem = newitem;
currentitem = newitem;
}
else
{
currentitem->next = newitem;
currentitem = newitem;
}
}
// hopefully the list is complete here.
// Open winamp.m3u for writing
hFile = CreateFile( playlistfile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
FreePlaylist(startitem);
return DPE_NOWRITE;
}
// Write it back into cplaylist. It'll be shorter, obviously, so it'll fit
wsprintf(cplaylist,"#EXTM3U\r\n");
currentitem = startitem;
while(currentitem != NULL)
{
if (currentitem->number != track)
{
wsprintf(temp,"#EXTINF:%s,%s\r\n%s\r\n",currentitem->time,currentitem->name,currentitem->path);
lstrcat(cplaylist,temp);
}
currentitem = currentitem->next;
}
// Write playlist to file
DWORD written;
WriteFile(hFile,cplaylist,lstrlen(cplaylist),&written,NULL);
CloseHandle(hFile);
delete cplaylist;
// free memory of linked list
FreePlaylist(startitem);
// clear current playlist and reload it
SendMessage(WAwnd(),WM_USER,0,WAU_CLEARPLIST);
int pathlen = lstrlen(playlistfile);
COPYDATASTRUCT cds;
cds.dwData = IPC_PLAYFILE;
cds.lpData = (void *)&playlistfile;
cds.cbData = pathlen+1;
SendMessage(WAwnd(),WM_COPYDATA,(WPARAM)NULL,(LPARAM)&cds);
// return to old position in list
if (plpos >= track)
plpos--;
SendMessage(WAwnd(),WM_USER,plpos,WAU_SETPLPOS);
return DPE_OK;
}
// --------------------------------------------------------------------------------
// Delete linked list after it's done with
void FreePlaylist(playlistitem * startitem)
{
playlistitem * current = startitem;
while(current != NULL)
{
startitem = current->next;
delete current;
current = startitem;
}
}
// --------------------------------------------------------------------------------
// Delete using Playlist window messages
int DeletePlaylistEntry2(connection * conn, int track)
{
HWND PLwnd = FindWindow("Winamp PE",NULL);
if (!PLwnd)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
// Free the buffer.
LocalFree( lpMsgBuf );
}
SendMessage(PLwnd,WM_USER,104,track);
OpenHTTPHeader(conn,"text/html",0,NULL);
if (conn->http.reqID == RID_HEAD)
return ST_CLOSE;
OpenHtmlHeader(conn);
char refreshto[MAX_PATH];
if (!GetArgValue(conn,"refresh",refreshto,10))
wsprintf(refreshto,"/list");
RefreshHeader(conn,refreshto);
Style(conn);
CloseHeader(conn);
OpenPageBody(conn);
prints(conn,"<p>Track");
printsi(conn,track);
prints(conn," deleted</p>");
return ST_CLOSEBODY;
}

BIN
Wawi Source/HTTPServer.exe Normal file

Binary file not shown.

BIN
Wawi Source/Images/OK.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

BIN
Wawi Source/Images/main.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 950 B

BIN
Wawi Source/Images/next.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 B

BIN
Wawi Source/Images/play.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

BIN
Wawi Source/Images/prev.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 963 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 963 B

BIN
Wawi Source/Images/stop.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 961 B

BIN
Wawi Source/Images/vol0.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 833 B

BIN
Wawi Source/Images/vol1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

BIN
Wawi Source/Images/vol2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

BIN
Wawi Source/Images/vol3.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 856 B

BIN
Wawi Source/Images/vol4.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

BIN
Wawi Source/Images/vol5.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

BIN
Wawi Source/Images/vol6.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 863 B

BIN
Wawi Source/Images/vol7.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

BIN
Wawi Source/Images/vol8.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

BIN
Wawi Source/Images/vol9.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
Wawi Source/Images/wa.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 B

BIN
Wawi Source/Log.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

View File

@@ -0,0 +1,51 @@
Winamp Control
/play[?nnn] Plays current track if no argument is given, or plays
the track at playlist position nnn. Also resumes playback
if Winamp is paused.
/prev Previous Track
/next Next Track
/pause Pause / Resume
/stop Stop
/stopslow Stops with fadeout
/vol?nn Sets the volume. <nn> is a number between 0 and 10 where
0 is mute and 10 is full volume.
Playlist control
/clear Clears playlist
/url?l&<url> Loads a HTTP location at <url> into the playlist
/url?p&<url> Loads a HTTP location at <url> into the playlist and plays it.
/sct?xxxxxxxxx.url Loads a URL shortcut file
Other pages
/list Returns current playlist
/img?nnn Image number nnn
/top Graphic link bar
/browse?\path\ Browse music collection at "%mp3_root_dir%\path\"
/about Returns a little 'about' page
/main Main page, with title and current track information
Unlinked
/smalltitle Returns the artist and title of the playing track. No HTML
formatting; just the HTTP header and a line of text.
/title Returns a HTML page of the track information - artist, title,
state of playback (playing, paused, stopped), track time.
Automatically refreshes.
/login Brings up a username & password box every time; can be used
to log out.
Still in development - they might work, they might not...
/shutdown Turns off the computer
/dl?\path\file Download a file at "%mp3_root_dir%\path\file"
Anything else returns the frameset to load the top link bar and the main page.

411
Wawi Source/Resource.rc Normal file
View File

@@ -0,0 +1,411 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// IMAGE
//
IDR_DIRECTORY IMAGE DISCARDABLE "dir.gif"
IDR_WAFILE IMAGE DISCARDABLE "wafile.gif"
IDR_PLAYLIST IMAGE DISCARDABLE "playlist.gif"
IDR_FILE IMAGE DISCARDABLE "file.gif"
IDR_IMG_ABOUT IMAGE DISCARDABLE "Images\\about.gif"
IDR_IMG_STOP IMAGE DISCARDABLE "Images\\stop.gif"
IDR_IMG_MAIN IMAGE DISCARDABLE "Images\\main.gif"
IDR_IMG_NEXT IMAGE DISCARDABLE "Images\\next.gif"
IDR_IMG_PAUSE IMAGE DISCARDABLE "Images\\pause.gif"
IDR_IMG_PLAY IMAGE DISCARDABLE "Images\\play.gif"
IDR_IMG_PLAYLIST IMAGE DISCARDABLE "Images\\playlist.gif"
IDR_IMG_PREV IMAGE DISCARDABLE "Images\\prev.gif"
IDR_IMG_BROWSE IMAGE DISCARDABLE "Images\\browse.gif"
IDR_IMG_BLACK IMAGE DISCARDABLE "Images\\black.gif"
IDR_VOL_09 IMAGE DISCARDABLE "Images\\vol9.gif"
IDR_VOL_10 IMAGE DISCARDABLE "Images\\vol10.gif"
IDR_VOL_02 IMAGE DISCARDABLE "Images\\vol2.gif"
IDR_VOL_03 IMAGE DISCARDABLE "Images\\vol3.gif"
IDR_VOL_04 IMAGE DISCARDABLE "Images\\vol4.gif"
IDR_VOL_05 IMAGE DISCARDABLE "Images\\vol5.gif"
IDR_VOL_06 IMAGE DISCARDABLE "Images\\vol6.gif"
IDR_VOL_07 IMAGE DISCARDABLE "Images\\vol7.gif"
IDR_VOL_08 IMAGE DISCARDABLE "Images\\vol8.gif"
IDR_VOL_01 IMAGE DISCARDABLE "Images\\vol1.gif"
IDR_VOL_00 IMAGE DISCARDABLE "Images\\vol0.gif"
IDR_IMG_STOPSLOW IMAGE DISCARDABLE "Images\\stopslow.gif"
IDR_ICO_WINAMP IMAGE DISCARDABLE "Images\\wa.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_USERS DIALOGEX 0, 0, 220, 201
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Manage Users"
FONT 8, "MS Sans Serif", 0, 0, 0x1
BEGIN
LISTBOX IDC_USERS,23,39,173,54,LBS_SORT | LBS_NOINTEGRALHEIGHT |
NOT WS_BORDER | WS_VSCROLL | WS_TABSTOP,WS_EX_STATICEDGE
EDITTEXT IDC_USERNAME,66,100,130,12,ES_AUTOHSCROLL | NOT
WS_BORDER,WS_EX_STATICEDGE
EDITTEXT IDC_PASSWORD,66,119,130,12,ES_PASSWORD | ES_AUTOHSCROLL |
NOT WS_BORDER,WS_EX_STATICEDGE
RTEXT "User",IDC_STATIC,27,102,31,10
RTEXT "Password",IDC_STATIC,26,121,32,10
PUSHBUTTON "Add/Update",IDC_UPDATE,150,146,46,15
CONTROL "Server",IDC_AUTH_SERVER,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,23,147,47,10
CONTROL "Play",IDC_AUTH_CONTROL,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,23,158,48,10
CONTROL "Add files",IDC_AUTH_PLAYLIST,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,88,147,50,10
CONTROL "Download",IDC_AUTH_DOWNLOAD,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,88,158,48,10
CONTROL "Browse",IDC_AUTH_BROWSE,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,88,169,50,10
PUSHBUTTON "Delete",IDC_DELETE,150,162,46,15
LTEXT "Select a user and update their permissions using the boxes below.",
IDC_STATIC,15,19,187,18
CONTROL "Remove Files",IDC_AUTH_CLEAR,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,23,169,59,10
GROUPBOX "User Management",IDC_STATIC,7,7,206,187
END
IDD_SERVER DIALOGEX 0, 0, 220, 201
STYLE WS_CHILD | WS_CAPTION | WS_SYSMENU
CAPTION "WAWI Config : Server Settings"
FONT 8, "MS Sans Serif", 0, 0, 0x1
BEGIN
GROUPBOX "Network Settings",IDC_STATIC,7,7,206,92
RTEXT "Port:",IDC_STATIC,61,66,16,8
EDITTEXT IDC_PORT_EDIT,83,65,30,12,ES_AUTOHSCROLL | ES_NUMBER |
NOT WS_BORDER,WS_EX_STATICEDGE
CONTROL "Hide error message if an error occurs",IDC_HIDE_ERROR,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,26,81,140,10
LTEXT "Change the port the server runs on. The default is 80; however if you run another web server you probably want to change it.",
IDC_STATIC,13,19,184,26
LTEXT "Winamp must be restarted before a change will take effect.",
IDC_STATIC,13,49,193,12
GROUPBOX "Password Storage",IDC_STATIC,7,105,206,75
CONTROL "Secure Passwords",IDC_SECUREPASSWORD,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,26,148,75,11
PUSHBUTTON "Err... what?",IDC_SECUREPASSWORDHELP,153,118,51,17
CONTROL "Debug Mode",IDC_PASS_DEBUG,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,141,148,58,11
LTEXT "Warning! Changing between Secure and Insecure passwords will require entering all passwords again.",
IDC_STATIC,13,118,131,26
LTEXT "Click 'Ok' before editing users if you change these.",
IDC_STATIC,13,164,194,10
END
IDD_WEBPAGE DIALOGEX 0, 0, 220, 201
STYLE WS_CHILD | WS_CAPTION | WS_SYSMENU
CAPTION "WAWI Config : Web Page Settings"
FONT 8, "MS Sans Serif", 0, 0, 0x1
BEGIN
GROUPBOX "Frames",IDC_STATIC,7,7,206,75
LTEXT "Change how many frames Wawi uses depending on your browser.",
IDC_STATIC,13,19,184,18
EDITTEXT IDC_PAGETITLE,20,112,150,12,ES_AUTOHSCROLL | NOT
WS_BORDER,WS_EX_STATICEDGE
PUSHBUTTON "?",IDC_PAGETITLEHELP,174,113,12,12
LTEXT "Web Page Title",IDC_STATIC,20,101,139,8
CONTROL "No Frames",IDC_NOFRAMES,"Button",BS_AUTORADIOBUTTON |
WS_GROUP,23,42,60,10
CONTROL "Two Frames",IDC_TWOFRAMES,"Button",BS_AUTORADIOBUTTON,
23,52,60,10
CONTROL "Three Frames",IDC_THREEFRAMES,"Button",
BS_AUTORADIOBUTTON,23,62,60,10
GROUPBOX "Page Details",IDC_STATIC,7,87,206,65
CONTROL "",IDC_FRAMEIMG,"Static",SS_BITMAP | SS_REALSIZEIMAGE,
128,40,16,14
EDITTEXT IDC_REFRESH,96,131,30,12,ES_AUTOHSCROLL | ES_NUMBER |
NOT WS_BORDER,WS_EX_STATICEDGE
LTEXT "Title Page Refresh (s)",IDC_STATIC,20,133,69,8
END
IDD_BROWSE DIALOGEX 0, 0, 220, 201
STYLE DS_MODALFRAME | WS_CHILD | WS_CAPTION | WS_SYSMENU
CAPTION "Browse Options"
FONT 8, "MS Sans Serif", 0, 0, 0x1
BEGIN
EDITTEXT IDC_MP3_ROOT,23,35,150,12,ES_AUTOHSCROLL | NOT WS_BORDER,
WS_EX_STATICEDGE
GROUPBOX "Browsing Options",IDC_STATIC,7,7,206,187
LTEXT "Root Directory",IDC_STATIC,23,24,114,8
EDITTEXT IDC_FILETYPES,23,98,150,12,ES_AUTOHSCROLL | NOT
WS_BORDER,WS_EX_STATICEDGE
LTEXT "Loadable Filetypes",IDC_STATIC,23,87,153,8
PUSHBUTTON "?",IDC_FILETYPEHELP,177,98,12,12
PUSHBUTTON "?",IDC_ROOTDIRHELP,177,35,12,12
CONTROL "Show",IDC_OTHER_FILES_SHOW,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,79,129,38,9
CONTROL "Download",IDC_OTHER_FILES_DL,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,126,129,48,9
CONTROL "Download",IDC_WA_FILES_DL,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,126,116,51,10
LTEXT "Other files:",IDC_STATIC,23,129,40,9
LTEXT "Winamp Files:",IDC_STATIC,23,116,55,10
CONTROL "Show",IDC_WA_FILES_SHOW,"Button",BS_AUTOCHECKBOX |
WS_DISABLED | WS_TABSTOP,79,116,38,10
EDITTEXT IDC_PLAYLISTDIR,23,67,150,12,ES_AUTOHSCROLL | NOT
WS_BORDER,WS_EX_STATICEDGE
LTEXT "Playlist Directory (Leave empty for Root Dir)",
IDC_STATIC,23,56,147,8
PUSHBUTTON "?",IDC_PLAYLISTDIRHELP,177,67,12,12
END
IDD_ABOUT DIALOG DISCARDABLE 0, 0, 220, 201
STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About"
FONT 8, "MS Sans Serif"
BEGIN
CONTROL "",IDC_MAINIMAGE,"Static",SS_BITMAP,6,13,206,68
CTEXT "Title goes here",IDC_ABOUT_TITLE,5,88,207,14
CTEXT "© Phil Himsworth 2002\r\n\r\ncontact@flippet.net - http://www.flippet.org",
IDC_STATIC,9,160,201,28
CTEXT "Remote control winamp from your web browser. First released waaaay back in August 2001; now much improved and shinier than ever!\r\n\r\nIf you see anything broken, or have an idea, get in touch and I'll have a look...",
IDC_STATIC,9,101,202,48
END
IDD_LOG DIALOGEX 0, 0, 220, 201
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Log File"
FONT 8, "MS Sans Serif", 0, 0, 0x1
BEGIN
GROUPBOX "Server Access Log",IDC_STATIC,7,7,206,108
LTEXT "WAWI keeps a log of who has accessed the server for diagnostic or statistical purposes.",
IDC_STATIC,18,26,125,25
EDITTEXT IDC_LOGFILEPATH,17,84,179,12,ES_AUTOHSCROLL | NOT
WS_BORDER,WS_EX_STATICEDGE
LTEXT "Logfile Directory (leave empty for Plugins Dir)",
IDC_STATIC,17,71,146,8
PUSHBUTTON "View Log...",IDC_VIEWLOG,149,26,50,14
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_USERS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 213
TOPMARGIN, 7
BOTTOMMARGIN, 194
END
IDD_SERVER, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 213
TOPMARGIN, 7
BOTTOMMARGIN, 194
END
IDD_WEBPAGE, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 213
TOPMARGIN, 7
BOTTOMMARGIN, 194
END
IDD_BROWSE, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 213
TOPMARGIN, 7
BOTTOMMARGIN, 194
END
IDD_LOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 213
TOPMARGIN, 7
BOTTOMMARGIN, 194
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_USERS ICON DISCARDABLE "users.ico"
IDI_SERVER ICON DISCARDABLE "server.ico"
IDI_WEBPAGE ICON DISCARDABLE "webpage.ico"
IDI_BROWSE ICON DISCARDABLE "browse.ico"
IDI_LOG ICON DISCARDABLE "Log.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDB_FRAMES_TWO BITMAP DISCARDABLE "Images\\frames_two_lg.bmp"
IDB_FRAMES_THREE BITMAP DISCARDABLE "Images\\frames_three_lg.bmp"
IDB_FRAMES_ONE BITMAP DISCARDABLE "Images\\frames_one_lg.bmp"
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (U.K.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// IMAGE
//
IDR_DOWNLOAD IMAGE DISCARDABLE "download.gif"
IDR_IMG_POPUP IMAGE DISCARDABLE "Images\\popup.gif"
IDR_PLAYDIR IMAGE DISCARDABLE "playdir.gif"
IDR_URLSCT IMAGE DISCARDABLE "Images\\world.gif"
IDR_IMG_ADMIN IMAGE DISCARDABLE "Images\\admin.gif"
IDR_IMG_OK IMAGE DISCARDABLE "Images\\OK.gif"
IDR_IMG_RPT_ON IMAGE DISCARDABLE "Images\\repeaton.gif"
IDR_IMG_RND_ON IMAGE DISCARDABLE "Images\\randomon.gif"
IDR_IMG_RPT_OFF IMAGE DISCARDABLE "Images\\repeatoff.gif"
IDR_IMG_RND_OFF IMAGE DISCARDABLE "Images\\randomoff.gif"
IDR_IMG_LIST_DEL IMAGE DISCARDABLE "Images\\list_delete.gif"
IDR_IMG_LIST_PLAY IMAGE DISCARDABLE "Images\\list_play.gif"
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_WINAMP ICON DISCARDABLE "images\\winamp.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDB_TITLE BITMAP DISCARDABLE "Images\\Title Graphic\\No Background.bmp"
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 7,5,10,0
PRODUCTVERSION 7,5,10,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080904b0"
BEGIN
VALUE "Comments", "Winamp Web Interface Plugin\0"
VALUE "CompanyName", " \0"
VALUE "FileDescription", "Winamp Web Interface Plugin\0"
VALUE "FileVersion", "7, 5, 10, 0\0"
VALUE "InternalName", "gen_httpSrv\0"
VALUE "LegalCopyright", "Copyright © 2002 Phil Himsworth\0"
VALUE "LegalTrademarks", "It's mine, dammit, MINE!\0"
VALUE "OriginalFilename", "gen_httpSrv.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", " gen_httpSrv\0"
VALUE "ProductVersion", "7, 5, 10, 0\0"
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x809, 1200
END
END
#endif // !_MAC
#endif // English (U.K.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

231
Wawi Source/Wawi_Readme.txt Normal file
View File

@@ -0,0 +1,231 @@
----------------------
Winamp Web Interface
----------------------
WAWI is a plugin which gives you remote control of Winamp from any computer which can access it over a network with any common-or-garden web browser. It lets you have full control over immediate playback, lets you edit the playlist and add songs
from your music collection, all without touching the computer actually running winamp or installing anything on the client computer.
Using It
--------
Install the plugin and point your browser at your computer. By default it runs on the normal web server port 80, but that can be changed in the Options->Server window. For example, at your own computer http://localhost/ should bring it up. If you change the port you can use http://localhost:xxxx instead, where xxxx is the port number. The main screen should appear; from there everything is linked so you can control winamp, access the playlist etc.
To start with you can't actually do much; you need to set up some permissions first. Do this in the Options -> Users window.
Adding Users
------------
Initially there is just one user listed, 'anon'... this is anyone who hasn't logged in using a different name. It does not have a password, and to start with has no permissions; change permissions by clicking on the boxes for what you want anyone to be able to do, and click 'Add/Update'.
To add a new user, maybe to let you control winamp but only let others look but not touch, type in a username in the 'user' box and a password in the 'password' box, check the desired access permissions, and click 'Add/Update'. Bingo, a new user.
Delete a user by clicking on the name in the list or typing the name straight into the 'user' box and click 'Delete'. Gone...
Different Modes for Different Browsers
--------------------------------------
The default mode is using two frames, one for the black bar along the top with the blue buttons and the main frame which displays the pages.
If you're using a no-frames browser select 'One Frame' in the Options->Web Page window. This will disable the top frame, and instead have a set of text links on each page to navigate around pages.
If you are using the interface from a PDA or something with a similarly small screen, there is a special small page with the basic controls on it, which lets you change the state of Random and Repeat and control playback. Point your browser at '/pda' to access this page.
The three frames mode is currently experimental but I think it works properly. This is similar to the two frame mode but with another frame at the bottom which updates with the song title and allows the main page to stay where it is when loading files or playing songs in the playlist.
Keeping track of what goes on
-----------------------------
The plugin keeps a log of who's been accessing the interface. By default this is kept in a file in the winamp 'plugins' directory called 'httpsrv.log'. Once this log file reaches 50KB it is renamed to 'httpsrv_<date>_<number>.log', for example the second full log file generated on the 12th of April 2002 will be named 'httpsrv_12-4-2002_2.log'.
The log file stores the time of the connection, the IP address and username of the client, the page they requested and the HTTP return code, for example '200' is a successful operation and '401' is when access is not allowed to a page or function.
Your Music Collection
---------------------
The web interface can load files into winamp from a directory specified as your music collection. Enter the path of your music collection into the box in the options screen, make sure you have the right access permission, and go load songs.
The contents of each directory are listed in a fairly self explanatory manner. Clicking on the name of a file or the icon next to it will load a file into winamp. Clicking on the name of a directory or the icon of a folder will browse that directory. Clicking on the icon of a folder with a red plus sign will add the entire contents of the folder to the playlist.
If downloading files is enabled, clicking on the icon of a disk will download a file onto the user's computer. Change this setting from the Options window.
Files that the interface should be able to load can be specified in the Options->Music Collection window; enter the extension of a file into the 'Filetypes' box to enable loading it from the interface. For example the default is 'wav mp3 m3u url', which allows MP3 files, Wave files, Winamp playlists and Internet Shortcuts to be loaded.
Internet Shortcut files appear with an icon of a world; loading these will load the target of the shortcut into the winamp playlist. This is useful if you make a shortcut to an internet radio station, for example.
Tinkering with how it looks
---------------------------
To alter the look of the page you can define your own Stylesheet to be sent along with the pages, if for example you are integrating it into another website or simply want to change how it looks. If there is a stylesheet in the winamp plugins directory called 'wawi.css' it will be used. If there isn't one there the default built-in stylesheet will be used instead.
Errors
------
If you've not told it to keep quiet it will pop up a message if it can't open the specified port. This is usually because there's another program using it - check you haven't got another web server running, as the default port for the plugin is the standard web port. If this is the case change it in the Config window for the plugin. If you tell it to not bother you if an error occurs it will sit quietly doing nothing.
Bugs
----
Hopefully the problem with MD5 passwords should be fixed now, after I finally got my hands on a computer that it wouldn't work on. However just in case it crops up again... sometimes it will not let you log in if passwords are being stored securely. If this seems to be the case tick the "debug" box and see what it says when adding a user or changing a password; if it says something like "encoded password" and a short string of gibberish (rather than a long string of alphanumerical gibberish) then please let me know about it! In the meantime, untick the secure mode; this should work. The difference is how the password is stored on your computer, not how it is sent over the network.
It was designed mainly using IE6 as a client... while Netscape and Lynx like it, Opera 6 seems to have a few problems; the currently playing track is not highlighted in the playlist; the main page doesn't update properly when selecting a track from the playlist to play. I shall look into it.
The 'download' function didn't work for me on Windows 9x; it has been fiddled with extensively but given that I now run Windows 2000 I have no way of testing it any more. It works on 2000. The interface uses the same method to send a StyleSheet for the web pages; while downloading files is not essential this probably is; let me know if it goes wrong and I'll try to fix it.
There're bound to be more... let me know if you find any.
Possibly More Recent Versions
-----------------------------
At the moment (April 2002) I am working on this regularly, so a new version is uploaded to the WAWI web site frequently. Check there for recent versions including bug fixes and new features. Wander over to www.flippet.net...
Test Platforms so far
---------------------
Development started on a Windows Me system, but now is done entirely on Windows 2000. Platforms I know it has been used on are now too numerous to name individually, but range from various versions of windows to PDAs. I feel quite boring using it from my laptop...
Change Log
----------
7.5.10
* Fixed the silly thing with the "browse" pages if you didn't give it a path to start with - it would show the root directory but none of the links would work.
7.5.9
* Secure passwords should now work ALL the time!!! Woohoo!!! (Hopefully...)
7.5.8
* Fixed the Base64 password system AGAIN, hopefully for the last time!
7.5.7
* Fixed which frame the new Delete went to (now stays in one frame; bit daft deleting something but not updating the playlist...
* Added a line in the HTTP header of HTML pages to stop the page being cached (hopefully)
* Made the 'random' and 'repeat' stay on the main page (again, a bit daft turning random off if the main page says it's still on and the like)
7.5.6
* Fixed the Base64 encoding/decoding, which hopefully should solve some password problems.
* Changed how delete playlist entry works - should be faster now, hopefully.
7.5.5
* Added a Save Playlist option
* Fixed a little bug if you tried to use a password of 'password' (muppet... ;¬P )
7.5
* Shiny new Options window; pretty pictures and pages, rather than having all options crammed onto one page
7.1
* First half-decent three frames mode!
* Ability to sort the playlist by title from the playlist page
7.0.1
* Fixed bug where there were no users in the list when first installing it
* Cleaned up the delete playlist entries function a bit
7.0
* Define your own stylesheet... if there's a file called 'wawi.css' in the plugins directory it will be used as a stylesheet.
* Ability to remove tracks from the playlist
* First introduction of web-based user management page, accessible from the 'admin' page. I think it looks funny on Opera though... I'll fix it shortly...
* Fixed bug where it would not save changes from the web admin page
* Slight under-the-hood change of page refreshing on adding files from the Browse pages
* Addded a 'PDA' mode for simple controls on small browsers - just point at '/pda'
* Added a password debug mode; if you have problems let me know what it says.
* Made it work again on w9x (sorry...)
* Certain options can be changed from the web interface with a new Admin page.
* When loading a file from the Browse page it will now return to the page where you clicked, instead of having to navigate back to it again.
* Option of using secure or non-secure passwords if you encounter problems.
6.0
* Added a 'restrict search' option; narrow your search of the playlist. I find it very handy.
* It now uses escape characters properly, so it should work on more browsers (the file browsing didn't work on Lynx before).
* 'View Log' button works wherever the log file directory is set to
* Massive, but under the hood, changes; any variables passed to the server are in the proper 'name=value' format, so they can be used from forms.
* Icons in the Browse section don't have silly backgrounds. At last!
5
* Added a completely new authentication system. You can set up users with different permissions - browse files, download files, add files to the playlist, clear the playlist and actually control playback.
* Added a favicon.ico so if you make it a Favourite you'll get a nice pwetty picture. Wow...
4
* Added a 'play URL immediately' option. Load a normal URL using /url?l&http://whatever, and play one immediately by /url?p&http://whatever.
* Requesting '/title' from the server returns a very simple page with just the currently playing song title, and which refreshes every minute.
* Requesting 'smalltitle' returns something similar, but it's just dead simple plain text version of the song info, so it can be included in another page or something along those lines.
* Directories have a 'play' button so you can load songs a directory at a time rather than a file at a time (which took ages!)
* Made links work properly in browsers that didn't convert spaces to %20s (eg. Lynx). There are probably other characters in names that don't work... if you find any, let me know.
* Added an (unlinked) url? command, which can play any filepath, UNC path, HTTP file, you name it. Just type it in... "/url?http://computer/path/to/song.mp3" and (hopefully) it'll work.
* Improved log handling - logs are rotated if they get big
* The popup window link works properly now and can be added to your Favourites or Bookmarks or whatever.
* Added an option to turn off the password protection if it annoys you and you've no need for it.
* Added a 'Stop with fadeout' button to the graphic link bar. It's not on the text link bar, but you can still use it if you must by typing in "/stopslow" in the Address bar of your browser.
* Passwords! Stop peeps messing... properly.
* A button to load the interface in a smaller popup window without the normal browser baggage like buttons and stuff. Still experimental, but it's there.
* The bar at the top is now a seperate frame to avoid having it reload the images every time.
* It also has a text only (well, mostly) mode if you don't like the top links at all; this makes it look like it did before version 3.0.
3
* A nice shiny bar at the top instead of the old text links bar. Popup about window; customisable title; and slightly better html.
* Under-the-hood changes; includes better http parsing, and should be faster too. Doesn't crash my network card any more! Also includes a small 'about' window from the browser, and lets you put your own title in for the main page.
* Wooo, shiny... now includes graphics in the Music Collection pages. Playlists (.m3u files) are handled better too.
* First submitted to winamp.com!
* The file types that can be loaded into winamp from the Browse section can now be chosen in the Options window. By default .wav and .mp3 files are loadable. Other filetypes can be displayed or hidden as desired. The access log file can also be viewed from within Winamp by clicking the View Log button in the options window.
* Now creates a log file with every connection, showing time, client and requested URL. Stored in a file in the plugins directory; I know several plugins where the log file ends up all over the place...
* Mainly under-the-hood changes; should be safer with multiple connections. More obvious directories in Browse pages. Got rid of server bluescreening problem!
* Added 'Read Only' option to stop people fiddling if you don't want them to.
2
* Added file browsing and adding.
* Added html stylesheets, proper html and random things to make it look nice
1
* Initial release
Me
--
Phil Himsworth, UK
web: http://www.flippet.org
email: contact@flippet.net
September, 2002
The Dull(er?) Bits
------------------
Disclaimer
----------
While I've gone to every effort to make sure this doesn't cause harmful effects - I don't want to fry my own computer! - I cannot say for sure that it will not fry yours. I will not be responsible for any damage or loss of anything even slightly relating to this program. You use it ENTIRELY AT YOUR OWN RISK. Don't run to me if things break. I'll fix bits of the program if you spot bugs if I want to, but I'm under no obligation to do so at all. And don't you forget it.
Besides that, I hope it's useful. Have fun!

530
Wawi Source/WebAdmin.cpp Normal file
View File

@@ -0,0 +1,530 @@
/* --- WEBADMIN.CPP ---
/
/ Written by Phil Himsworth, 2001-2002.
/
/*/
#include <windows.h>
#include "types.h"
#include "main.h"
#include "html.h"
#include "plugin.h"
#include "resource.h"
#include "op_winamp.h"
extern char mp3root[MAX_PATH], playlistdir[MAX_PATH], logfiledir[MAX_PATH], filetypes[255];
extern int browse_enable, dl_wa_files, dl_other_files, show_other_files, frames, title_refresh, securepassword;
extern char szAppVer[];
extern char pagetitle[255];
extern winampGeneralPurposePlugin plugin;
// --------------------------------------------------------------------------------
// Returns Web Admin page
int CControl::WebAdmin(connection * conn)
{
OpenHTTPHeader(conn,"text/html",0,NULL);
if (conn->http.reqID == RID_HEAD)
return ST_CLOSE;
OpenHtmlHeader(conn);
Style(conn);
CloseHeader(conn);
OpenPageBody(conn);
prints(conn,"<h3>\n<i>\n... Wawi Remote Admin ...\n</i></h3>\n");
prints(conn,"<h4>");
Link(conn,"/user","<font color=red>[</font>User Management<font color=red>]</font>",T_MAIN);
prints(conn,"</h4>\n");
prints(conn,"<form action=\"/apply\" method=\"get\">\n");
prints(conn,"<table width=\"100%\" cellspacing=\"5\" cellpadding=\"0\" border=\"0\">\n<tr>\n");
prints(conn,"<td align=\"right\">Main Page Title</td>\n<td><input type=\"text\" name=\"title\" size=\"30\" value=\"");
prints(conn,pagetitle);
prints(conn,"\"></td>\n</tr>\n<tr>\n");
prints(conn,"<td align=\"right\">Loadable Filetypes</td>\n<td><input type=\"text\" name=\"filetypes\" size=\"30\" value=\"");
prints(conn,filetypes);
prints(conn,"\"></td>\n</tr>\n<tr>\n");
prints(conn,"<td align=\"right\">Music Root Directory</td>\n<td><input type=\"text\" name=\"root\" size=\"30\" value=\"");
prints(conn,mp3root);
prints(conn,"\"></td>\n</tr>\n<tr>\n");
prints(conn,"<td align=\"right\">Playlists Directory</td>\n<td><input type=\"text\" name=\"playlists\" size=\"30\" value=\"");
prints(conn,playlistdir);
prints(conn,"\"></td>\n</tr>\n<tr>\n<td>&nbsp;</td>\n</tr>\n<tr>\n");
// Frames mode radio buttons
prints(conn,"<td align=\"right\">Frames:</td>\n<td><input type=\"radio\" name=\"frames\" value=\"1\"");
if (frames == 1)
prints(conn," checked=\"on\"");
prints(conn,">No Frames</td>\n</tr>\n<tr>\n<td align=\"right\">&nbsp;</td>\n<td><input type=\"radio\" name=\"frames\" value=\"2\"");
if (frames == 2)
prints(conn," checked=\"on\"");
prints(conn,">2</td>\n</tr>\n<tr>\n<td align=\"right\">&nbsp;</td>\n<td><input type=\"radio\" name=\"frames\" value=\"3\"");
if (frames == 3)
prints(conn," checked=\"on\"");
prints(conn,">3</td>\n</tr>\n<tr>\n");
prints(conn,"<td align=\"right\">Secure Passwords</td>\n<td><input type=\"checkbox\" name=\"securepassword\"");
if (securepassword == 1)
prints(conn," checked=\"on\"");
prints(conn,"><b>Warning!</b> Changing this will invalidate all user passwords.</td>\n</tr>\n<tr>");
prints(conn,"<td>&nbsp;</td>\n</tr>\n<tr>\n");
prints(conn,"<td align=\"right\">Winamp Files</td>\n<td><input type=\"checkbox\" name=\"dl_wa_files\"");
if (dl_wa_files == 1)
prints(conn," checked=\"on\"");
prints(conn,">Download</td>\n</tr>\n<tr>\n");
prints(conn,"<td align=\"right\">Other Files</td>\n<td><input type=\"checkbox\" name=\"dl_other_files\"");
if (dl_other_files == 1)
prints(conn," checked=\"on\"");
prints(conn,">Download <input type=\"checkbox\" name=\"show_other_files\"");
if (show_other_files == 1)
prints(conn," checked=\"on\"");
prints(conn,">Show</td>\n</tr>\n");
prints(conn,"<td colspan=\"2\" align=\"center\"><input type=\"image\" alt=\"Apply Changes\" src=\"img?image=");
printsi(conn,IDR_IMG_OK);
prints(conn,"\"></td>\n</tr>\n</table>");
prints(conn,"</form>\n");
if (frames == 1)
LinkBar(conn);
prints(conn,"<p>&nbsp;</p>");
return ST_CLOSEBODY;
}
// Returns admin apply page and actually does the stuff
int CControl::ApplyAdmin(connection * conn)
{
bool changed = false;
OpenHTTPHeader(conn,"text/html",0,NULL);
if (conn->http.reqID == RID_HEAD)
return ST_CLOSE;
OpenHtmlHeader(conn);
Style(conn);
CloseHeader(conn);
OpenPageBody(conn);
prints(conn,"<h3>\n<i>\n... Wawi Remote Admin ...\n</i></h3>\n");
char instring[255]; // used for everything
if (GetArgValue(conn,"title",instring,255))
{
Unescape_url(instring);
if (!StrComp(pagetitle,instring))
{
lstrcpy(pagetitle,instring);
prints(conn,"<p>Page title changed to <b>");
prints(conn,pagetitle);
prints(conn,"</b></p>\n");
changed = true;
}
}
if (GetArgValue(conn,"filetypes",instring,255))
{
Unescape_url(instring);
if (!StrComp(filetypes,instring))
{
lstrcpy(filetypes,instring);
prints(conn,"<p>Filetypes changed to <b>");
prints(conn,filetypes);
prints(conn,"</b></p>\n");
changed = true;
}
}
if (GetArgValue(conn,"root",instring,255))
{
Unescape_url(instring);
if (!StrComp(mp3root,instring))
{
lstrcpy(mp3root,instring);
prints(conn,"<p>Root music directory changed to <b>");
prints(conn,mp3root);
prints(conn,"</b></p>\n");
changed = true;
}
}
if (GetArgValue(conn,"playlists",instring,255))
{
Unescape_url(instring);
if (!StrComp(playlistdir,instring))
{
lstrcpy(playlistdir,instring);
prints(conn,"<p>Playlist directory changed to <b>");
prints(conn,playlistdir);
prints(conn,"</b></p>\n");
changed = true;
}
}
wsprintf(instring,"2");
GetArgValue(conn,"frames",instring,255);
if (StrComp(instring,"1"))
{
if (frames != 1)
{
frames = 1;
prints(conn,"<p>No Frames mode turned <b>On</b></p>");
changed = true;
}
}
else
{
if (StrComp(instring,"3"))
{
if (frames != 3)
{
frames = 3;
prints(conn,"<p>Three Frames mode turned <b>On</b></p>");
changed = true;
}
}
else
{
if (frames != 2)
{
frames = 2;
prints(conn,"<p>Two Frames mode turned <b>On</b></p>");
changed = true;
}
}
}
wsprintf(instring,"off");
GetArgValue(conn,"securepassword",instring,255);
if (StrComp(instring,"on"))
{
if (securepassword == 0)
{
securepassword = 1;
prints(conn,"<p>Secure passwords turned <b>On</b></p>");
changed = true;
}
}
else
{
if (securepassword == 1)
{
securepassword = 0;
prints(conn,"<p>Secure passwords turned <b>Off</b></p>");
changed = true;
}
}
wsprintf(instring,"off");
GetArgValue(conn,"dl_wa_files",instring,255);
if (StrComp(instring,"on"))
{
if (dl_wa_files == 0)
{
dl_wa_files = 1;
prints(conn,"<p>Downloading of Winamp files is <b>Enabled</b></p>");
changed = true;
}
}
else
{
if (dl_wa_files == 1)
{
dl_wa_files = 0;
prints(conn,"<p>Downloading of Winamp files is <b>Disabled</b></p>");
changed = true;
}
}
wsprintf(instring,"off");
GetArgValue(conn,"dl_other_files",instring,255);
if (StrComp(instring,"on"))
{
if (dl_other_files == 0)
{
dl_other_files = 1;
prints(conn,"<p>Downloading other files is <b>Enabled</b></p>");
changed = true;
}
}
else
{
if (dl_other_files == 1)
{
dl_other_files = 0;
prints(conn,"<p>Downloading other files is <b>Disabled</b></p>");
changed = true;
}
}
wsprintf(instring,"off");
GetArgValue(conn,"show_other_files",instring,255);
if (StrComp(instring,"on"))
{
if (show_other_files == 0)
{
show_other_files = 1;
prints(conn,"<p>Listing other files is <b>Enabled</b></p>");
changed = true;
}
}
else
{
if (show_other_files == 1)
{
show_other_files = 0;
prints(conn,"<p>Listing other files is <b>Disabled</b></p>");
changed = true;
}
}
if (changed == false)
prints(conn,"<p>No changes made.</p>\n");
config_write();
prints(conn,"<p>");
ImgLink(conn,"/",IDR_IMG_OK,"Return to Main Page",0,0,T_TOP);
prints(conn,"</p>\n");
return ST_CLOSEBODY;
}
// --------------------------------------------------------------------------------
// User admin page
int CControl::User(connection * conn)
{
char username[20];
char password[40];
int access;
if (!GetArgValue(conn,"user",username,20))
wsprintf(username,"anon");
OpenHTTPHeader(conn,"text/html",0,NULL);
if (conn->http.reqID == RID_HEAD)
return ST_CLOSE;
OpenHtmlHeader(conn);
Style(conn);
CloseHeader(conn);
OpenPageBody(conn);
prints(conn,"<h3>\n<i>\n... Wawi User Admin ...\n</i></h3>\n");
prints(conn,"<form action=\"/user\" method=\"get\">\n<p>\n");
prints(conn,"<table border=\"0\" cellpadding=\"0\" cellspacing=\"5\">\n<tr>\n<td align=\"right\">");
prints(conn,"Show User:</td>\n<td colspan=\"2\"><select onchange=\"form.submit()\" size=\"1\" name=\"user\">\n");
user * users = NULL;
char ini_file[MAX_PATH], *p;
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");
users = RetrieveUsers(users, ini_file); // fill list 'users' with usernames
user * current = users; // pointer to start of list
bool goodname = false;
while(current != NULL)
{
prints(conn,"<option value=\"");
prints(conn,current->name);
if (StrComp(current->name,username))
{
prints(conn,"\" selected>");
goodname = true;
}
else
prints(conn,"\">");
prints(conn,current->name);
prints(conn,"</option>\n");
current = current->next;
delete users;
users = current;
}
prints(conn,"</select>\n");
prints(conn,"<input type=\"image\" alt=\"Show information\" src=\"img?image=");
printsi(conn,IDR_IMG_OK);
prints(conn,"\"></td>\n</tr>\n</table>\n</p>\n</form>\n");
if (!goodname)
{
prints(conn,"<p>User <b>");
prints(conn,username);
prints(conn,"</b> is not a user of this server.</p>");
return ST_CLOSEBODY;
}
else
{
char userkey[30];
wsprintf(userkey,"#%s_access",username);
access = GetPrivateProfileInt("Users",userkey,AUTH_ANON,ini_file);
GetPrivateProfileString("Users",username,"password",password,40,ini_file);
prints(conn,"<form action=\"/setuser\" method=\"get\">\n<p>\n");
prints(conn,"<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"5\">\n");
prints(conn,"<tr>\n<td align=\"right\">User</td>\n");
prints(conn,"<td colspan=\"2\"><input type=\"text\" name=\"user\" size=\"40\" value=\"");
prints(conn,username);
prints(conn,"\"></td>\n</tr>\n");
prints(conn,"<tr>\n<td align=\"right\">Password</td>\n");
prints(conn,"<td colspan=\"2\"><input type=\"password\" name=\"p\" size=\"40\" value=\"");
if (!StrComp(username,"anon"))
prints(conn,password);
prints(conn,"\"></td>\n</tr>\n");
prints(conn,"<tr>\n<td colspan=\"2\">&nbsp;</td>\n</tr>\n");
prints(conn,"<tr>\n<td align=\"right\">Server<input type=\"checkbox\" name=\"a_server\" ");
if (access & AUTH_SERVER)
prints(conn,"checked=\"on\"");
prints(conn,"></td>\n");
prints(conn,"<td align=\"left\"><input type=\"checkbox\" name=\"a_playlist\" ");
if (access & AUTH_PLAYLIST)
prints(conn,"checked=\"on\"");
prints(conn,">Add files</td>\n</tr>\n");
prints(conn,"<tr>\n<td align=\"right\">Play<input type=\"checkbox\" name=\"a_control\" ");
if (access & AUTH_CONTROL)
prints(conn,"checked=\"on\"");
prints(conn,"></td>\n");
prints(conn,"<td align=\"left\"><input type=\"checkbox\" name=\"a_download\" ");
if (access & AUTH_DOWNLOAD)
prints(conn,"checked=\"on\"");
prints(conn,">Download</td>\n</tr>\n");
prints(conn,"<tr>\n<td align=\"right\">Remove files<input type=\"checkbox\" name=\"a_clear\" ");
if (access & AUTH_CLEAR)
prints(conn,"checked=\"on\"");
prints(conn,"></td>\n");
prints(conn,"<td align=\"left\"><input type=\"checkbox\" name=\"a_browse\" ");
if (access & AUTH_BROWSE)
prints(conn,"checked=\"on\"");
prints(conn,">Browse</td>\n</tr>\n<tr>\n<td colspan=\"2\" align=\"center\">");
prints(conn,"<input type=\"submit\" name=\"addupd\" value=\"Add/Update\">");
prints(conn,"<input type=\"submit\" name=\"delete\" value=\"Delete\">\n</td>\n</tr>\n</table>\n</p>\n</form>\n");
}
if (frames == 1)
LinkBar(conn);
prints(conn,"<p>&nbsp;</p>\n");
return ST_CLOSEBODY;
}
// --------------------------------------------------------------------------------
// Sets stuff from the user admin page
int CControl::SetUser(connection * conn)
{
OpenHTTPHeader(conn,"text/html",0,NULL);
if (conn->http.reqID == RID_HEAD)
return ST_CLOSE;
OpenHtmlHeader(conn);
Style(conn);
prints(conn,"<h3>\n<i>\n... Wawi User Admin ...\n</i></h3>\n");
char username[20];
char password[40];
if (!GetArgValue(conn,"user",username,20) || StrComp(username,""))
{
CloseHeader(conn);
OpenPageBody(conn);
prints(conn,"<p>No user selected.</p>\n");
ImgLink(conn,"/main",IDR_IMG_OK,"Return to main page",0,0,T_MAIN);
return ST_CLOSEBODY;
}
char ini_file[MAX_PATH], *p;
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");
char whichbutton[20];
if (GetArgValue(conn,"delete",whichbutton,20))
{
DeleteUser(ini_file,username);
RefreshHeader(conn,"/user");
CloseHeader(conn);
OpenPageBody(conn);
prints(conn,"<p>Deleting user <b>");
prints(conn,username);
prints(conn,"</b></p>\n");
return ST_CLOSEBODY;
}
char refreshto[40];
wsprintf(refreshto,"/user?user=%s",username);
RefreshHeader(conn,refreshto);
CloseHeader(conn);
OpenPageBody(conn);
prints(conn,"<p>Updating user information for <b>");
prints(conn,username);
prints(conn,"</b></p>\n");
GetArgValue(conn,"p",password,40);
//MessageBox(NULL,password,"password",MB_OK | MB_TOPMOST);
int access = 0;
char authstring[10];
if (GetArgValue(conn,"a_server",authstring,10))
if (StrComp(authstring,"on"))
access += AUTH_SERVER;
if (GetArgValue(conn,"a_control",authstring,10))
if (StrComp(authstring,"on"))
access += AUTH_CONTROL;
if (GetArgValue(conn,"a_clear",authstring,10))
if (StrComp(authstring,"on"))
access += AUTH_CLEAR;
if (GetArgValue(conn,"a_playlist",authstring,10))
if (StrComp(authstring,"on"))
access += AUTH_PLAYLIST;
if (GetArgValue(conn,"a_download",authstring,10))
if (StrComp(authstring,"on"))
access += AUTH_DOWNLOAD;
if (GetArgValue(conn,"a_browse",authstring,10))
if (StrComp(authstring,"on"))
access += AUTH_BROWSE;
UpdateUser(ini_file,username,password,access);
return ST_CLOSEBODY;
}

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;
}

BIN
Wawi Source/browse.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
Wawi Source/dir.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 887 B

BIN
Wawi Source/download.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

BIN
Wawi Source/file.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

View File

@@ -0,0 +1,407 @@
# Microsoft Developer Studio Project File - Name="gen_httpServ" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=gen_httpServ - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "gen_httpServ.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "gen_httpServ.mak" CFG="gen_httpServ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "gen_httpServ - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "gen_httpServ - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "gen_httpServ - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GEN_HTTPSERV_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GEN_HTTPSERV_EXPORTS" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib mswsock.lib version.lib winmm.lib comctl32.lib /nologo /dll /machine:I386 /out:"Release/gen_httpSrv.dll"
# Begin Special Build Tool
SOURCE="$(InputPath)"
PostBuild_Cmds=copy Release\gen_httpsrv.dll "c:\program files\sound\winamp\plugins"
# End Special Build Tool
!ELSEIF "$(CFG)" == "gen_httpServ - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GEN_HTTPSERV_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GEN_HTTPSERV_EXPORTS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib mswsock.lib version.lib winmm.lib comctrl32.lib /nologo /dll /debug /machine:I386 /out:"Debug/gen_httpSrv.dll" /pdbtype:sept
# Begin Special Build Tool
SOURCE="$(InputPath)"
PostBuild_Cmds=copy Debug\gen_httpsrv.dll "c:\program files\sound\winamp\plugins"
# End Special Build Tool
!ENDIF
# Begin Target
# Name "gen_httpServ - Win32 Release"
# Name "gen_httpServ - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\browse.cpp
# End Source File
# Begin Source File
SOURCE=.\ClientConnection.cpp
# End Source File
# Begin Source File
SOURCE=.\Config.cpp
# End Source File
# Begin Source File
SOURCE=.\Config_users.cpp
# End Source File
# Begin Source File
SOURCE=.\DeletePlaylistEntry.cpp
# End Source File
# Begin Source File
SOURCE=.\html.cpp
# End Source File
# Begin Source File
SOURCE=.\main.cpp
# End Source File
# Begin Source File
SOURCE=.\net_http_html.cpp
# End Source File
# Begin Source File
SOURCE=.\op_winamp.cpp
# End Source File
# Begin Source File
SOURCE=.\Resource.rc
# End Source File
# Begin Source File
SOURCE=.\security.cpp
# End Source File
# Begin Source File
SOURCE=.\strings.cpp
# End Source File
# Begin Source File
SOURCE=.\WebAdmin.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\html.h
# End Source File
# Begin Source File
SOURCE=.\main.h
# End Source File
# Begin Source File
SOURCE=.\op_winamp.h
# End Source File
# Begin Source File
SOURCE=.\plugin.h
# End Source File
# Begin Source File
SOURCE=.\resource.h
# End Source File
# Begin Source File
SOURCE=.\types.h
# End Source File
# Begin Source File
SOURCE=.\wamessage.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# Begin Source File
SOURCE=.\Images\about.gif
# End Source File
# Begin Source File
SOURCE=.\Images\admin.gif
# End Source File
# Begin Source File
SOURCE=.\Images\black.gif
# End Source File
# Begin Source File
SOURCE=.\Images\browse.gif
# End Source File
# Begin Source File
SOURCE=.\browse.ico
# End Source File
# Begin Source File
SOURCE=.\dir.gif
# End Source File
# Begin Source File
SOURCE=.\download.gif
# End Source File
# Begin Source File
SOURCE=.\file.gif
# End Source File
# Begin Source File
SOURCE=.\Images\frames_one.bmp
# End Source File
# Begin Source File
SOURCE=.\Images\frames_one_lg.bmp
# End Source File
# Begin Source File
SOURCE=.\Images\frames_three.bmp
# End Source File
# Begin Source File
SOURCE=.\Images\frames_three_lg.bmp
# End Source File
# Begin Source File
SOURCE=.\Images\frames_two.bmp
# End Source File
# Begin Source File
SOURCE=.\Images\frames_two_lg.bmp
# End Source File
# Begin Source File
SOURCE=.\icon1.ico
# End Source File
# Begin Source File
SOURCE=.\Images\list_delete.gif
# End Source File
# Begin Source File
SOURCE=.\Images\list_play.gif
# End Source File
# Begin Source File
SOURCE=.\Log.ico
# End Source File
# Begin Source File
SOURCE=.\Images\main.gif
# End Source File
# Begin Source File
SOURCE=.\Images\next.gif
# End Source File
# Begin Source File
SOURCE=".\Images\Title Graphic\No Background.bmp"
# End Source File
# Begin Source File
SOURCE=.\Images\OK.gif
# End Source File
# Begin Source File
SOURCE=.\Images\pause.gif
# End Source File
# Begin Source File
SOURCE=.\Images\play.gif
# End Source File
# Begin Source File
SOURCE=.\playdir.gif
# End Source File
# Begin Source File
SOURCE=.\Images\playlist.gif
# End Source File
# Begin Source File
SOURCE=.\playlist.gif
# End Source File
# Begin Source File
SOURCE=.\Images\popup.gif
# End Source File
# Begin Source File
SOURCE=.\Images\prev.gif
# End Source File
# Begin Source File
SOURCE=.\Images\randomoff.gif
# End Source File
# Begin Source File
SOURCE=.\Images\randomon.gif
# End Source File
# Begin Source File
SOURCE=.\Images\repeatoff.gif
# End Source File
# Begin Source File
SOURCE=.\Images\repeaton.gif
# End Source File
# Begin Source File
SOURCE=.\server.ico
# End Source File
# Begin Source File
SOURCE=.\Images\stop.gif
# End Source File
# Begin Source File
SOURCE=.\Images\stopslow.gif
# End Source File
# Begin Source File
SOURCE=.\users.ico
# End Source File
# Begin Source File
SOURCE=.\Images\vol0.gif
# End Source File
# Begin Source File
SOURCE=.\Images\vol1.gif
# End Source File
# Begin Source File
SOURCE=.\Images\vol10.gif
# End Source File
# Begin Source File
SOURCE=.\Images\vol2.gif
# End Source File
# Begin Source File
SOURCE=.\Images\vol3.gif
# End Source File
# Begin Source File
SOURCE=.\Images\vol4.gif
# End Source File
# Begin Source File
SOURCE=.\Images\vol5.gif
# End Source File
# Begin Source File
SOURCE=.\Images\vol6.gif
# End Source File
# Begin Source File
SOURCE=.\Images\vol7.gif
# End Source File
# Begin Source File
SOURCE=.\Images\vol8.gif
# End Source File
# Begin Source File
SOURCE=.\Images\vol9.gif
# End Source File
# Begin Source File
SOURCE=.\Images\wa.ico
# End Source File
# Begin Source File
SOURCE=.\wa.ico
# End Source File
# Begin Source File
SOURCE=.\wafile.gif
# End Source File
# Begin Source File
SOURCE=.\webpage.ico
# End Source File
# Begin Source File
SOURCE=.\Images\winamp.ico
# End Source File
# Begin Source File
SOURCE=.\Images\world.gif
# End Source File
# End Group
# End Target
# End Project

View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "gen_httpServ"=".\gen_httpServ.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

400
Wawi Source/html.cpp Normal file
View File

@@ -0,0 +1,400 @@
/* --- HTML.CPP ---
/
/ Written by Phil Himsworth, 2001-2002.
/
/*/
#include <windows.h>
#include "types.h"
#include "main.h"
#include "resource.h"
#include "wamessage.h"
#include "html.h"
extern int frames;
// --------------------------------------------------------------------------------
// *** HTTP / HTML FUNCTIONS ***
// Sends HTTP header
void OpenHTTPHeader(connection * conn, char * type, int length, char * filename)
{
char openstring[200];
prints(conn,"HTTP/1.0 200 OK\nConnection: close\n");
if (StrComp(type,"text/html"))
prints(conn,"Expires: -1\n");
if (type != NULL)
{
wsprintf(openstring,"Content-type: %s\n",type);
prints(conn,openstring);
}
if (length != 0)
{
wsprintf(openstring,"Content-length: %d\n",length);
prints(conn,openstring);
}
if (filename != NULL)
{
wsprintf(openstring,"Content-Disposition: attachment; filename=\"%s\"\n",filename);
prints(conn,openstring);
}
prints(conn,"\n");
}
// Sends HTML header
void OpenHtmlHeader(connection * conn)
{
prints(conn,"<html>\n<head>\n<title>\nWinamp Web Interface\n</title>\n");
}
// Sends styles and ends header
void Style(connection * conn)
{
prints(conn,"<link rel=STYLESHEET href=\"wawi.css\" type=\"text/css\">\n");
}
// Sends a header which refreshes to the given URL after a second
void RefreshHeader(connection * conn, char * url)
{
prints(conn,"<meta http-equiv=\"Refresh\" content=\"1; url=");
prints(conn,url);
prints(conn,"\">\n");
}
// Close HTML Header
void CloseHeader(connection * conn)
{
AboutSource(conn);
prints(conn,"</head>\n");
}
// Opens HTML page body
void OpenPageBody(connection * conn)
{
prints(conn,"<body bgcolor=\"#");
prints(conn,"EEEEEE");
prints(conn,"\">");
//OpenTable(conn);
}
// Opens HTML header body
void OpenHeaderBody(connection * conn)
{
prints(conn,"<body leftmargin=\"0\" rightmargin=\"0\" topmargin=\"0\" bgcolor=\"#000000\">\n");
//OpenTable(conn);
}
// Closes HTML body
void CloseBody(connection * conn)
{
//CloseTable(conn);
prints(conn,"</body>\n</html>\n\n");
}
// Open page table
void LinkTable(connection * conn)
{
prints(conn,"<table border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\">\n <tr>\n");
prints(conn,"<td width=\"2%\" bgcolor=\"#000000\">&nbsp;</td>\n");
prints(conn,"<td width=\"96%\" bgcolor=\"#000000\">");
ImgLinkBar(conn);
prints(conn,"</td>\n<td width=\"2%\" bgcolor=\"#000000\">&nbsp;</td>\n</tr>\n</table>\n");
}
// --------------------------------------------------------------------------------
// Sticks a dot in... separator between stuff
void dot(connection * conn)
{
prints(conn,"&middot;");
}
// Nonbreaking space
void nbsp(connection * conn)
{
prints(conn,"&nbsp;");
}
// --------------------------------------------------------------------------------
// Image
void Img(connection * conn, int img, char * alt, int dx, int dy)
{
prints(conn,"<img border=\"0\" src=\"img?image=");
printsi(conn,img);
prints(conn,"\" alt=\"");
prints(conn,alt);
prints(conn,"\"");
if (dx != 0 || dy != 0)
{
prints(conn," width=\"");
printsi(conn,dx);
prints(conn,"\" height=\"");
printsi(conn,dy);
prints(conn,"\"");
}
prints(conn,">");
}
// --------------------------------------------------------------------------------
// Image link
void ImgLink(connection * conn, char * link, int img, char * alt, int dx, int dy, int target)
{
prints(conn,"<a href=\"");
prints(conn,link);
prints(conn,"\"");
switch(frames)
{
case 1: if (target == T_TOP)
prints(conn," target=\"_top\"");
break;
case 2: if (target == T_MAIN || target == T_BOTTOM)
prints(conn," target=\"main\"");
if (target == T_TOP)
prints(conn," target=\"_top\"");
break;
case 3: if (target == T_MAIN)
prints(conn," target=\"main\"");
if (target == T_BOTTOM)
prints(conn," target=\"bottom\"");
if (target == T_TOP)
prints(conn," target=\"_top\"");
break;
default: break;
}
prints(conn,"><img border=\"0\" src=\"img?image=");
printsi(conn,img);
prints(conn,"\" alt=\"");
prints(conn,alt);
prints(conn,"\">");
if (dx != 0 || dy != 0)
{
prints(conn," width=\"");
printsi(conn,dx);
prints(conn,"\" height=\"");
printsi(conn,dy);
prints(conn,"\">");
}
prints(conn,"</a>");
}
// --------------------------------------------------------------------------------
// Text Link
void Link(connection * conn, char * link, char * text, int target)
{
prints(conn,"<a href=\"");
prints(conn,link);
prints(conn,"\"");
switch(frames)
{
case 2: if (target == T_MAIN || target == T_BOTTOM)
prints(conn," target=\"main\"");
break;
case 3: if (target == T_MAIN)
prints(conn," target=\"main\"");
if (target == T_BOTTOM)
prints(conn," target=\"bottom\"");
break;
default: break;
}
prints(conn,">");
prints(conn,text);
prints(conn,"</a>");
}
// --------------------------------------------------------------------------------
// Function source for javascript popup about window
void AboutSource(connection * conn)
{
prints(conn,"<Script language=\"JavaScript\">\nfunction about()\n{\n window.open(\"about\",\"newWin\",\"width=300,height=150\");\n}\n</script>\n\n");
}
// --------------------------------------------------------------------------------
// Displays the volume controls and link bar - Graphics version
void ImgLinkBar(connection * conn)
{
prints(conn,"<p align=center>\n");
// Play control links
ImgLink(conn,"/prev",IDR_IMG_PREV,"Previous Track",0,0,T_BOTTOM);
Img(conn,IDR_IMG_BLACK,"",2,30);
//nbsp(conn);
ImgLink(conn,"/play",IDR_IMG_PLAY,"Play",0,0,T_BOTTOM);
//nbsp(conn);
Img(conn,IDR_IMG_BLACK,"",2,30);
ImgLink(conn,"/pause",IDR_IMG_PAUSE,"Pause",0,0,T_BOTTOM);
//nbsp(conn);
Img(conn,IDR_IMG_BLACK,"",2,30);
ImgLink(conn,"/stop",IDR_IMG_STOP,"Stop",0,0,T_BOTTOM);
//nbsp(conn);
Img(conn,IDR_IMG_BLACK,"",2,30);
ImgLink(conn,"/stopslow",IDR_IMG_STOPSLOW,"Stop with fadeout",0,0,T_BOTTOM);
//nbsp(conn);
Img(conn,IDR_IMG_BLACK,"",2,30);
ImgLink(conn,"/next",IDR_IMG_NEXT,"Next Track",0,0,T_BOTTOM);
Img(conn,IDR_IMG_BLACK,"",8,30);
// Volume control links
ImgLink(conn,"/vol?volume=0",IDR_VOL_00,"0/10",0,0,T_BOTTOM);
ImgLink(conn,"/vol?volume=1",IDR_VOL_01,"1/10",0,0,T_BOTTOM);
ImgLink(conn,"/vol?volume=2",IDR_VOL_02,"2/10",0,0,T_BOTTOM);
ImgLink(conn,"/vol?volume=3",IDR_VOL_03,"3/10",0,0,T_BOTTOM);
ImgLink(conn,"/vol?volume=4",IDR_VOL_04,"4/10",0,0,T_BOTTOM);
ImgLink(conn,"/vol?volume=5",IDR_VOL_05,"5/10",0,0,T_BOTTOM);
ImgLink(conn,"/vol?volume=6",IDR_VOL_06,"6/10",0,0,T_BOTTOM);
ImgLink(conn,"/vol?volume=7",IDR_VOL_07,"7/10",0,0,T_BOTTOM);
ImgLink(conn,"/vol?volume=8",IDR_VOL_08,"8/10",0,0,T_BOTTOM);
ImgLink(conn,"/vol?volume=9",IDR_VOL_09,"9/10",0,0,T_BOTTOM);
ImgLink(conn,"/vol?volume=10",IDR_VOL_10,"10/10",0,0,T_BOTTOM);
Img(conn,IDR_IMG_BLACK,"",8,30);
// Page navigation links
ImgLink(conn,"/main",IDR_IMG_MAIN,"Main",0,0,T_MAIN);
//nbsp(conn);
Img(conn,IDR_IMG_BLACK,"",2,30);
ImgLink(conn,"/list",IDR_IMG_PLAYLIST,"Playlist",0,0,T_MAIN);
//nbsp(conn);
Img(conn,IDR_IMG_BLACK,"",2,30);
ImgLink(conn,"/browse?path=%5c",IDR_IMG_BROWSE,"Music Collection",0,0,T_MAIN);
//nbsp(conn);
Img(conn,IDR_IMG_BLACK,"",2,30);
prints(conn,"<script language=\"JavaScript\">\nvar shortcut = new String(document.location);\nvar len = shortcut.lastIndexOf('/');\nshortcut = shortcut.slice(0,len+1);\n");
prints(conn,"document.write(\"<a href=\\\"javascript:void(weblog=open('\" + shortcut + \"','','width=600,height=360,toolbar=0,location=0,directories=0,status=0,menuBar=0,scrollBars=1,resizable=1'))\\\"><img src=/img?image=\");");
prints(conn,"\ndocument.write(");
printsi(conn,IDR_IMG_POPUP);
prints(conn,");");
prints(conn,"\ndocument.write(\" border=\\\"0\\\" alt=\\\"Winamp Web Interface Popup Window\\\"></a>\");\n</script>");
Img(conn,IDR_IMG_BLACK,"",2,30);
ImgLink(conn,"/admin",IDR_IMG_ADMIN,"Wawi Admin",0,0,T_MAIN);
//nbsp(conn);
Img(conn,IDR_IMG_BLACK,"",2,30);
ImgLink(conn,"javascript:about()",IDR_IMG_ABOUT,"About Winamp Web Interface",0,0,T_NONE);
prints(conn,"</p>\n");
}
// --------------------------------------------------------------------------------
// Displays the volume controls and link bar - Noframes version
void LinkBar(connection * conn)
{
prints(conn,"<p align=center>\n");
// Volume control links
prints(conn,"Volume: \n");
for (int i=0;i<=10;i++)
{
prints(conn,"<a href=/vol?volume=");
printsi(conn,i);
prints(conn,">");
printsi(conn,i);
prints(conn,"</a>\n");
if (i != 10)
dot(conn);
}
prints(conn,"<br>\n");
// Play control links
prints(conn,"<a href=\"/prev\">Previous</a>\n");
dot(conn);
prints(conn," <a href=\"/play\">Play</a>\n");
dot(conn);
prints(conn," <a href=\"/pause\">Pause</a>\n");
dot(conn);
prints(conn," <a href=\"/stop\">Stop</a>\n");
dot(conn);
prints(conn," <a href=\"/next\">Next</A>\n");
prints(conn,"<br><a href=\"/main\">Main</a>\n");
dot(conn);
prints(conn," <a href=\"/list\">Playlist</a>\n");
dot(conn);
prints(conn," <a href=\"/browse?path=%5c\">Music Collection</a>\n");
dot(conn);
prints(conn," <a href=\"/admin\">Admin</a>\n");
prints(conn,"</p>\n");
}
// --------------------------------------------------------------------------------
// Retrieves and formats the information about the current song
void FullSongInfo(connection * conn)
{
char tbuffer[255];
int status = SendMessage(WAwnd(),WM_USER, 0, WAU_STATUS);
int pos = SendMessage(WAwnd(),WM_USER, 0, WAU_GETPLPOS)+1;
char * trackname = (char*)SendMessage(WAwnd(),WM_USER, pos-1, WAU_GETTITLE);
//MessageBox(NULL,"Still going!","gen_httpSrv debug",MB_OK);
switch(status)
{
case 1: if (trackname==NULL)
wsprintf(tbuffer,"Winamp is playing");
else
wsprintf(tbuffer,"Playing track %d - %s - ", pos,trackname);
prints(conn,tbuffer);
PrintTrackTime(conn);
break;
case 3: if (trackname==NULL)
wsprintf(tbuffer,"Winamp is paused");
else
wsprintf(tbuffer,"Paused in track %d - %s - ", pos,trackname);
prints(conn,tbuffer);
PrintTrackTime(conn);
break;
default: if (trackname==NULL)
wsprintf(tbuffer,"Winamp is stopped");
else
wsprintf(tbuffer,"Winamp is stopped at track %d - %s", pos, trackname );
prints(conn,tbuffer);
break;
}
}
// --------------------------------------------------------------------------------
// Retrieves and formats a tiny string of the current song information (for /smalltitle)
void SongInfo(connection * conn)
{
int status = SendMessage(WAwnd(),WM_USER, 0, WAU_STATUS);
int pos = SendMessage(WAwnd(),WM_USER, 0, WAU_GETPLPOS)+1;
char * trackname = (char*)SendMessage(WAwnd(),WM_USER, pos-1, WAU_GETTITLE);
//MessageBox(NULL,"Still going!","gen_httpSrv debug",MB_OK);
switch(status)
{
case 1: if (trackname!=NULL)
{
//wsprintf(tbuffer,"%s", pos,trackname);
prints(conn,trackname);
}
break;
default: break;
}
}

20
Wawi Source/html.h Normal file
View File

@@ -0,0 +1,20 @@
// html.cpp
void OpenHTTPHeader(connection * conn, char * type, int length, char * filename);
void OpenHtmlHeader(connection * conn);
void Style(connection * conn);
void RefreshHeader(connection * conn, char * url);
void CloseHeader(connection * conn);
void OpenPageBody(connection * conn);
void OpenHeaderBody(connection * conn);
void CloseBody(connection * conn);
void LinkTable(connection * conn);
void dot(connection * conn);
void nbsp(connection * conn);
void Img(connection * conn, int img, char * alt, int dx, int dy);
void ImgLink(connection * conn, char * link, int img, char * alt, int dx, int dy, int target);
void Link(connection * conn, char * link, char * text, int target);
void AboutSource(connection * conn);
void ImgLinkBar(connection * conn);
void LinkBar(connection * conn);
void FullSongInfo(connection * conn);
void SongInfo(connection * conn);

299
Wawi Source/main.cpp Normal file
View File

@@ -0,0 +1,299 @@
/* --- MAIN.CPP ---
/
/ Written by Phil Himsworth, 2001-2002.
/
/*/
#include <windows.h>
#include <process.h>
#include <winver.h>
#include "types.h"
#include "plugin.h"
#include "resource.h"
#include "main.h"
char szAppName[] = "Winamp Web Interface";
char szAppVer[10]; // now filled in automagically on startup
char mp3root[MAX_PATH];
char playlistdir[MAX_PATH];
char filetypes[255]; // file types which will show in the browse bit.
char pagetitle[255];
char logfiledir[MAX_PATH];
extern char bchars[]; // lookup table for base64 needs to be built on startup
extern char achars[256];
// All winamp needs to know about the plugin
winampGeneralPurposePlugin plugin =
{
GPPHDR_VER,
"",
init,
config,
quit,
};
// Globals for actual server (rather than random winamp things)
LPDWORD client_thread;
SOCKET server_socket;
int con_port, hide_error, frames, title_refresh;
int show_other_files, dl_wa_files, dl_other_files;
extern HWND ConfigWnd;
// --------------------------------------------------------------------------------
// Entry point of DLL for windows; does nothing
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}
// --------------------------------------------------------------------------------
// The interface which Winamp sees-
// It returns the plugin information struct
extern "C"
{
__declspec( dllexport ) winampGeneralPurposePlugin * winampGetGeneralPurposePlugin()
{
return &plugin;
}
}
// --------------------------------------------------------------------------------
// Startup. This is where interesting things start happening
int init()
{
HANDLE newthread;
DWORD newthread_id;
static char c[512];
char filename[512],*p;
GetModuleFileName(plugin.hDllInstance,filename,sizeof(filename));
// Retrieve version info
DWORD versize = GetFileVersionInfoSize(filename, NULL);
char * versiondata = new char[versize];
GetFileVersionInfo(filename, NULL, versize, versiondata);
VS_FIXEDFILEINFO * info;
UINT verlen;
VerQueryValue(versiondata,"\\",(void**)&info,&verlen);
int ver_l = (int)info->dwFileVersionLS;
int ver_h = (int)info->dwFileVersionMS;
int ver1, ver2, ver3, ver4; // version of form ver1,ver2,ver3,ver4
/*
ver1 = (ver_h & 0xFFFF0000) >> 16;
ver2 = (ver_h & 0x0000FFFF);
ver3 = (ver_l & 0xFFFF0000) >> 16;
ver4 = (ver_l & 0x0000FFFF);
*/
ver1 = HIWORD(ver_h);
ver2 = LOWORD(ver_h);
ver3 = HIWORD(ver_l);
ver4 = LOWORD(ver_l);
if (ver3 == 0)
wsprintf(szAppVer,"%u.%u", ver1, ver2);
else
wsprintf(szAppVer,"%u.%u.%u", ver1, ver2, ver3);
delete versiondata;
ZeroMemory(achars,256);
for(int i = 0; i < 64; i++) // build lookup table for FromBase64()
achars[bchars[i]] = i;
p = filename+lstrlen(filename);
while (p >= filename && *p != '\\') p--;
wsprintf((plugin.description=c),"%s Plugin v.%s (%s)",szAppName,szAppVer,p+1);
newthread = CreateThread(NULL,0,HTTPServerThread,0,0,&newthread_id);
return 0;
}
// --------------------------------------------------------------------------------
// Config dialog please
void config()
{
if (!ConfigWnd)
{
NewConfig();
ConfigWnd = NULL;
}
else
SetActiveWindow(ConfigWnd);
}
// --------------------------------------------------------------------------------
// Winamp is saying goodbye
void quit()
{
// Hmmm. Did there always used to be nothing in here? Curiouser and curiouser...
}
// --------------------------------------------------------------------------------
// Opens the server socket
bool InitServerSocket()
{
config_read();
WORD wVersionRequested = MAKEWORD(2,2);
WSADATA wsaData;
if (WSAStartup(wVersionRequested, &wsaData ) != 0 )
{
if (hide_error == 0)
MessageBox(plugin.hwndParent, "ERROR: Winsock not available", "Winamp Web Interface", MB_OK);
return false;
}
server_socket = socket(AF_INET,SOCK_STREAM,0);
if (server_socket == INVALID_SOCKET)
{
if (hide_error == 0)
MessageBox(plugin.hwndParent, "ERROR: Couldn't create socket", "Winamp Web Interface", MB_OK);
return false;
}
struct sockaddr_in server_address;
ZeroMemory(&server_address,sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(con_port);
if (bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address)) != 0)
{
if (hide_error == 0)
MessageBox(plugin.hwndParent, "ERROR: Couldn't open port", "Winamp Web Interface", MB_OK);
return false;
}
if (listen(server_socket,5) != 0)
{
if (hide_error == 0)
MessageBox(plugin.hwndParent, "ERROR: Cannot act as server", "Winamp Web Interface", MB_OK);
return false;
}
return true; // Server socket opened successfully
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Server main thread entry point
DWORD WINAPI HTTPServerThread(LPVOID param)
{
// initialise winsock
if (InitServerSocket())
{
//printf("Server is listening for connections on port %d.\n",ntohs(server_address.sin_port));
struct sockaddr_in client_address;
SOCKET client_socket;
int client_address_length = sizeof(client_address);
while (true)
{
client_socket = accept(server_socket,(struct sockaddr *) &client_address, &client_address_length);
//printf("Connection request from %s:%d - ", (char*)inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));
if (client_socket != INVALID_SOCKET)
{
DWORD connection_id;
client_thread = (DWORD*)CreateThread(NULL,0,ClientConnection,(void*)client_socket, 0, &connection_id);
}
}
closesocket(server_socket);
}
return true;
}
// --------------------------------------------------------------------------------
// *** WINAMP FUNCTIONS ***
// Returns handle to winamp window
HWND WAwnd()
{
return plugin.hwndParent;
}
// --------------------------------------------------------------------------------
// Insert a node into a list starting from 'current'
void Insert(fileinfo *newfile, fileinfo *current)
{
if (GoesBefore(newfile->name,current->name)) // newfile goes before current
{
//wsprintf(tempstring,"%s goes before %s and after %s",newfile->name,current->name, current->prev->name);
//MessageBox(NULL,tempstring,"gen_httpsrv debug goes before",MB_OK);
if (current->prev != NULL)
current->prev->next = newfile;
newfile->prev = current->prev;
newfile->next = current;
current->prev = newfile;
//wsprintf(tempstring,"Order is now %s, %s, %s",newfile->prev->name,newfile->name,newfile->next->name);
//MessageBox(NULL,tempstring,"gen_httpsrv debug goes before result",MB_OK);
}
else
{
if (current->next == NULL) // newfile is after current; current is the last node
{
//wsprintf(tempstring,"%s goes after %s and is the last record",newfile->name,current->name);
//MessageBox(NULL,tempstring,"gen_httpsrv debug after and last",MB_OK);
current->next = newfile;
newfile->prev = current;
}
else
{ // newfile is after current but before something else
Insert(newfile,current->next); // AAARGH! RECURSION! Like hell it'll work...
}
}
}
// --------------------------------------------------------------------------------
// Compare two strings, return TRUE if the first one should be before the second alphabetically
bool GoesBefore(char *file1, char *file2)
{
if (file1 == NULL || file2 == NULL)
return true;
int i=0;
while (ToLowerCase(file1[i]) == ToLowerCase(file2[i]))
{
if (file1[i] == 0)
return true;
i++;
}
if (ToLowerCase(file1[i]) > ToLowerCase(file2[i]))
return false;
else
return true;
}

96
Wawi Source/main.h Normal file
View File

@@ -0,0 +1,96 @@
// browse.cpp
void UpDirectory(char * mp3path, char * mp3pathout);
bool IsWinampFile(fileinfo * file);
bool IsWinampFile(char * filename);
void AddFileToList(connection * conn,WIN32_FIND_DATA *find, char* mp3path, filesearch * search);
bool GoodPath(char* mp3path);
int Browse(connection * conn, char * mp3path);
// ClientConnection.cpp
DWORD WINAPI ClientConnection(LPVOID socket_param);
void MakeLogEntry(connection * conn);
// Config.cpp
BOOL CALLBACK ConfigUsersWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
BOOL CALLBACK ConfigAboutWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
BOOL CALLBACK ConfigServerWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
BOOL CALLBACK ConfigWebPageWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
BOOL CALLBACK ConfigBrowseWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
BOOL CALLBACK ConfigLogWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
void config_read();
void config_write();
void ViewLog();
void NewConfig();
// Config_users.cpp
BOOL CALLBACK ConfigUsersWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
void UpdateUserInfoBoxes(HWND hwndDlg, HWND hwndList, char * ini_file, int item);
void DisplayDlgAccess(HWND hwndDlg, int access);
int GetDlgAccess(HWND hwndDlg);
user * RetrieveUsers(user * users, char * ini_file);
void UpdateUserList(char * ini_file, HWND hwndList);
void UpdateDlgUser(char * ini_file, HWND hwndDlg, HWND hwndList);
void UpdateUser(char * ini_file,char * username, char * password, int access);
void DeleteDlgUser(char * ini_file, HWND hwndDlg, HWND hwndList);
void DeleteUser(char * ini_file, char * username);
// DeletePlaylistEntry.cpp
int DeletePlaylistEntry(int track);
void FreePlaylist(playlistitem * startitem);
int DeletePlaylistEntry2(connection * conn, int track);
// main.cpp
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved);
int init();
void config();
void quit();
bool InitServerSocket();
DWORD WINAPI HTTPServerThread(LPVOID param);
HWND WAwnd();
void Insert(fileinfo *file1, fileinfo *file2);
bool GoesBefore(char *file1, char *file2);
//net_http_html.cpp
void prints(connection * conn, char * string);
void flush(connection * conn);
void printsi(connection * conn, int number);
void ReportError(connection * conn, char * errstring);
void Send400(connection * conn);
bool GetRequest(connection * conn);
bool DecodeUrl(connection * conn);
void ListArgs(connection * conn);
bool GetArgValue(connection * conn, char * name, char * value, int len);
void Unescape_url(char * url);
char x2c(char *what);
void Escape_url(char * url);
// security.cpp
bool MD5(char * input, char * output, int output_len);
int SendBasic401(connection * conn,char * realm);
char * FindSubString(char * buffer,char * target);
void FindBasicAuth(connection * conn, char * buffer);
void ToBase64(char * instr, char * outstr);
void FromBase64(char * instr, char * outstr);
int CheckCredentials(connection * conn, char * user, char * pass);
int GetUserAccess(char * ini_file,char * user);
// strings.cpp
char * GetDelimitedString(char * buffer, char delimiter, char * result, int result_len);
bool GetUnquotedString(char * buffer, char * result, int result_len);
bool GetQuotedString(char * buffer, char * result, int result_len);
bool StartString(char* string1, char* string2);
char * GetAString(char* chptr, char* text);
void PrintTime(connection * conn, int mins, int seconds);
void PrintTrackTime(connection * conn);
void ToLowerCase(char * string);
char ToLowerCase(char c);
bool StrComp(char * string1, char * string2);
void ReplaceSlashes(char * string);
char * GetFilename(char * path);
int atoi2(const char *str );
bool contains(char * echars,char ch);
char * strstr2(char *string, char *substring);

BIN
Wawi Source/makepimp.exe Normal file

Binary file not shown.

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);
}

1027
Wawi Source/op_winamp.cpp Normal file

File diff suppressed because it is too large Load Diff

35
Wawi Source/op_winamp.h Normal file
View File

@@ -0,0 +1,35 @@
// op_winamp.cpp
class CControl
{
public:
int Image(connection * conn,int type);
int TopFrame(connection * conn);
int SmallTitle(connection * conn);
int Title(connection * conn);
int Shutdown(connection * conn);
int Clear(connection * conn);
int Download(connection * conn);
int Load(connection * conn);
int List(connection * conn);
int Next(connection * conn);
int Prev(connection * conn);
int Play(connection * conn);
int Stop(connection * conn);
int StopSlow(connection * conn);
int Pause(connection * conn);
int Volume(connection * conn);
int Playmode(connection * conn);
int About(connection * conn);
int Main(connection * conn);
int WebAdmin(connection * conn);
int ApplyAdmin(connection * conn);
int pda(connection * conn);
int Delete(connection * conn);
int User(connection * conn);
int SetUser(connection * conn);
int UserStyle(connection * conn);
int Sort(connection * conn);
int SavePlaylist(connection * conn);
};

2
Wawi Source/pimp.bat Normal file
View File

@@ -0,0 +1,2 @@
@echo off
makepimp gen_httpsrv.psc

BIN
Wawi Source/playdir.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 904 B

BIN
Wawi Source/playlist.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

14
Wawi Source/plugin.h Normal file
View File

@@ -0,0 +1,14 @@
typedef struct {
int version;
char *description;
int (*init)();
void (*config)();
void (*quit)();
HWND hwndParent;
HINSTANCE hDllInstance;
} winampGeneralPurposePlugin;
#define GPPHDR_VER 0x10
extern winampGeneralPurposePlugin *gen_plugins[256];
typedef winampGeneralPurposePlugin * (*winampGeneralPurposePluginGetter)();

118
Wawi Source/resource.h Normal file
View File

@@ -0,0 +1,118 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by Resource.rc
//
#define IDABOUT 3
#define IDC_VIEWLOG 4
#define IDUSERS 5
#define IDD_DIALOG1 101
#define IDR_DIRECTORY 107
#define IDR_WAFILE 110
#define IDR_PLAYLIST 111
#define IDR_FILE 112
#define IDR_DOWNLOAD 113
#define IDR_IMG_ABOUT 114
#define IDR_IMG_STOP 115
#define IDR_IMG_MAIN 116
#define IDR_IMG_NEXT 117
#define IDR_IMG_PAUSE 118
#define IDR_IMG_PLAY 119
#define IDR_IMG_PLAYLIST 120
#define IDR_IMG_PREV 121
#define IDR_IMG_BROWSE 122
#define IDR_IMG_BLACK 123
#define IDR_VOL_09 124
#define IDR_VOL_10 125
#define IDR_VOL_02 126
#define IDR_VOL_03 127
#define IDR_VOL_04 128
#define IDR_VOL_05 129
#define IDR_VOL_06 130
#define IDR_VOL_07 131
#define IDR_VOL_08 132
#define IDR_VOL_01 133
#define IDR_VOL_00 134
#define IDR_IMG_POPUP 135
#define IDR_IMG_STOPSLOW 136
#define IDR_PLAYDIR 137
#define IDD_USERS 138
#define IDR_ICO_WINAMP 141
#define IDR_URLSCT 142
#define IDR_IMG_ADMIN 143
#define IDR_IMG_OK 144
#define IDR_IMG_RPT_ON 145
#define IDR_IMG_RND_ON 146
#define IDR_IMG_RPT_OFF 147
#define IDR_IMG_RND_OFF 148
#define IDR_IMAGE1 150
#define IDR_IMG_LIST_DEL 151
#define IDR_IMG_LIST_PLAY 152
#define IDD_SERVER 153
#define IDD_WEBPAGE 154
#define IDD_BROWSE 156
#define IDD_ABOUT 157
#define IDD_LOG 158
#define IDI_USERS 159
#define IDI_SERVER 160
#define IDI_WEBPAGE 161
#define IDI_BROWSE 162
#define IDI_LOG 163
#define IDB_FRAMES_TWO 164
#define IDB_FRAMES_THREE 165
#define IDB_FRAMES_ONE 166
#define IDI_WINAMP 168
#define IDB_TITLE 170
#define IDC_PORT_EDIT 1000
#define IDC_HIDE_ERROR 1001
#define IDC_MP3_ROOT 1002
#define IDC_PLAYLISTDIR 1003
#define IDC_FILETYPES 1004
#define IDC_FILETYPEHELP 1005
#define IDC_ROOTDIRHELP 1006
#define IDC_HIDEOTHERFILES 1007
#define IDC_OTHER_FILES_SHOW 1007
#define IDC_OTHER_FILES_DL 1008
#define IDC_WA_FILES_DL 1009
#define IDC_PLAYLISTDIRHELP 1010
#define IDC_WA_FILES_SHOW 1011
#define IDC_PAGETITLE 1012
#define IDC_PAGETITLEHELP 1013
#define IDC_TEXTMODE 1014
#define IDC_PORT_EDIT2 1015
#define IDC_USERNAME 1015
#define IDC_SECUREPASSWORD 1015
#define IDC_PASSWORD 1016
#define IDC_LOGFILEPATH 1018
#define IDC_REFRESH 1019
#define IDC_USERS 1020
#define IDC_BUTTON1 1023
#define IDC_UPDATE 1023
#define IDC_SECUREPASSWORDHELP 1023
#define IDC_AUTH_SHUTDOWN 1024
#define IDC_AUTH_SERVER 1024
#define IDC_AUTH_CONTROL 1025
#define IDC_AUTH_PLAYLIST 1026
#define IDC_AUTH_DOWNLOAD 1027
#define IDC_BROWSE 1028
#define IDC_AUTH_BROWSE 1028
#define IDC_DELETE 1029
#define IDC_ADD 1030
#define IDC_AUTH_CLEAR 1031
#define IDC_PASS_DEBUG 1032
#define IDC_NOFRAMES 1035
#define IDC_TWOFRAMES 1036
#define IDC_THREEFRAMES 1037
#define IDC_FRAMEIMG 1040
#define IDC_MAINIMAGE 1042
#define IDC_ABOUT_TITLE 1043
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 171
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1044
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

312
Wawi Source/security.cpp Normal file
View File

@@ -0,0 +1,312 @@
/* --- SECURITY.CPP ---
/
/ Written by Phil Himsworth, 2001-2002.
/
/*/
#include <windows.h>
#include <wincrypt.h>
#include <mmsystem.h>
#include "types.h"
#include "main.h"
#include "html.h"
#include "plugin.h"
extern char password[], username[];
extern int securepassword;
extern winampGeneralPurposePlugin plugin;
// Base64 character array
// 0 1 2 3 4 5 6
// 01234567890123456789012345678901234567890123456789012345678901234
char bchars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+*";
char achars[256];
// --------------------------------------------------------------------------------
// Calculates MD5 of a string
bool MD5(char * input, char * output, int output_len)
{
//MessageBox(NULL,input,"MD5 input",MB_TOPMOST | MB_OK);
HCRYPTPROV hProv = 0;
HCRYPTHASH Hash;
if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
MessageBox( NULL, (LPCTSTR)lpMsgBuf, "MD5 AcquireContext Error", MB_OK | MB_ICONINFORMATION );
// Free the buffer.
LocalFree( lpMsgBuf );
return false;
}
CryptCreateHash(hProv,CALG_MD5, 0, 0, &Hash);
int input_len = lstrlen(input);
BYTE md5raw[2048];
int md5raw_len = 2048;
CryptHashData(Hash,(unsigned char*)input,input_len, 0); // md5 of "<time>:<password>"
CryptGetHashParam(Hash, HP_HASHVAL, md5raw,(DWORD*)&md5raw_len,0);
wsprintf(output,""); // Make output a terminated string
char temp[4];
//wsprintf(temp,"%d",md5raw_len);
//MessageBox(NULL,temp,"gen_httpSrv md5raw_len",MB_OK);
for (int i=0;i<md5raw_len;i++)
{
wsprintf(temp,"%2.2x", md5raw[i]);
lstrcat(output,temp);
}
//MessageBox(NULL,output,"gen_httpSrv debug MD5", MB_OK);
CryptReleaseContext(hProv,0);
return true;
}
// --------------------------------------------------------------------------------
// Sends a 401 for Basic authentication
int SendBasic401(connection * conn, char * realm)
{
prints(conn,"HTTP/1.0 401 Unauthorized\nWWW-Authenticate: Basic realm=\"");
prints(conn,realm);
prints(conn,"\"\n");
prints(conn,"Content-Type: text/html\n\n<html>\n<head>\n<title>Login Failed</title>\n");
Style(conn);
CloseHeader(conn);
OpenPageBody(conn);
prints(conn,"<h1>Login Failed</h1>\n<p><b>Winamp Web Interface could not log you in.</b></p>\n<p><a href=\"/main\">Back to main page</a></p>");
CloseBody(conn);
conn->http.responsecode = 401;
return ST_CLOSE;
}
// --------------------------------------------------------------------------------
// Finds a substring in another string. Probably should be in strings.cpp...
char * FindSubString(char * buffer,char * target)
{
//MessageBox(NULL,buffer,"gen_httpSrv FindSubString",MB_OK);
int len = lstrlen(buffer) - lstrlen(target);
for (int i=0;i<=len;i++)
{
if (StartString(target,buffer+i))
return (char*)(buffer+i);
}
return NULL;
}
// --------------------------------------------------------------------------------
// Finds auth headers in a request
void FindBasicAuth(connection * conn, char * buffer)
{
//int ptr;
//MessageBox(NULL,buffer,"gen_httpSrv FindBasicAuth: buffer",MB_OK);
char * chptr = FindSubString(buffer,"Authorization:"); // Look for auth
if (!chptr)
{ // Not found
chptr = FindSubString(buffer,"Authorisation:"); // Misspellings?
if (!chptr) // Still no; fail
{
//MessageBox(NULL,"No Auth","gen_httpSrv debug FindBasicAuth",MB_OK);
conn->http.auth = CheckCredentials(conn,"anon","");
return;
}
}
// Authorisation section found
//MessageBox(NULL,chptr,"gen_httpSrv debug",MB_OK);
char temp[100];
char * cl_user;
char * cl_pass;
chptr = GetAString(chptr,(char*)&temp); // chptr now points at Authorisation, so get it
chptr = GetAString(chptr,(char*)&temp); // get auth mode - 'basic'
chptr = GetAString(chptr,(char*)&temp); // get user/pass string
char userpass[100];
FromBase64((char*)&temp,(char*)&userpass);
int i=0;
while(userpass[i] != ':')
{
if (userpass[i] == 0)
{
conn->http.auth = CheckCredentials(conn,"anon","");
return;
}
i++;
}
userpass[i] = 0;
cl_pass = &userpass[i+1];
cl_user = (char*)&userpass;
//wsprintf(temp,"User: %s\nPassword: %s",cl_user,cl_pass);
//MessageBox(NULL,temp,"user/password",MB_TOPMOST | MB_OK);
//MessageBox(NULL,temp,"gen_httpSrv debug base64 from client",MB_OK);
conn->http.auth = CheckCredentials(conn, cl_user, cl_pass);
}
// --------------------------------------------------------------------------------
// Converts a string to Base64
void ToBase64(char * instr, char * outstr)
{
//MessageBox(NULL,instr,"instr",MB_OK);
int i=0;
int o=0;
int j = lstrlen(instr);
bool done = false;
while(instr[i] != 0 && done == false)
{
outstr[o] = bchars[(instr[i] & 0xFC) / 4];
outstr[o+1] = bchars[((instr[i] & 0x03) * 16) + ((instr[i+1] & 0xF0) / 16)];
if (instr[i+1] == 0)
{
outstr[o+2] = '=';
outstr[o+3] = '=';
done = true;
}
else
{
outstr[o+2] = bchars[((instr[i+1] & 0x0F) * 4) + ((instr[i+2] & 0xC0) /64)];
if (instr[i+2] == 0)
{
outstr[o+3] = '=';
done = true;
}
else
outstr[o+3] = bchars[(instr[i+2] & 0x3F)];
}
o += 4;
i += 3;
}
outstr[o] = 0;
}
// --------------------------------------------------------------------------------
// Converts a Base64 string to plaintext
void FromBase64(char * instr,char * outstr)
{
int i=0;
int o=0;
int j=lstrlen(instr);
for (int n=0;n<j;n++) // reduce ascii codes to numbers
{
if (instr[n] != '=')
instr[n] = achars[instr[n]];
else
instr[n] = (char)255;
}
while(instr[i] != 0)
{
outstr[o] = ((instr[i] & 0x3F) * 4) + ((instr[i+1] & 0x30) / 16);
if (instr[i+2] == (char)255)
outstr[o+1] = 0;
else
{
outstr[o+1] = ((instr[i+1] & 0x0F) * 16) + ((instr[i+2] & 0x3C) / 4);
if (instr[i+3] == (char)255)
outstr[o+2] = 0;
else
outstr[o+2] = ((instr[i+2] & 0x03) * 64) + (instr[i+3] & 0x3F);
}
i += 4;
o += 3;
}
outstr[o] = 0;
}
// --------------------------------------------------------------------------------
// Checks credentials with those in ini file
int CheckCredentials(connection * conn, char * user, char * pass)
{
char ini_file[MAX_PATH], *p;
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");
if (StrComp(user,"anon"))
return GetUserAccess(ini_file,user);
char password[40];
GetPrivateProfileString("Users",user,"",(char*)&password,40,ini_file);
char md5pass[40];
if (securepassword == 1)
MD5(pass,(char*)&md5pass,40);
else
ToBase64(pass,md5pass);
//if (password[0] == 0)
// return AUTH_ANON;
//char temp[150];
//wsprintf(temp,"file: %s\nrecv: %s",password,md5pass);
//MessageBox(NULL,temp,"auth",MB_OK | MB_TOPMOST);
if (StrComp(password,md5pass))
{
wsprintf(conn->http.user,user);
return GetUserAccess(ini_file, user);
}
else
return AUTH_ANON;
}
// --------------------------------------------------------------------------------
// Gets access rights from the ini file
int GetUserAccess(char * ini_file,char * user)
{
char useraccesskey[30];
wsprintf(useraccesskey, "#%s_access", user);
return GetPrivateProfileInt("Users",useraccesskey,AUTH_ANON,ini_file);
}

BIN
Wawi Source/server.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

265
Wawi Source/strings.cpp Normal file
View File

@@ -0,0 +1,265 @@
/* --- STRINGS.CPP ---
/
/ Written by Phil Himsworth, 2001-2002.
/
/*/
#include <windows.h>
#include "wamessage.h"
#include "types.h"
#include "main.h"
// This would be so much easier if Clib didn't have memory leaks within CreateThread...
// Oh well, here are the random string doodles
// (And if I had found the Win32 string functions first...!)
// Returns a substring ending with the delimiter
char * GetDelimitedString(char * buffer, char delimiter, char * result, int result_len)
{
int ptr = 0;
while(buffer[ptr] != delimiter && ptr < result_len)
{
result[ptr] = buffer[ptr];
if (buffer[ptr] == 0) // Check for end of string
return NULL;
ptr++;
}
result[ptr] = 0;
return buffer+ptr;
}
// --------------------------------------------------------------------------------
// Gets a string not in quotes
bool GetUnquotedString(char * buffer, char * result, int result_len)
{
int resptr = 0, ptr = 0;
while(buffer[ptr] != ' ' && buffer[ptr] != ',' && buffer[ptr] != 0 && ptr != result_len) // copy string
{
result[resptr] = buffer[ptr];
ptr++;
resptr++;
}
result[resptr] = 0;
return true;
}
// --------------------------------------------------------------------------------
// Gets a string within quotes
bool GetQuotedString(char * buffer, char * result, int result_len)
{
int ptr = 0;
while(buffer[ptr] != '\"') // find first "
{
if (buffer[ptr] == 0) // end of string and no quote start found; fail
return false;
ptr++;
}
// ptr points to first "; move on 1 to start of string
ptr++;
int resptr = 0;
while(buffer[ptr] != '\"' && buffer[ptr] != 0 && ptr != result_len) // copy string until closing "
{ // or end of buffer
result[resptr] = buffer[ptr];
ptr++;
resptr++;
}
result[resptr] = 0; // make last char 0
return true;
}
// --------------------------------------------------------------------------------
// Checks if string2 begins with string1
bool StartString(char* string1, char* string2)
{
//char temp[2048];
//wsprintf(temp,"1: %s\n2:%s",string1,string2);
//MessageBox(NULL,temp,"gen_httpSrv StartString",MB_OK);
int ptr = 0;
while(ToLowerCase(string1[ptr]) == ToLowerCase(string2[ptr])) // Keep going until they're different
{
if (string1[ptr] == 0) // if string1 finishes, they're the same
return true;
ptr++;
}
if (string1[ptr] == 0) // If they're different because string1 has ended, yes
return true;
else
return false; // If they're different and string1 has not ended, no
}
// --------------------------------------------------------------------------------
// Retrieves next token from buffer
char * GetAString(char* chptr, char* text) // Old GetAString - only accepts single words
{
int bptr = 0;
int tptr = 0;
while (chptr[bptr] == ' ' || chptr[bptr] == '\n' || chptr[bptr] == '\r') // skip leading spaces and stuff
bptr++;
while (chptr[bptr] != 0 && chptr[bptr] != ' ' && chptr[bptr] != '\n' && chptr[bptr] != '\r' && bptr < 255) // while current char is a letter
{
text[tptr] = chptr[bptr]; // add letter to text[]
bptr++;
tptr++;
}
text[tptr] = 0;
chptr = chptr + bptr;
return chptr; // return pointer to the end of this string
}
// --------------------------------------------------------------------------------
// Mangles the time into a displayable format
void PrintTime(connection * conn, int mins,int seconds)
{
char tbuffer[20];
if (seconds<10) // Avoids it printing eg. '4:2' when it should be '4:02'
wsprintf(tbuffer,"%d:0%d",mins,seconds);
else
wsprintf(tbuffer,"%d:%d",mins,seconds);
prints(conn,tbuffer);
}
void PrintTrackTime(connection * conn)
{
int tracklen;
int trackpos = SendMessage(WAwnd(),WM_USER, 0, WAU_TRACKPOS) / 1000;
int mins = trackpos / 60;
int seconds = trackpos % 60;
prints(conn, " (");
PrintTime(conn,mins,seconds);
tracklen = SendMessage(WAwnd(),WM_USER, 1, WAU_TRACKLENGTH);
mins = tracklen / 60;
seconds = tracklen % 60;
prints(conn, " / ");
PrintTime(conn,mins,seconds);
prints(conn, ")\n\r");
}
// --------------------------------------------------------------------------------
// Convert a string to lower case
void ToLowerCase(char * string)
{
int i=0;
while (string[i] != 0 && i < 255)
{
if (string[i] >= 'A' && string[i] <= 'Z')
string[i] += 32;
i++;
}
}
// --------------------------------------------------------------------------------
// Convert a char to lower case
char ToLowerCase(char c)
{
if (c >= 'A' && c <= 'Z')
c += 32;
return c;
}
// --------------------------------------------------------------------------------
// Blatantly better Strcmp using win32 lstrcmp
bool StrComp(char * string1, char * string2)
{
if (lstrcmp(string1, string2) == 0) // Converts result from lstrcmp to a bool
return true;
else
return false;
}
// --------------------------------------------------------------------------------
// Converts '/' characters to '\'... it's Opera trying to be helpful, dammit!
void ReplaceSlashes(char * string)
{
int ptr=0;
while (string[ptr]!=0)
{
if (string[ptr]=='/')
string[ptr] = '\\';
ptr++;
}
}
// --------------------------------------------------------------------------------
// Retrieves a filename from a full path
char * GetFilename(char * path)
{
char * filename;
for (int i=0;path[i] != 0;i++)
if (path[i]=='\\')
filename = path+i;
return filename+1; // ignore leading slash
}
// --------------------------------------------------------------------------------
// Non-clib version of atoi
int atoi2(const char *str )
{
int val = 0, mlt = 1;
char *p;
p = (char *) (str + lstrlen( str ) - 1);
for( ; p >= str; --p, mlt *= 10 ) {
val += (mlt * ((int)*p - '0'));
}
return val;
}
// --------------------------------------------------------------------------------
// Checks if string contains a character
bool contains(char * echars,char ch)
{
int x=0;
while(echars[x] != 0)
{
if (echars[x] == ch)
return true;
x++;
}
return false;
}
// --------------------------------------------------------------------------------
// Finds substring
char * strstr2(char *string, char *substring)
{
char *a, *b;
b = substring;
if (*b == 0) {
return string;
}
for ( ; *string != 0; string += 1) {
if (*string != *b) {
continue;
}
a = string;
while (1) {
if (*b == 0) {
return string;
}
if (*a++ != *b++) {
break;
}
}
b = substring;
}
return NULL;
}

108
Wawi Source/types.h Normal file
View File

@@ -0,0 +1,108 @@
// Global types and definitions
// list to store user information from ini file
struct user
{
char name[20];
user * next;
};
// return values from DeletePlaylistEntry
#define DPE_OK 1
#define DPE_NOREAD 2
#define DPE_NOWRITE 3
// playlist for deleting items
struct playlistitem
{
int number;
char time[10];
char name[MAX_PATH];
char path[MAX_PATH];
playlistitem * next;
};
struct fileinfo
{
char path[MAX_PATH];
char name[MAX_PATH];
bool playlist;
bool urlsct;
fileinfo *next;
fileinfo *prev;
};
struct filesearch
{
fileinfo *firstfile;
fileinfo *firstdir;
int dnodes;
int fnodes;
};
// Request IDs
#define RID_GET 101
#define RID_HEAD 102
// Image types
#define IMG_GIF 301
#define IMG_ICO 302
// Access level IDs. These get OR-ed together to come up with a single value
#define AUTH_ANON 0
#define AUTH_BROWSE 1
#define AUTH_DOWNLOAD 2
#define AUTH_PLAYLIST 4
#define AUTH_CLEAR 8
#define AUTH_CONTROL 16
#define AUTH_SERVER 32
// Target frames
#define T_NONE 601
#define T_MAIN 602
#define T_BOTTOM 603
#define T_TOP 604
// holds information about 1 name/value pair ...?<name>=<value>&...
struct argument
{
char name[30];
char value[128];
};
// Main connection information structure
struct http_request
{
char user[20]; // logged on user (or 'anon')
char request[10]; // 'GET', 'HEAD' etc
int reqID; // integer representing the above
char file[512]; // full requested url
char page[MAX_PATH]; // just the page, without arguments
char http_version[10]; // HTTP Version; eg. "HTTP/1.0"
int responsecode; // HTTP response; 200, 400, 401 etc
char realm[50]; // authentication realm
int auth; // access level
argument pairs[50]; // name/value pairs for arguments
int num_args; // number of arguments
};
#define BUF_LEN 10000
// Return states
#define ST_NONE 200
#define ST_CLOSE 201
#define ST_CLOSEBODY 202
struct connection
{
char output[BUF_LEN];
http_request http;
SOCKET socket;
sockaddr_in remote_host;
int state;
bool log;
};

BIN
Wawi Source/users.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
Wawi Source/wafile.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

45
Wawi Source/wamessage.h Normal file
View File

@@ -0,0 +1,45 @@
// defines for winamp API messages.
// WM_COMMAND winamp play control messages
#define WAC_PLAY 40045
#define WAC_PAUSE 40046
#define WAC_STOP 40047
#define WAC_NEXT 40048
#define WAC_PREV 40044
#define WAC_EXIT 40001
#define WAC_STOPFADE 40147
#define WAC_STOPNEXT 40157
// WM_COMMAND winamp misc control messages
#define WAC_HIDEMAIN 40258
#define WAC_HIDEPLAY 40040
#define WAC_HIDEEQ 40036
#define WAC_RANDOMT 40023
#define WAC_REPEATT 40022
#define WAC_QUIT 40001
// WM_USER winamp messages
#define WAU_CLEARPLIST 101
#define WAU_STATUS 104
#define WAU_SETPLPOS 121
#define WAU_GETPLPOS 125
#define WAU_TRACKLENGTH 105 // data = 1
#define WAU_TRACKPOS 105 // data = 0
#define WAU_GETRANDOM 250
#define WAU_GETREPEAT 251
#define WAU_SETRANDOM 252
#define WAU_SETREPEAT 253
#define WAU_GETTITLE 212
#define WAU_PLCOUNT 124
#define WAU_PLSAVE 120
#define WAU_UPDTITLE 243
// COPYDATASTRUCT winamp messages
#define IPC_PLAYFILE 100
// Playlist window WM_COMMAND messages
#define PLC_SORTTITLE 40209

BIN
Wawi Source/wawi_large.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
Wawi Source/wawi_small.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
Wawi Source/webpage.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

261
Wawi Source/winamp.m3u Normal file
View File

@@ -0,0 +1,261 @@
#EXTM3U
#EXTINF:239,Beautiful South - 36D
D:\Music\Albums\Beautiful South- Carry On Up The Charts\36D.mp3
#EXTINF:177,Beautiful South - A Little Time
D:\Music\Albums\Beautiful South- Carry On Up The Charts\A Little Time.mp3
#EXTINF:272,Beautiful South - Bell Bottomed Tear
D:\Music\Albums\Beautiful South- Carry On Up The Charts\Bell Bottomed Tear.mp3
#EXTINF:213,Beautiful South - Dream A Little Dream Of Me
D:\Music\Albums\Beautiful South- Carry On Up The Charts\Dream A Little Dream Of Me.mp3
#EXTINF:155,Beautiful South - Everybody's Talkin'
D:\Music\Albums\Beautiful South- Carry On Up The Charts\Everybody's Talkin'.mp3
#EXTINF:226,Beautiful South - Good As Gold (Stupid As Mud)
D:\Music\Albums\Beautiful South- Carry On Up The Charts\Good As Gold (Stupid As Mud).mp3
#EXTINF:243,Beautiful South - I'll Sail This Ship Alone
D:\Music\Albums\Beautiful South- Carry On Up The Charts\I'll Sail This Ship Alone.mp3
#EXTINF:256,Beautiful South - Let Love Speak Up Itself
D:\Music\Albums\Beautiful South- Carry On Up The Charts\Let Love Speak Up Itself.mp3
#EXTINF:170,Beautiful South - My Book
D:\Music\Albums\Beautiful South- Carry On Up The Charts\My Book.mp3
#EXTINF:212,Beautiful South - Old Red Eyes Is Back
D:\Music\Albums\Beautiful South- Carry On Up The Charts\Old Red Eyes Is Back.mp3
#EXTINF:212,Beautiful South - One Last Love Song
D:\Music\Albums\Beautiful South- Carry On Up The Charts\One Last Love Song.mp3
#EXTINF:225,Beautiful South - Prettiest Eyes
D:\Music\Albums\Beautiful South- Carry On Up The Charts\Prettiest Eyes.mp3
#EXTINF:242,Beautiful South - Song For Whoever
D:\Music\Albums\Beautiful South- Carry On Up The Charts\Song For Whoever.mp3
#EXTINF:214,Beautiful South - We Are Each Other
D:\Music\Albums\Beautiful South- Carry On Up The Charts\We Are Each Other.mp3
#EXTINF:171,Beautiful South - You Keep It All In
D:\Music\Albums\Beautiful South- Carry On Up The Charts\You Keep It All In.mp3
#EXTINF:233,Dido - All You Want
D:\Music\Albums\Dido - No Angel\All You Want.mp3
#EXTINF:272,Dido - Don't Think Of Me
D:\Music\Albums\Dido - No Angel\Don't Think Of Me.mp3
#EXTINF:255,Dido - Here With Me
D:\Music\Albums\Dido - No Angel\Here With Me.mp3
#EXTINF:278,Dido - Honestly OK
D:\Music\Albums\Dido - No Angel\Honestly OK.mp3
#EXTINF:237,Dido - Hunter
D:\Music\Albums\Dido - No Angel\Hunter.mp3
#EXTINF:235,Dido - I'm No Angel
D:\Music\Albums\Dido - No Angel\I'm No Angel.mp3
#EXTINF:234,Dido - Isobel
D:\Music\Albums\Dido - No Angel\Isobel.mp3
#EXTINF:189,Dido - My Life
D:\Music\Albums\Dido - No Angel\My Life.mp3
#EXTINF:267,Dido - My Love's Gone
D:\Music\Albums\Dido - No Angel\My Love's Gone.mp3
#EXTINF:292,Dido - Slide
D:\Music\Albums\Dido - No Angel\Slide.mp3
#EXTINF:402,Dido - Take My Hand
D:\Music\Albums\Dido - No Angel\Take My Hand.mp3
#EXTINF:218,Dido - Thank You
D:\Music\Albums\Dido - No Angel\Thank You.mp3
#EXTINF:239,Elton John - Can You Feel The Love Tonight
D:\Music\Albums\Elton John\Can You Feel The Love Tonight.mp3
#EXTINF:288,Elton John - Circle Of Life
D:\Music\Albums\Elton John\Circle Of Life.mp3
#EXTINF:348,Elton John & George Michael - Don't Let The Sun Go Down On Me
D:\Music\Albums\Elton John\Don't Let The Sun Go Down On Me.mp3
#EXTINF:281,Elton John - I Guess That's Why They Call This The Blues
D:\Music\Albums\Elton John\I Guess That's Why They Call It The Blues.mp3
#EXTINF:308,Elton John - Sacrifice
D:\Music\Albums\Elton John\Sacrifice.mp3
#EXTINF:227,Elton John - Sorry Seems To Be The Hardest Word
D:\Music\Albums\Elton John\Sorry Seems To Be The Hardest Word.mp3
#EXTINF:351,Elton John - The One
D:\Music\Albums\Elton John\The One.mp3
#EXTINF:258,Yesterday Went Too Soon
D:\Music\Albums\Feeder\Yesterday Went Too Soon.mp3
#EXTINF:191,Buck Rogers
D:\Music\Albums\Feeder - Echo Park\Buck Rogers.mp3
#EXTINF:222,Bug
D:\Music\Albums\Feeder - Echo Park\Bug.mp3
#EXTINF:199,Choke
D:\Music\Albums\Feeder - Echo Park\Choke.mp3
#EXTINF:259,Oxygen
D:\Music\Albums\Feeder - Echo Park\Oxygen.mp3
#EXTINF:228,Piece By Piece
D:\Music\Albums\Feeder - Echo Park\Piece By Piece.mp3
#EXTINF:325,Satellite News
D:\Music\Albums\Feeder - Echo Park\Satellite News.mp3
#EXTINF:218,Seven Days In The Sun
D:\Music\Albums\Feeder - Echo Park\Seven Days In The Sun.mp3
#EXTINF:191,Standing On The Edge
D:\Music\Albums\Feeder - Echo Park\Standing On The Edge.mp3
#EXTINF:175,Tell All Your Friends
D:\Music\Albums\Feeder - Echo Park\Tell All Your Friends.mp3
#EXTINF:270,Turn
D:\Music\Albums\Feeder - Echo Park\Turn.mp3
#EXTINF:213,Under The Weather
D:\Music\Albums\Feeder - Echo Park\Under The Weather.mp3
#EXTINF:230,We Can't Rewind
D:\Music\Albums\Feeder - Echo Park\We Can't Rewind.mp3
#EXTINF:114,Feeder - 20th Century Trip
D:\Music\Albums\Feeder - Polythene\20th Century Trip.mp3
#EXTINF:206,Feeder - Cement
D:\Music\Albums\Feeder - Polythene\Cement.mp3
#EXTINF:206,Feeder - Change
D:\Music\Albums\Feeder - Polythene\Change.mp3
#EXTINF:252,Feeder - Crash
D:\Music\Albums\Feeder - Polythene\Crash.mp3
#EXTINF:321,Feeder - Descend
D:\Music\Albums\Feeder - Polythene\Descend.mp3
#EXTINF:284,Feeder - Forgive
D:\Music\Albums\Feeder - Polythene\Forgive.mp3
#EXTINF:264,Feeder - High
D:\Music\Albums\Feeder - Polythene\High.mp3
#EXTINF:263,Feeder - My Perfect Day
D:\Music\Albums\Feeder - Polythene\My Perfect Day.mp3
#EXTINF:207,Feeder - Polythene Girl
D:\Music\Albums\Feeder - Polythene\Polythene Girl.mp3
#EXTINF:274,Feeder - Radiation
D:\Music\Albums\Feeder - Polythene\Radiation.mp3
#EXTINF:206,Feeder - Stereo World
D:\Music\Albums\Feeder - Polythene\Stereo World.mp3
#EXTINF:229,Feeder - Suffocate
D:\Music\Albums\Feeder - Polythene\Suffocate.mp3
#EXTINF:229,Feeder - Tangerine
D:\Music\Albums\Feeder - Polythene\Tangerine.mp3
#EXTINF:254,Ain't It The Life
D:\Music\Albums\Foo Fighters - There Is Nothing Left To Lose\Ain't It The Life.mp3
#EXTINF:348,Aurora
D:\Music\Albums\Foo Fighters - There Is Nothing Left To Lose\Aurora.mp3
#EXTINF:200,Breakout
D:\Music\Albums\Foo Fighters - There Is Nothing Left To Lose\Breakout.mp3
#EXTINF:227,Generator
D:\Music\Albums\Foo Fighters - There Is Nothing Left To Lose\Generator.mp3
#EXTINF:221,Gimme Stitches
D:\Music\Albums\Foo Fighters - There Is Nothing Left To Lose\Gimme Stitches.mp3
#EXTINF:276,Headwires
D:\Music\Albums\Foo Fighters - There Is Nothing Left To Lose\Headwires.mp3
#EXTINF:234,Learn To Fly
D:\Music\Albums\Foo Fighters - There Is Nothing Left To Lose\Learn To Fly.mp3
#EXTINF:232,Live-In Skin
D:\Music\Albums\Foo Fighters - There Is Nothing Left To Lose\Live-In Skin.mp3
#EXTINF:242,MIA!!s
D:\Music\Albums\Foo Fighters - There Is Nothing Left To Lose\MIA!!s.mp3
#EXTINF:275,Next Year
D:\Music\Albums\Foo Fighters - There Is Nothing Left To Lose\Next Year.mp3
#EXTINF:255,Stacked Actors
D:\Music\Albums\Foo Fighters - There Is Nothing Left To Lose\Stacked Actors.mp3
#EXTINF:251,Bliss
D:\Music\Albums\Muse - Origin Of Symmetry\Bliss.mp3
#EXTINF:438,Citizen Erased
D:\Music\Albums\Muse - Origin Of Symmetry\Citizen Erased.mp3
#EXTINF:287,Darkshines
D:\Music\Albums\Muse - Origin Of Symmetry\Darkshines.mp3
#EXTINF:199,Feeling Good
D:\Music\Albums\Muse - Origin Of Symmetry\Feeling Good.mp3
#EXTINF:200,Hyper Music
D:\Music\Albums\Muse - Origin Of Symmetry\Hyper Music.mp3
#EXTINF:277,Megalomania
D:\Music\Albums\Muse - Origin Of Symmetry\Megalomania.mp3
#EXTINF:217,Micro Cuts
D:\Music\Albums\Muse - Origin Of Symmetry\Micro Cuts.mp3
#EXTINF:362,New Born
D:\Music\Albums\Muse - Origin Of Symmetry\New Born.mp3
#EXTINF:219,Muse - Plug In Baby
D:\Music\Albums\Muse - Origin Of Symmetry\Plug In Baby.mp3
#EXTINF:259,Screenager
D:\Music\Albums\Muse - Origin Of Symmetry\Screenager.mp3
#EXTINF:379,Space Dementia
D:\Music\Albums\Muse - Origin Of Symmetry\Space Dementia.mp3
#EXTINF:196,Simon & Garfunkel - Baby Driver
D:\Music\Albums\Simon & Garfunkel - Bridge Over Troubled Water\Baby Driver.mp3
#EXTINF:290,Simon & Garfunkel - Bridge Over Troubled Water
D:\Music\Albums\Simon & Garfunkel - Bridge Over Troubled Water\Bridge Over Troubled Water.mp3
#EXTINF:175,Simon & Garfunkel - Bye Bye Love
D:\Music\Albums\Simon & Garfunkel - Bridge Over Troubled Water\Bye Bye Love.mp3
#EXTINF:174,Simon & Garfunkel - Cecilia
D:\Music\Albums\Simon & Garfunkel - Bridge Over Troubled Water\Cecilia.mp3
#EXTINF:186,Simon & Garfunkel - El Condor Pasa
D:\Music\Albums\Simon & Garfunkel - Bridge Over Troubled Water\El Condor Pasa.mp3
#EXTINF:153,Simon & Garfunkel - Keep The Customer Satisfied
D:\Music\Albums\Simon & Garfunkel - Bridge Over Troubled Water\Keep The Customer Satisfied.mp3
#EXTINF:221,Simon & Garfunkel - So Long, Frank Lloyd Wright
D:\Music\Albums\Simon & Garfunkel - Bridge Over Troubled Water\So Long, Frank Lloyd Wright.mp3
#EXTINF:108,Simon & Garfunkel - Song For The Asking
D:\Music\Albums\Simon & Garfunkel - Bridge Over Troubled Water\Song For The Asking.mp3
#EXTINF:308,Simon & Garfunkel - The Boxer
D:\Music\Albums\Simon & Garfunkel - Bridge Over Troubled Water\The Boxer.mp3
#EXTINF:236,Simon & Garfunkel - The Only Living Boy In New York
D:\Music\Albums\Simon & Garfunkel - Bridge Over Troubled Water\The Only Living Boy In New York.mp3
#EXTINF:164,Simon & Garfunkel - Why Don't You Write Me
D:\Music\Albums\Simon & Garfunkel - Bridge Over Troubled Water\Why Don't You Write Me.mp3
#EXTINF:225,Stereophonics - A Minute Longer
D:\Music\Albums\Stereophonics- Performance And Cocktails\A Minute Longer.mp3
#EXTINF:175,Stereophonics - Half Of The Lies You Tell Ain't True
D:\Music\Albums\Stereophonics- Performance And Cocktails\Half Of The Lies You Tell Ain't True.mp3
#EXTINF:279,Stereophonics - Hurry Up And Wait
D:\Music\Albums\Stereophonics- Performance And Cocktails\Hurry Up And Wait.mp3
#EXTINF:267,Stereophonics - I Stopped To Fill My Car Up
D:\Music\Albums\Stereophonics- Performance And Cocktails\I Stopped To Fill My Car Up.mp3
#EXTINF:229,Stereophonics - I Wouldn't Believe You Radio
D:\Music\Albums\Stereophonics- Performance And Cocktails\I Wouldn't Believe You Radio.mp3
#EXTINF:241,Stereophonics - Is Yesterday, Tomorrow, Today?
D:\Music\Albums\Stereophonics- Performance And Cocktails\Is Yesterday, Tomorrow, Today.mp3
#EXTINF:252,Stereophonics - Just Looking
D:\Music\Albums\Stereophonics- Performance And Cocktails\Just Looking.mp3
#EXTINF:213,Stereophonics - Pick A Part That's New
D:\Music\Albums\Stereophonics- Performance And Cocktails\Pick A Part That's New.mp3
#EXTINF:270,Stereophonics - Plastic California
D:\Music\Albums\Stereophonics- Performance And Cocktails\Plastic California.mp3
#EXTINF:237,Stereophonics - Roll Up And Shine
D:\Music\Albums\Stereophonics- Performance And Cocktails\Roll Up And Shine.mp3
#EXTINF:235,Stereophonics - She Takes Her Clothes Off
D:\Music\Albums\Stereophonics- Performance And Cocktails\She Takes Her Clothes Off.mp3
#EXTINF:244,Stereophonics - T-Shirt Sun Tan
D:\Music\Albums\Stereophonics- Performance And Cocktails\T-Shirt Sun Tan.mp3
#EXTINF:174,Stereophonics - The Bartender And The Thief
D:\Music\Albums\Stereophonics- Performance And Cocktails\The Bartender And The Thief.mp3
#EXTINF:124,The Beatles - Eleanor Rigby
D:\Music\Albums\The Beatles\Eleanor Rigby.mp3
#EXTINF:185,The Beatles - Here Comes the Sun
D:\Music\Albums\The Beatles\Here Comes the Sun.mp3
#EXTINF:426,The Beatles - Hey Jude
D:\Music\Albums\The Beatles\Hey Jude.mp3
#EXTINF:104,The Beatles - I Will
D:\Music\Albums\The Beatles\I Will.mp3
#EXTINF:229,The Beatles - Let It Be
D:\Music\Albums\The Beatles\Let It Be.mp3
#EXTINF:213,The Beatles - She's Leaving Home
D:\Music\Albums\The Beatles\She's Leaving Home.mp3
#EXTINF:216,The Beatles - The Long And Winding Road
D:\Music\Albums\The Beatles\The Long And Winding Road.mp3
#EXTINF:125,The Beatles - Yesterday
D:\Music\Albums\The Beatles\Yesterday.mp3
#EXTINF:181,The Levellers - Belaruse
D:\Music\Albums\The Levellers - One Way Of Life\Belaruse.mp3
#EXTINF:196,The Levellers - Bozos
D:\Music\Albums\The Levellers - One Way Of Life\Bozos.mp3
#EXTINF:284,The Levellers - Carry Me
D:\Music\Albums\The Levellers - One Way Of Life\Carry Me.mp3
#EXTINF:245,The Levellers - Celebrate
D:\Music\Albums\The Levellers - One Way Of Life\Celebrate.mp3
#EXTINF:215,The Levellers - Dog Train
D:\Music\Albums\The Levellers - One Way Of Life\Dog Train.mp3
#EXTINF:196,The Levellers - Fantasy
D:\Music\Albums\The Levellers - One Way Of Life\Fantasy.mp3
#EXTINF:209,The Levellers - Far From Home
D:\Music\Albums\The Levellers - One Way Of Life\Far From Home.mp3
#EXTINF:187,The Levellers - Fifteen Years
D:\Music\Albums\The Levellers - One Way Of Life\Fifteen Years.mp3
#EXTINF:265,The Levellers - Hope Street
D:\Music\Albums\The Levellers - One Way Of Life\Hope Street.mp3
#EXTINF:231,The Levellers - Julie
D:\Music\Albums\The Levellers - One Way Of Life\Julie.mp3
#EXTINF:168,The Levellers - Just The One
D:\Music\Albums\The Levellers - One Way Of Life\Just The One.mp3
#EXTINF:204,The Levellers - One Way
D:\Music\Albums\The Levellers - One Way Of Life\One Way.mp3
#EXTINF:242,The Levellers - Shadow On The Sun
D:\Music\Albums\The Levellers - One Way Of Life\Shadow On The Sun.mp3
#EXTINF:240,The Levellers - This Garden
D:\Music\Albums\The Levellers - One Way Of Life\This Garden.mp3
#EXTINF:331,The Levellers - Too Real (12")
D:\Music\Albums\The Levellers - One Way Of Life\Too Real.mp3
#EXTINF:241,The Levellers - What A Beautiful Day
D:\Music\Albums\The Levellers - One Way Of Life\What A Beautiful Day.mp3

BIN
Wawi_7-5-13.exe Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Some files were not shown because too many files have changed in this diff Show More