/* --- CLIENTCONNECTION.CPP --- / / Written by Phil Himsworth, 2001-2002. / /*/ #include #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,"\n\nWinamp Web Interface\n\n"); prints(&conn,"\n

Winamp Web Interface

\n\n\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,"\n\n\n\n"); prints(&conn,"<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 }