#include #include #include "resource.h" #include "main.h" extern char szAppName[]; extern char username[20], password[20], title[255]; extern char host[255]; extern int port; extern bool use_auth; extern HWND hwnd; // Base64 character array // 0 1 2 3 4 5 6 // 01234567890123456789012345678901234567890123456789012345678901234 const char bchars[] = "=BCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+*"; // -------------------------------------------------------------------------------- // Start winsock bool StartWinSock() { WORD wVersionRequested = MAKEWORD(2,2); WSADATA wsaData; if (WSAStartup(wVersionRequested, &wsaData ) != 0 ) { MessageBox(NULL, "ERROR: Winsock not available", szAppName, MB_OK); return false; } return true; } // -------------------------------------------------------------------------------- // Low level socket writing function - strings void prints(SOCKET socket, char * string) { int i=0; while (string[i] != 0) i++; if (send(socket,string,i,0) == SOCKET_ERROR) { //MessageBox(NULL,"Socket send() error!",szAppName,MB_OK); } } // Low level socket writing function - integers void printsi(SOCKET socket,int number) { char buffer[256]; wsprintf(buffer,"%d",number); // Stick it in a string and call prints() prints(socket,(char*)&buffer); } // -------------------------------------------------------------------------------- // Opens socket bool MakeRequest(char * host, int port, char * url, bool verbose, bool auth, bool gettitle) { //MessageBox(NULL,"Entering MakeRequest","wawitray",MB_OK | MB_TOPMOST); SOCKET ssocket = socket(AF_INET,SOCK_STREAM,0); if (ssocket == INVALID_SOCKET) { if (verbose) MessageBox(NULL, "ERROR: Couldn't create socket", szAppName, MB_OK); return false; } struct sockaddr_in server_address; ZeroMemory(&server_address,sizeof(server_address)); server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = inet_addr(host); server_address.sin_port = htons(port); if (SOCKET_ERROR == connect(ssocket,(sockaddr*)&server_address,sizeof(sockaddr_in))) { if (verbose) MessageBox(hwnd,"Couldn't connect to remote Winamp!\n\nCheck you have the address and port right.",szAppName,MB_OK|MB_ICONERROR); return false; } char method[6]; if (gettitle) wsprintf(method,"GET"); else wsprintf(method,"HEAD"); char request[100]; if (auth) { char b64userpass[100], userpass[100]; wsprintf(userpass,"%s:%s",username,password); ToBase64(userpass,b64userpass); wsprintf(request,"%s %s HTTP/1.0\nAuthorisation: Basic %s\n\n",method,url,b64userpass); } else { wsprintf(request,"%s %s HTTP/1.0\nConnection: Close\n\n",method,url); } prints(ssocket,request); int res = GetResponse(ssocket,gettitle); closesocket(ssocket); switch(res) { case RES_OK: break; case RES_AUTH: if (verbose) MessageBox(hwnd,"Incorrect username or password!\n\nCheck the details are right in the Config window.",szAppName,MB_OK|MB_ICONERROR | MB_TOPMOST); break; case RES_NOTFOUND: if (verbose) MessageBox(hwnd,"Received a 404 Page Not Found response, which the Winamp HTTP Server does not produce!\n\nAre you sure your host and port settings are correct?",szAppName,MB_OK | MB_ICONERROR | MB_TOPMOST); break; case RES_BADREQUEST: if (verbose) MessageBox(hwnd,"Received a 400 Bad Request message, which the Winamp HTTP Server does not produce!\n\nCheck your Host and Port settings are correct.",szAppName, MB_OK | MB_ICONERROR | MB_TOPMOST); case RES_UNKNOWN: case RES_FAIL: if (verbose) MessageBox(hwnd,"Unknown HTTP Response",szAppName,MB_OK | MB_ICONWARNING | MB_TOPMOST); break; } //MessageBox(hwnd,"Leaving MakeRequest","wawitray",MB_OK | MB_TOPMOST); return true; } int WASend(char * command) { MakeRequest(host,port,command,true,use_auth,false); return 1; } // -------------------------------------------------------------------------------- // 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; } // -------------------------------------------------------------------------------- // Receives return HTTP header int GetResponse(SOCKET socket, bool gettitle) { char buffer[2048],http_version[20],response[5],text[100]; int buffer_len; int buffer_filled = 0; int buffer_left; bool complete = false; int breaks; if (gettitle) breaks = 1; else breaks = 0; 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(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')) { if (breaks == 0) { buffer[i+1] = 0; //MessageBox(NULL,buffer,"gen_httpsrv debug", MB_OK); char * chptr = (char*)&buffer; chptr = GetAString(chptr,http_version); chptr = GetAString(chptr,response); chptr = GetAString(chptr,text); chptr = SkipHeader(chptr); if (StrComp(response,"200")) { if (gettitle) GetALine(chptr,title); return RES_OK; } if (StrComp(response,"401")) return RES_AUTH; if (StrComp(response,"404")) return RES_NOTFOUND; if (StrComp(response,"400")) return RES_BADREQUEST; return RES_UNKNOWN; } else breaks--; } } else { return RES_FAIL; } } } // -------------------------------------------------------------------------------- // 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 } // -------------------------------------------------------------------------------- // Skips the rest of the HTTP header char * SkipHeader(char * chptr) { while (chptr[0] != '\n' || (chptr[1] != '\n' && chptr[2] != '\r')) chptr++; return chptr; } // -------------------------------------------------------------------------------- // Gets a whole line char * GetALine(char * chptr, char * text) { 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] != '\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 } // -------------------------------------------------------------------------------- // Strcmp() without using Clib bool StrComp(char * string1, char * string2) { int ptr=0; while (ToLowerCase(string1[ptr]) == ToLowerCase(string2[ptr])) // while the strings are the same, keep going { if (string1[ptr] == 0) // if they're the same and 0, they're identical null terminated strings return true; ptr++; } return false; // if not the same, they're... not the same } // -------------------------------------------------------------------------------- // Convert a char to lower case char ToLowerCase(char c) { if (c >= 'A' && c <= 'Z') c += 32; return c; }