/* --- MAIN.CPP --- / / Written by Phil Himsworth, 2001-2002. / /*/ #include #include #include #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; }