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

