Steve8x Posted September 3, 2008 Share Posted September 3, 2008 Version 2.1 is released. It has been improved and standardized! changelog: M'SpaceJuke v2.1 <> 10-29-08 =========================================== *Split the project up into separate files *Now complies with C++ standards *More compatible (ws2_32.dll is different in XP SP1 & SP2) *More accurate download percentage by calculating it *No longer messes up and freezes/crashes when you type an invalid friendid/url *Made project in MSVC++ 2008 instead of Dev-Cpp! *Uses a different font for edit box, combo box, and buttons... *scanbuffer.dll removed, findstr function made in inline assembly instead. *Reduced file size! OK guys I've been working on this all night and now I'm excited to share it with you! and best of all its OPEN SOURCE! Artist disabled downloading? Well Steve8x RE-enabled it ;) Version 2.1 is here and its now better than ever! It no longer injects code into a web browser in order to function. It works entirely on its own! You can even download multiple songs at once! From multiple artists too simultaneously! I did a little playing around with the flash music players which Myspace has. I discovered how to make the mini flash player load any song I want, by encoding the friendID and songID and placing it in the URL of the mini player! Here's an image of me downloading songs with the latest version 2.1 Here's how it works, You type in an artist URL or FRIEND ID. For the artist URL its not the whole thing. Just whats after "http://myspace.com/" Then click the "Get Songs" button to download the user's myspace page code, which will give the app the friendID. friendID's are needed to get list the songs on the profile. So I made it so you can just type the URL as that's easier to remember and it will grab the friendID for you. If you type the URL/FriendID wrong it no longer crashes, instead it will just popup "Invalid Friend ID" messagebox! Select the song you want to download and click "Download". It will then take the friendID of the user, and the songID of the song you selected and encode them with base64, and sprintf the encoded strings into a mini.swf URL which once loaded will start playing the song you selected for download... Once that is done, It creates a new download window and creates a progress bar + some static text AND an internet explorer control within it. The internet explorer control loads the sprintf formatted mini.swf URL and the flash music player loads and your song starts playing in the download window... I have hooked winsock 'send' in my own app! why? so that when the flash player loads the song and plays it, I copy the packet it sends and then I send it myself :) Since the flash player knows how to get the valid token, The packet is valid! The app then starts receiving the mp3, first the header along with a part of the mp3... The header contains "Content-Length: " which lets me know exactly how big the mp3 file is! That way I can show a percentage and a progress bar, and know when to stop receiving packets! The mp3 files are saved into a folder called "downloads" created in the same directory where you ran M'SpaceJuke 2.1 from... Don't worry if your downloading a song that has the same name as a previous song you've downloaded, it will not overwrite your downloads but instead change the file name like so ... "song.mp3", "song_2.mp3", "song_3.mp3", etc... If you want to download multiple songs, I recommend muting(mute not pause) other ones besides one you want to listen to at that time. Or just mute them all. As I don't think anybody likes to listen to multiple songs all at ONCE! That would give me a headache! Share your thoughts and be a tester! Give me some feedback on how good it works for you and ways I can improve it! SOURCE CODE FOR VERSION 2.1:(MSVC++ 2008 Solution) http://popeax.com/download/apps/M'SpaceJuke-2.1-SRC.zip BINARY FOR VERSION 2.1: http://popeax.com/download/apps/M'SpaceJuke-2.1.zip source code for older version 2.0 (left only for comparison of improvement) [Dev-Cpp Project] http://popeax.com/download/apps/M'SpaceJuke2_SRC.zip [M'SpaceJuke.h] #ifndef MYSPACEJUKE_H #define MYSPACEJUKE_H //includes #include "EasySockets.h" #include "EasyControls.h" #include "StrFunctions.h" #include "BitstreamFont.h" #include "base64.h" #include <stdio.h> #include <time.h> //libs to link with #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "comctl32.lib") //typedefs typedef BOOL (CALLBACK* InitAtlAxWin)(void); // for loading SWF's in the download windows InitAtlAxWin InitAtl; //prototypes LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK DownloadWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); void SendHook(); void SendHook2(DWORD sendbuffer, DWORD buffsize); void HookWinsockSend(); void WorkerThread(); void DownloadThread(); void DownloadMP3(); void InstallFont(); int GetFriendID(); int ListSongs(); //variables FILE* f = 0; char* head = 0; char* postdata = 0; char* recvdata = 0; char* artist = 0; char* songs = 0; char* bsid = 0; char* magicalpacket = 0; HWND hwnd, fID, GS, DB, song, dj, sngz; HWND downloadwindows[32] = {0}; HWND swfplayers[32] = {0}; HWND progbars[32] = {0}; HWND txtz[32] = {0}; int hookenabled = 0, downloads = 0; LRESULT selectedsong; LOGFONT BitStream = {0}; HFONT hFont; #endif Here's the main cpp file's source, just so you can get a glimpse of the code here: [M'SpaceJuke.cpp] //M'SpaceJuke v2.1 - downloads songs from MySpace! //even when the download link has been 'disabled' by the artist //© 2008 Steve8x Inc. //Version 2.1 - 10-29-08 //Made project comply with C++ standards //Also fixed a couple small things #include "M'SpaceJuke.h" const char* host = "mediaservices.myspace.com"; const char* header = "GET /services/media/musicplayerxml.ashx?b=%s"; //friendID will be in place of '%s' const char* footer = "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\nAccept: text/html, */*\r\nAccept-Language: en-us,en;q=0.5\r\nAccept-Encoding: identity\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\nConnection: close\r\n\r\n"; char friendid[200] = {0}; char dbg[200] = {0}; DWORD pSendHook = 0, pSendHook2 = 0, pReturnAddress = 0; EasyControls* ctrl = new EasyControls; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmd, int nCmdShow) { MSG Msg; WNDCLASSEX wc; ctrl->hInst = hInstance; wc.cbSize = sizeof(WNDCLASSEX); wc.hInstance = hInstance; wc.lpszClassName = L"M'SpaceJuke2_Class"; wc.lpfnWndProc = WndProc; wc.style = CS_DBLCLKS; wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(101)); wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(101)); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.lpszMenuName = NULL; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = (HBRUSH)GetStockObject(0); RegisterClassEx(&wc); wc.lpszClassName = L"M'SpaceJuke2_Downloader_Class"; wc.lpfnWndProc = DownloadWndProc; RegisterClassEx(&wc); // Initialize common controls library! ctrl->InitCommonCtrls(); // to make sure you can see the controls! //Create the window hwnd = CreateWindowExA(0, "M'SpaceJuke2_Class", "M'SpaceJuke v2.1", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_CLIPSIBLINGS, CW_USEDEFAULT, CW_USEDEFAULT, 288, 175, HWND_DESKTOP, 0, hInstance, 0); ctrl->text(hwnd, "FriendID:", 1, 1, 60, 22, 200); fID = ctrl->edit(hwnd, 1, 0, 0, 65, 1, 135, 22, 400); GS = ctrl->button(hwnd, "Get Songs", 202, 1, 80, 22, 420); ctrl->text(hwnd, "Select Song:", 1, 30, 100, 20, 201); song = ctrl->dropdown(hwnd, 0, 1, 50, 200, 200, 300); DB = ctrl->button(hwnd, "Download", 202, 50, 80, 22, 421); dj = ctrl->text(hwnd, "Artist: NULL", 1, 80, 288, 22, 202); sngz = ctrl->text(hwnd, "Songs: 0", 1, 100, 288, 22, 203); ctrl->text(hwnd, "© 2008 Steve8x", 85, 128, 150, 22, 204); InstallFont(); SendMessage(fID, WM_SETFONT, (WPARAM)hFont, 1); SendMessage(song, WM_SETFONT, (WPARAM)hFont, 1); SendMessage(GS, WM_SETFONT, (WPARAM)hFont, 1); SendMessage(DB, WM_SETFONT, (WPARAM)hFont, 1); //Usage of new!! bsid = new char[200]; artist = new char[200]; songs = new char[10000]; recvdata = new char[100000]; magicalpacket = new char[1000]; //Show our window ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); InitAtl = (InitAtlAxWin)GetProcAddress(LoadLibraryA("atl"), "AtlAxWinInit"); InitAtl(); //Init winsock 2.2 WSADATA wsaData = {0}; WSAStartup(MAKEWORD(2, 2), &wsaData); HookWinsockSend(); //very important part :) while(GetMessage(&Msg, 0, 0, 0)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: if(wParam == 420) //Get Songs button pressed { EnableWindow(fID, 0); EnableWindow(GS, 0); hookenabled = 0; //no point having the hook enabled here, since were only getting the songs CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&WorkerThread, 0, 0, 0); } if(wParam == 421) //Download button pressed { hookenabled = 1; //enable hook so we can capture the necessary packet! CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&DownloadThread, 0, 0, 0); } break; case WM_LBUTTONDOWN: //I do this for all my app's I like dragging the window from anywhere SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, lParam); break; case WM_CTLCOLORSTATIC: SetBkMode((HDC)wParam, TRANSPARENT); return (LRESULT)GetStockObject(WHITE_BRUSH); break; case WM_CLOSE: delete[] ctrl; delete[] bsid; delete[] artist; delete[] songs; delete[] recvdata; delete[] magicalpacket; WSACleanup(); PostQuitMessage(0); break; default: return DefWindowProc (hWnd, message, wParam, lParam); } return 0; } LRESULT CALLBACK DownloadWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_LBUTTONDOWN: SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, lParam); break; case WM_CTLCOLORSTATIC: SetBkMode((HDC)wParam, TRANSPARENT); return (LRESULT)GetStockObject(WHITE_BRUSH); break; case WM_CLOSE: //Closing a download window does not stop the download DestroyWindow(hWnd); break; default: return DefWindowProc (hWnd, message, wParam, lParam); } return 0; } //Now lets get down to the nuts and bolts! :P void _declspec(naked) SendHook() { _asm { push ebp //required mov ebp, esp //required sub esp, 0x10 //required push [ebp+0x10] //push size of send buffer into stack(as param) push [ebp+0x0C] //push pointer to send buffer into stack(as param) call dword ptr [pSendHook2] //call my C++ function jmp dword ptr [pReturnAddress] //jump back to WS2_32 'send' + 6 } } void SendHook2(DWORD sendbuffer, DWORD buffsize) { if(hookenabled == 1) { DWORD pToken = findstr((char*)sendbuffer, buffsize, "token=", 0); if(pToken != -1) { // 'token' was found in buffer so we found the right packet :) ZeroMemory(magicalpacket, 1000); memcpy(magicalpacket, (void*)sendbuffer, buffsize); CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&DownloadMP3, 0, 0, 0); } } } //Hook Winsock In My Own APP. So I Can Intercept The Magical Packet //Which Will Allow Me To Download The MP3 Thats Playing In The Flash Player! void HookWinsockSend() { char* hookaddress = 0; //Set up for winsock 'send' hook DWORD sendaddress = (DWORD)GetProcAddress(GetModuleHandleA("ws2_32.dll"), "send"); if(sendaddress == 0) sendaddress = (DWORD)&send; pSendHook = (DWORD)&SendHook; pSendHook2 = (DWORD)&SendHook2; //XP Service Pack 2 version of ws2_32.dll if(*(WORD*)sendaddress == 0xFF8B) // mov edi, edi (basically a two byte nop) { OutputDebugStringA("[myspacejuke] (XP-SP2) send bytes = {0x8B, 0xFF}"); pReturnAddress = sendaddress + 8; hookaddress = (char*)sendaddress + 2; } //XP Service Pack 1 version of ws2_32.dll else if(*(WORD*)sendaddress == 0x8B55) //push ebp + 1 byte of next instruction { OutputDebugStringA("[myspacejuke] (XP-SP1) send bytes = {0x55, 0x8B}"); pReturnAddress = sendaddress + 6; hookaddress = (char*)sendaddress; } else //Should never happen! but you never know! { char cdate[9] = {0}; char ctime[9] = {0}; _strdate(cdate); _strtime(ctime); f = fopen("errorlog.txt", "wb"); sprintf(dbg, "%s %s\r\n\r\nWinsock Hook Failed!\r\nFirst 20 Bytes Of Send:\r\n", cdate, ctime); fwrite(dbg, strlen(dbg), 1, f); hookaddress = (char*)sendaddress; BYTE temp = 0; for(int i = 0; i < 20; i++) { temp = *(BYTE*)&hookaddress[i]; sprintf(dbg, "\r\n[%i]: 0x%X", i, temp); fwrite(dbg, strlen(dbg), 1, f); } fclose(f); MessageBoxA(0, "Failed to hook winsock \"send\" \nEmail me the \"errorlog.txt\" so I can fix it!\nAlso state which version of windows you have + service packs\n\nSteve8x@live.com", "Winsock Hook Failed!", 0); ExitProcess(0); } //unprotect the right 6 bytes of the beginning of 'send' for the hook DWORD oldprotect = 0; VirtualProtect(hookaddress, 6, PAGE_EXECUTE_READWRITE, &oldprotect); //replace start of winsock 'send' with (JMP DWORD PTR [pointertosendhook]) *(WORD*)hookaddress = 0x25FF; *(DWORD*)&hookaddress[2] = (DWORD)&pSendHook; // winsock 'send' is now hooked :) } void WorkerThread() { xClient* cli = new xClient; head = new char[1000]; postdata = new char[10000]; ZeroMemory(friendid, 200); ZeroMemory(head, 1000); ZeroMemory(postdata, 10000); ZeroMemory(recvdata, 10000); GetWindowTextA(fID, friendid, 200); sprintf(postdata, "GET /%s HTTP/1.1\r\nHost: www.myspace.com\r\n%s", friendid, footer); //connect to server using my class;) cli->ConnectToServer("myspace.com", 80); sendx(cli->serversock, postdata, strlen(postdata)); recvx(cli->serversock, recvdata, 10000); cli->Close(); if(GetFriendID() == 0) { EnableWindow(fID, 1); EnableWindow(GS, 1); MessageBoxA(0, "Invalid Friend ID!", "ERROR!", MB_ICONEXCLAMATION); goto cleanup; } sprintf(head, header, friendid); sprintf(postdata, "%s HTTP/1.1\r\nAccept: */*\r\nConnection: close\r\nHost: %s\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\n\r\n", head, host); ZeroMemory(recvdata, 10000); cli->ConnectToServer((char*)host, 80); sendx(cli->serversock, postdata, strlen(postdata)); recvx(cli->serversock, recvdata, 10000); cli->Close(); int numsongs = ListSongs(); sprintf(dbg, "Songs: %i", numsongs); SetWindowTextA(sngz, dbg); EnableWindow(fID, 1); EnableWindow(GS, 1); cleanup: delete cli; delete[] head; delete[] postdata; ExitThread(0); } int GetFriendID() { char* bandid = recvdata; DWORD pInvalid = findstr(recvdata, strlen(recvdata), "Invalid Friend ID", 0); if(pInvalid != -1) return 0; DWORD pFriendID = findstr(recvdata, strlen(recvdata), "DisplayFriendId\":", 1); if(pFriendID == -1) return 0; bandid = ((char*)pFriendID + 17); int stringsize = GetStrSize(bandid, ',', 0); ZeroMemory(friendid, 200); memcpy(friendid, bandid, stringsize); return 1; } int ListSongs() //scans through XML file in buffer and puts the songs into the listbox { DWORD i = 0; int numsongs = 0; char* title = recvdata; ZeroMemory(artist, 200); ZeroMemory(songs, 10000); SendMessage(song, CB_RESETCONTENT, 0, 0); // clears the list box DWORD pName = findstr(title, strlen(title), "<name>", 0); if(pName == -1) // -1 means string was not found should not happen return 0; title = ((char*)pName + 15); int stringsize = GetStrSize(title, ']', 0); memcpy(artist, title, stringsize); if(strcmp("This artist does not exist", artist) == 0) { return 0; } sprintf(dbg, "Artist: %s", artist); SetWindowTextA(dj, dbg); nextsong: while(cmp(title, "title=\"", 7) == 0) // locate song title { if(cmp(title, "</playlist>", 11) == 1) { //end of songs in xml file reached SendMessage(song, CB_SHOWDROPDOWN, 1, 0); return numsongs; } title++; } title += 7; // get past 'title="' stringsize = GetStrSize(title, 0x22, 0); //copy song name into string array memcpy(&songs[i], title, stringsize); //Add song name to list box SendMessageA(song, CB_ADDSTRING, 0, (LPARAM)&songs[i]); i += (stringsize + 1); //calculate next string offset numsongs++; goto nextsong; } void DownloadThread() { char* swfurl = new char[1000]; char* songurl = recvdata; int stringsize = 0; selectedsong = SendMessage(song, CB_GETCURSEL, 0, 0); int selected = selectedsong + 1; while(selected != 0) // locate bsid/songid of song selected and store it { ZeroMemory(bsid, 200); while(cmp(songurl, "bsid=\"", 6) == 0) { songurl++; } songurl += 6; stringsize = GetStrSize(songurl, 0x22, 0); memcpy(bsid, songurl, stringsize); songurl++; selected--; } //encode songid/bsid, friendid/bandid, and autoplay boolean for URL to be valid std::string song = base64_encode((const unsigned char*)bsid, strlen(bsid)); std::string band = base64_encode((const unsigned char*)friendid, strlen(friendid)); std::string unknown = "MTIyMTA0Njk5NQ=="; std::string AutoPlay = base64_encode((const unsigned char*)"True", 4); //then we can have the mini flash player load any song we want :) ZeroMemory(swfurl, 1000); sprintf(swfurl, "http://lads.myspace.com/mini/mini.swf?b=%s&o=%s&d=%s&i=%s&a=%s&u=%s", song.c_str(), band.c_str(), unknown.c_str(), band.c_str(), AutoPlay.c_str(), band.c_str()); downloadwindows[downloads] = CreateWindowExA(0, "M'SpaceJuke2_Downloader_Class", "Downloading...", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_CLIPSIBLINGS, CW_USEDEFAULT, CW_USEDEFAULT, 303, 150, HWND_DESKTOP, 0, ctrl->hInst, 0); CreateWindowExA(0, "AtlAxWin", swfurl, WS_VISIBLE | WS_CHILD, 1, 1, 300, 55, downloadwindows[downloads], 0, ctrl->hInst, 0); progbars[downloads] = ctrl->progbar(downloadwindows[downloads], 1, 60, 294, 15, 0); txtz[downloads] = ctrl->text(downloadwindows[downloads], "Loading...", 1, 80, 300, 22, 0); ShowWindow(downloadwindows[downloads], 1); UpdateWindow(downloadwindows[downloads]); downloads++; MSG Msg; while(GetMessage(&Msg, 0, 0, 0)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } delete[] swfurl; ExitThread(0); } void DownloadMP3() { xClient* cli = new xClient; char* mp3bytes = new char[1048576]; // allocate 1MB buffer to recv mp3 in... char* songpath = new char[1000]; char* host = new char[100]; char* contentlength = new char[100]; int selected = selectedsong; int d_id = downloads - 1; char* songName = songs; while(selected != 0) { int strsize = strlen(songName) + 1; songName += strsize; selected--; } ZeroMemory(songpath, 1000); CreateDirectoryA("downloads", 0); sprintf(songpath, "downloads\\%s.mp3", songName); //check if file exists first, and if so change the name a little so we dont overwrite the existing song int songNum = 2; checkagain: f = fopen(songpath, "rb"); if(f) { fclose(f); sprintf(songpath, "downloads\\%s_%i.mp3", songName, songNum); songNum++; goto checkagain; } SetWindowTextA(txtz[d_id], songpath); ZeroMemory(host, 100); DWORD pHost = findstr(magicalpacket, strlen(magicalpacket), "Host: ", 1); char* findhost = ((char*)pHost + 6); int strsize = GetStrSize(findhost, 0, 1); memcpy(host, findhost, strsize); //heres where the fun part begins! ZeroMemory(mp3bytes, 1048576); cli->ConnectToServer(host, 80); hookenabled = 0; // disable hook so we don't end up in a indefinite loop :) sendx(cli->serversock, magicalpacket, strlen(magicalpacket)); hookenabled = 1; // we can re-enable after we send the packet! recvx(cli->serversock, mp3bytes, 1000); // recv part of the mp3 + header containing 'Content-Length' which is the size of the mp3 ZeroMemory(contentlength, 100); DWORD pContentLen = findstr(mp3bytes, strlen(mp3bytes), "Content-Length: ", 1); char* contentlen = ((char*)pContentLen + 16); strsize = GetStrSize(contentlen, 0, 1); memcpy(contentlength, contentlen, strsize); unsigned long ContentLen = atoi(contentlength); // convert string to number sprintf(dbg, "Mp3 File Size = %u bytes", ContentLen); OutputDebugStringA(dbg); char* mp3head = mp3bytes; while(*(DWORD*)mp3head != 0x0A0D0A0D) // \r\n\r\n { mp3head++; } mp3head += 4; DWORD mp3headsize = 0; char* endofmp3head = mp3head; while(*(DWORD*)endofmp3head != 0) { mp3headsize++; endofmp3head++; } DWORD byteswritten = 0; HANDLE hMP3 = CreateFileA(songpath, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); WriteFile(hMP3, mp3head, mp3headsize, &byteswritten, 0); unsigned long ContentLenDownloaded = byteswritten; DWORD blocksize = ContentLen / 66; float percentage = ((float)ContentLenDownloaded / (float)ContentLen) * 100.0f; SendMessage(progbars[d_id], PBM_SETPOS, (int)percentage, 0); DWORD bytesleft = 0; //RECIEVING MP3 AND WRITING TO FILE! YAY :) while(ContentLenDownloaded < ContentLen) { bytesleft = ContentLen - ContentLenDownloaded; ZeroMemory(mp3bytes, 1048576); sendx(cli->serversock, "!", 1); //keep-alive (i think) if(bytesleft < blocksize) { recvx(cli->serversock, mp3bytes, bytesleft); WriteFile(hMP3, mp3bytes, bytesleft, &byteswritten, 0); } else { recvx(cli->serversock, mp3bytes, blocksize); WriteFile(hMP3, mp3bytes, blocksize, &byteswritten, 0); } ContentLenDownloaded += byteswritten; percentage = ((float)ContentLenDownloaded / (float)ContentLen) * 100.0f; SendMessage(progbars[d_id], PBM_SETPOS, (int)percentage, 0); sprintf(dbg, "Downloading... [%.2f%% Done!]", percentage); SetWindowTextA(downloadwindows[d_id], dbg); //sprintf(dbg, "downloaded = %u, total = %u, bytesleft = %u", ContentLenDownloaded, ContentLen, bytesleft); //OutputDebugString(dbg); } CloseHandle(hMP3); cli->Close(); SetWindowTextA(downloadwindows[d_id], "Downloading... [100% Done!]"); SendMessage(progbars[d_id], PBM_SETPOS, 100, 0); delete cli; delete[] mp3bytes; delete[] songpath; delete[] host; delete[] contentlength; //keep arrays packed downloadwindows[d_id] = downloadwindows[downloads-1]; progbars[d_id] = progbars[downloads-1]; txtz[d_id] = txtz[downloads-1]; downloads--; ExitThread(0); } void InstallFont() { char WinDir[260] = {0}; char Slash[2] = "\\"; char Fontz[] = "Fonts\\VeraMono.ttf"; GetSystemDirectoryA(WinDir, 260); for(int i = 3; i < sizeof(WinDir); i++) { if(WinDir[i] == Slash[0]) { for(int z = 0; z < sizeof(Fontz); z++) { i++; WinDir[i] = Fontz[z]; } break; } } f = fopen(WinDir, "rb"); if(f) { fclose(f); OutputDebugStringA("Bitstream Font Is Already Installed!"); } else { f = fopen(WinDir, "wb"); fwrite(&BitstreamFont, sizeof(BitstreamFont), 1, f); fclose(f); AddFontResourceA("VeraMono.ttf"); OutputDebugStringA("Bitstream Font Was Installed Successfully!"); } BitStream.lfHeight = 14; BitStream.lfWeight = 420; wcscpy(BitStream.lfFaceName, L"Bitstream Vera Sans Mono"); hFont = CreateFontIndirect(&BitStream); } Quote Link to comment Share on other sites More sharing options...
digip Posted September 3, 2008 Share Posted September 3, 2008 1 -Most bands have multiple songs on a page, not just one. Will it get all of them? Or will it only downlaod the first song? 2-Can you make it take any url instead of prepending myspace.com to it, so any website with an mp3 playing in a flash player can rip it? If this works like you say, timeshifting pandora should be much easier with this as well. Just have to search packets for the word "lame" since they do not store them as .mp3 files. I think they use an XML playlist though, so it may be possible to root them out from it as well, but I haven't used Pandora in about a year now so I forget what they used to have in the packets. I made a screencap tutorial on how to rip from pandora using Wireshark a whiel back, but I think it got deleted from my site when I switched to dream host. I used the same method as the myspace rip except liek I said above, you have to search for lame as the encoding was done with lame encoder, and the do(or did) not store them with .mp3 in the file name. Off topic, I'm not good with assembly and I don't have any Visual C compilers, so I can't make the program myself. Tried microsofts visual c++ but I just couldn't grasp it. Im much better with VB6, as it is what I am used to and been using the longest. I am only now starting to get into C+ and have been using mingw to teach myself C. Assembly is also one I want to learn, as I have Olly Debug, but really don't grasp a lot of it either. I use it generally to see what a program tries to hook into and what strings are in a program so if it were a malware program, I can go through it for web links and passwords. PeID is also good for that. Quote Link to comment Share on other sites More sharing options...
Steve8x Posted September 4, 2008 Author Share Posted September 4, 2008 1 -Most bands have multiple songs on a page, not just one. Will it get all of them? Or will it only download the first song? 2-Can you make it take any url instead of prepending myspace.com to it, so any website with an mp3 playing in a flash player can rip it? 1. DOWNLOAD ALL THE SONGS YOU WANT! 2. This one is made specifically for myspace! but I think I'll make one for pandora too! ;) Quote Link to comment Share on other sites More sharing options...
Steve8x Posted September 13, 2008 Author Share Posted September 13, 2008 BUMP! Version 2.0 is released! :) Quote Link to comment Share on other sites More sharing options...
jollyrancher82 Posted September 13, 2008 Share Posted September 13, 2008 Why are you using malloc() and free() in C++? You should be using new and delete. if(retval == -1 | retval == 0) Found this in EasySockets.h, I don't know if you meant || or you wanted to use |. You should also separate classes into .h and .cpp. Headers are for class definitions, and the .cpp file is for the class implementation. Quote Link to comment Share on other sites More sharing options...
Steve8x Posted September 13, 2008 Author Share Posted September 13, 2008 Why are you using malloc() and free() in C++? You should be using new and delete. if(retval == -1 | retval == 0) Found this in EasySockets.h, I don't know if you meant || or you wanted to use |. You should also separate classes into .h and .cpp. Headers are for class definitions, and the .cpp file is for the class implementation. Whats wrong with malloc as opposed to new? new allocates memory on the heap, and malloc allocates it ? im not sure, but works fine! I also like to use VirtualAlloc as well since it initializes the memory to zero for you. Also you can choose the page protection when allocating... I guess it just depends on which one you like to write? VA: char* mystring = (char*)VirtualAlloc(0, 1000, MEM_COMMIT, PAGE_READWRITE); VirtualFree(mystring, 0, MEM_DECOMMIT); malloc: char* mystring = (char*)malloc(1000); ZeroMemory(mystring, 1000); free(mystring); new: char* mystring = new char[1000]; delete[] mystring; Does new initialize memory to zero? i'm not sure! as for the retval question... well in c++ double pipe || means 'and', and single pipe | means 'or' at least im pretty sure, as thats how ive used them without any problems heres the code snippet from the recvx function if(retval == -1 | retval == 0) break; so its saying if retval equals negative 1 or retval equals 0 then break It was just if(retval == -1) before... but I changed it so it breaks if it equals -1 or 0 since with recv, -1 indicates an error. While 0 indicates that the connection was closed without errors. So that way it doesn't get stuck in the loop if the connection gets closed or has an error... now that I think about it it wouldn't make sense to say retval == -1 AND retval == 0, lol a variable can't be two numbers at the same time! about the header files, I like putting classes into header files, instead of splitting it up into two separate files... To me it seems messy to spread it out like that. And I see no reason to do so since it does in fact work the same in a header file! you can put anything in a .h file that you could in a .cpp, its just a different file extension! But that doesn't mean you can code entirely in .h files lol! I use header files for functions, or classes, or to embed data in my apps. there are many uses for header files, than simply putting function prototypes or definitions... I'm the type of person that doesn't like putting every little code snippet in a separate file! I've run into source codes I was looking over many times where there were what seemed like millions of .cpp and .h files! each with not much code in them, which makes it difficult to browse through since you have to open up a bunch of files and switch between them. Whats wrong with using your scroll bar? When the scroll bar becomes tiny enough that scrolling becomes a pain, then its time to split your code into separate files ;) Quote Link to comment Share on other sites More sharing options...
jollyrancher82 Posted September 13, 2008 Share Posted September 13, 2008 | and & are bitwise or and and respectively. || and && are logical or and and respectively. if(retval == -1 | retval == 0) This code is performing a bitwise or operation. if (retval == -1 || retval == 0) This is the code that should be used. Also the idea behind multiple source files is for organisation. Having source in single files is untidy, and unorganised. If you plan on going into programming as career you should look into managing source files better. Quote Link to comment Share on other sites More sharing options...
CrashandDie Posted September 13, 2008 Share Posted September 13, 2008 In C++, new and delete is used. Do not use malloc() or free() unless you know what you are doing, and if you do, do not mix malloc()/free() with new/delete. The reason behind this, is that simply put, new/delete call the constructors/destructors of an object. malloc()/free() won't. Indeed, you can use new to allocate raw memory, but this is not its main usage. Use one, and stick with it. Want to keep using malloc/free? Go back to C. From what I can see, you're just coding C, so don't advertise it like C++. I don't see classes, I don't see any heritage, I don't see any kind of OO programming. In C++, we don't use char *. char* is a pointer to a char. char* to string literal is deprecated in C++. See ISO 14882:2003 Annex C Subclause _lex.string. Use char const* to point at the first character of a string literal. Use std::string::c_str() to get a char const* to a c string from std::string. For old C functions that accept char* and promise not to alter the string, you may use const_cast. The reason why people actually use a different file for headers and code, is that they're two distinct things. I haven't looked at your code, so I'm just assuming a few things, but this is what you should know: It is "ok" to put member functions of an object in the header if it is a one liner (e.g: int getX() { return x; }). It is not OK to put whole functions in the header file. Yes "it works", but it's wrong. Want an argument about that? Sure: The first reason one could use, is that it's just easier to maintain. Having correctly organised files is a huge time-saver, and allows for anyone new to the project to get a sense of direction fairly quickly. Having a ton of different shit in a few files is the best way to confuse the shit out of everyone. The second point is the whole inline mess. If you declare a function in a header, it must be inline. In any case, then it will appear in every .o that includes the header. Marked inline won't give collisions because it will be put in a special 'link once' section. The implication is thus: longer compile times and link times, more diskspace etc etc... You should only inline functions that are small and need it for run time speed. You may feel these are little cons, but trust me, it's poor practise, and poor coding style. You'll get slammed for it if you do something like that at work or in any kind of official (read collaborative) coding project. I think as a whole, you should probably try to pick up C++ as a language; cuz you're just coding C. None of what I've seen is C++. Oh yeah. You use std::string. At least you don't abuse using namespaces. Quote Link to comment Share on other sites More sharing options...
Steve8x Posted September 14, 2008 Author Share Posted September 14, 2008 EDIT: on a side note, has anyone even tried using the app to download a song? Let me know if you have as that's feedback I'm also looking for, besides code suggestions... well thanks TomB and CrashandDie for your feedback! That's another reason I post my code, so people can tell me what they feel is wrong with it... I'm not set in my ways so I'm open to changing my coding style... I advertise it as C++, because I never started with C... I went str8 to C++. Even thought they are similar, they are different still... Object Oriented Programming? I don't think you've looked at the code enough... Well my Winsock CLASSES are in there in EasySockets.h and in my code I create xClient objects... I can create a client object or a server object and use them... In this app I only need to use the client object... Maybe you missed the parts which contained this line? xClient* cli = new xClient; that creates a new xClient object, and also a pointer to it... then it can be used like so: cli->ConnectToServer("hak5.org", 80); sendx(cli->serversock, buffertosend, sendbuffersize); recvx(cli->serversock, recvbuffer, numberofbytestorecieve); //if done close connection or do more sending and receiving first cli->Close(); //clean up delete cli; I created the xClient + xServer classes as I started using winsock in a lot of my apps, and I disliked repeatedly having the same code everywhere. I mean that's why we create functions right? Make functions which do all the dirty work, then you can just call them. Which in turn makes your code look more neat. So I created a simple class for client and server communication which works very well ;) Well your not always going to be allocating memory for an 'object'. I always use new for creating class objects, but for raw memory, where a buffer will be, or some other kind of data which is just data and does not include functions, Allocating memory is allocating memory. How you do it shouldn't matter, as long as the memory is allocated I don't see a problem with it... That being said as long as your not allocating the memory on the STACK, your fine... As stack memory is limited and shouldn't be used for large buffers... However I will try to start using new, and stop using malloc()! However I still don't see a problem with using VirtualAlloc and I'll continue to use that! as for the char* yes char* is a pointer to a single character, but there isn't a way to make something point to many characters at once... and it wouldn't make sense either... What I mean is, even though its a pointer to 1 character, what comes after it? usually another character, and another and another, until a NULL terminating character is reached. null terminator is binary 0 I guess since I'm so used to assembly I don't think of things in terms of syntax. I think of what needs to be done on machine level. Like okay I need to allocate some memory to store my buffer, while simultaneously creating a pointer to it. Then I can use that pointer to write to it, or read from it, add to the pointer to move up in it, or subtract from it to move backward. Find strings in it if necessary by comparing bytes in the buffer to bytes in the string, etc... Think of it this way... even though in C++ you know a "char*" is a pointer to a char... what does it really come down to on machine level? Your "char*" is simply is a 32bit(DWORD) value which holds the address of the character it points to! So you see what I'm getting at? C++ is very strict with syntax while assembly is not... So type casting must be used frequently, And I'm fine with that. But I like being able to relax with ASM and just deal with DWORDS! :) I guess it just depends on if you like manually handling memory allocation for your strings yourself... I am starting to see the goodness of using std::string though, and I will definitely start using that instead of char* the header files to put classes and functions in, I will (for the most part) stop putting functions and classes in header files, only because of the "inline" issue which you mentioned, that's something I wasn't aware of thanks for letting me know that... Also I won't ever put a ton of shit in a few files... But I also wont put a little code in a million files! I'll find somewhere in the middle and stay there ;) As for picking up C++? Try to remake the project as a straight C project, naming the files .c instead of .cpp I really doubt it will compile without modifications. That's how I know its C++! std::string I'm starting to like it! Quote Link to comment Share on other sites More sharing options...
jollyrancher82 Posted September 15, 2008 Share Posted September 15, 2008 well thanks TomB and CrashandDie for your feedback! That's another reason I post my code, so people can tell me what they feel is wrong with it... I'm not set in my ways so I'm open to changing my coding style.. Feedback helps developers understand different ways of accomplishing the same goals. I advertise it as C++, because I never started with C... I went str8 to C++. Even thought they are similar, they are different still... Object Oriented Programming? I don't think you've looked at the code enough... Well my Winsock CLASSES are in there in EasySockets.h and in my code I create xClient objects... I can create a client object or a server object and use them... In this app I only need to use the client object... Maybe you missed the parts which contained this line? xClient* cli = new xClient; that creates a new xClient object, and also a pointer to it... then it can be used like so: cli->ConnectToServer("hak5.org", 80); sendx(cli->serversock, buffertosend, sendbuffersize); recvx(cli->serversock, recvbuffer, numberofbytestorecieve); //if done close connection or do more sending and receiving first cli->Close(); //clean up delete cli; I created the xClient + xServer classes as I started using winsock in a lot of my apps, and I disliked repeatedly having the same code everywhere. I mean that's why we create functions right? Make functions which do all the dirty work, then you can just call them. Which in turn makes your code look more neat. So I created a simple class for client and server communication which works very well ;) I have a similar solution for winsock, except I use polymorphism, and inheritence. Well your not always going to be allocating memory for an 'object'. I always use new for creating class objects, but for raw memory, where a buffer will be, or some other kind of data which is just data and does not include functions, Allocating memory is allocating memory. How you do it shouldn't matter, as long as the memory is allocated I don't see a problem with it... That being said as long as your not allocating the memory on the STACK, your fine... As stack memory is limited and shouldn't be used for large buffers... However I will try to start using new, and stop using malloc()! However I still don't see a problem with using VirtualAlloc and I'll continue to use that! You should use new/delete in C++ without question. I can't remember off the top of my head but I believe VirtualAlloc uses new or new uses VirtualAlloc, I forget which way around it is. as for the char* yes char* is a pointer to a single character, but there isn't a way to make something point to many characters at once... and it wouldn't make sense either... What I mean is, even though its a pointer to 1 character, what comes after it? usually another character, and another and another, until a NULL terminating character is reached. null terminator is binary 0 I guess since I'm so used to assembly I don't think of things in terms of syntax. I think of what needs to be done on machine level. Like okay I need to allocate some memory to store my buffer, while simultaneously creating a pointer to it. Then I can use that pointer to write to it, or read from it, add to the pointer to move up in it, or subtract from it to move backward. Find strings in it if necessary by comparing bytes in the buffer to bytes in the string, etc... Think of it this way... even though in C++ you know a "char*" is a pointer to a char... what does it really come down to on machine level? Your "char*" is simply is a 32bit(DWORD) value which holds the address of the character it points to! So you see what I'm getting at? C++ is very strict with syntax while assembly is not... So type casting must be used frequently, And I'm fine with that. But I like being able to relax with ASM and just deal with DWORDS! :) I guess it just depends on if you like manually handling memory allocation for your strings yourself... I am starting to see the goodness of using std::string though, and I will definitely start using that instead of char* Mixing assembly with C++ can be a good and bad thing. Different compilers have different inline asm syntax. I like the idea behind the string class however I wrote my own slimline string class for C++. the header files to put classes and functions in, I will (for the most part) stop putting functions and classes in header files, only because of the "inline" issue which you mentioned, that's something I wasn't aware of thanks for letting me know that... Also I won't ever put a ton of shit in a few files... But I also wont put a little code in a million files! I'll find somewhere in the middle and stay there ;) It's never a bad thing to have many files, it's good management and allows you to know where everything is. I work a lot with OOP. So I generally have the class definition in a header, and the implementation in the source file. This never gets messy and I find it easy to manage knowing where everything is. Quote Link to comment Share on other sites More sharing options...
Steve8x Posted September 15, 2008 Author Share Posted September 15, 2008 Mixing assembly with C++ can be a good and bad thing. Different compilers have different inline asm syntax. I like the idea behind the string class however I wrote my own slimline string class for C++. I'll have to disagree, mixing assembly and c++ is a great way to speed up your application. Inline assembly is not the only way to do assembly! But yes they do have different syntax for different compilers, And an example, is that DevCPP inline ASM syntax is a lot different than Microsoft Visual C++ inline ASM syntax! Dev uses at&t syntax by default(it can be switched to intel though), but even when you switch to intel, the syntax is still weird, and using C++ variables in the ASM code is more difficult and I'm not sure how to do it in Dev... So I don't use inline ASM in Dev!! The MSVC++ inline ASM syntax though is really nice, I like it a lot! and sometimes have used that compiler just to be able to use that great syntax! heres an example of MSVC++ intel syntax (it uses intel by default, intel syntax is a lot nicer to use) DWORD addnumbers(DWORD value1, DWORD value2) { _asm { mov eax, [value1] add eax, [value2] ret } } what it does is return the sum of the two numbers added together. And if you don't know it yet, the return value is put in eax, whenever you call a function like so: DWORD sumofnumbers = 0; sumofnumbers = addnumbers(1000, 1000); when the function returns whatever value is in the 32bit eax register, is copied into that variable. "sumofnumbers" for this example... the equivalent to that example in MASM32 is: addnumbers proc value1:DWORD, value2:DWORD mov eax, value1 add eax, value2 ret addnumbers endp both the inline asm and the masm32 version look like this when you look at the address of the function in a disassembler/debugger! almost every function starts out with push ebp mov ebp, esp the next two lines of code are: (these are hex values were dealing with) mov eax, [ebp+08] add eax, [ebp+0C] since values returned are returned in eax, were just going to use the eax register so theres 1 line less of code [ebp+08] is a memory location in stack memory, it contains the value of the first parameter, for "addnumbers" function it is value1, value2 is the second parameter... [ebp+0C] is where on the stack the second parameter is! so it copies the first number into eax, then adds the second one to it! simple enough to understand... now we have the right return value in eax, we can just return, so masm and msvc++ inline assembly just put 'ret' or 'retn' but in the disassembled code you see that "leave" and "ret 0008" what does the "0008" in ret mean? since the two parameters used in the function are only temporary, you have to get rid of them on the stack, so two parameters which are 32bit(DWORD) values, so thats 4 bytes x 2 = 8 bytes ;) ret 8, pops off the two parameters off of the stack, and then it pops the return address, off of the stack and jumps to it... see when you call a function, what your really doing is pushing the parameters into the stack backwards then doing a "call" on the address of the function... when you do a call it takes the EIP (the address of the next instruction to be executed after the "call" line) and pushes it into the stack then jumps to the function you called... thats how the function knows where to come back to after its done, by that return address being pushed into the stack... calling it and storing it in a variable in masm: invoke addnumbers, 10000, 10000 mov sumofnumbers, eax what it actually looks like in memory: as you can see although inline ASM syntax is different from compiler, to compiler. Assembly in general syntax is always the same. Thats what everything comes down to, simple instructions which your processor executes and follows along... and actually you don't even need to use inline assembly at all to use assembly in C++, you can either make a MASM32 dll and call functions in it, or have it create threads , etc... Or you can look at the code in a disassembler and write the bytes into a char array, create a function pointer defined as how the function really is, then you can call it ;) Quote Link to comment Share on other sites More sharing options...
high6 Posted September 15, 2008 Share Posted September 15, 2008 The reason behind this, is that simply put, new/delete call the constructors/destructors of an object. malloc()/free() won't. Indeed, you can use new to allocate raw memory, but this is not its main usage. Use one, and stick with it. Want to keep using malloc/free? Go back to C. From what I can see, you're just coding C, so don't advertise it like C++. I don't see classes, I don't see any heritage, I don't see any kind of OO programming. In C++, we don't use char *. char* is a pointer to a char. char* to string literal is deprecated in C++. See ISO 14882:2003 Annex C Subclause _lex.string. Use char const* to point at the first character of a string literal. Use std::string::c_str() to get a char const* to a c string from std::string. For old C functions that accept char* and promise not to alter the string, you may use const_cast. The reason why people actually use a different file for headers and code, is that they're two distinct things. I haven't looked at your code, so I'm just assuming a few things, but this is what you should know: It is "ok" to put member functions of an object in the header if it is a one liner (e.g: int getX() { return x; }). It is not OK to put whole functions in the header file. Yes "it works", but it's wrong. Want an argument about that? Sure: The first reason one could use, is that it's just easier to maintain. Having correctly organised files is a huge time-saver, and allows for anyone new to the project to get a sense of direction fairly quickly. Having a ton of different shit in a few files is the best way to confuse the shit out of everyone. The second point is the whole inline mess. If you declare a function in a header, it must be inline. In any case, then it will appear in every .o that includes the header. Marked inline won't give collisions because it will be put in a special 'link once' section. The implication is thus: longer compile times and link times, more diskspace etc etc... You should only inline functions that are small and need it for run time speed. You may feel these are little cons, but trust me, it's poor practise, and poor coding style. You'll get slammed for it if you do something like that at work or in any kind of official (read collaborative) coding project. I think as a whole, you should probably try to pick up C++ as a language; cuz you're just coding C. None of what I've seen is C++. Oh yeah. You use std::string. At least you don't abuse using namespaces. Someone is a bit pissy. Quote Link to comment Share on other sites More sharing options...
jollyrancher82 Posted September 15, 2008 Share Posted September 15, 2008 I'll have to disagree, mixing assembly and c++ is a great way to speed up your application. Inline assembly is not the only way to do assembly! *snip* You shouldn't use inline assembly "just because you can" in an application. There are certain situations when it is good, and the rest are bad and offer no benefit. The performance of a desktop application depends on what it's being used for, or the platform it's being run on. If you're writing a C++ application, the likelihood of it needed to be "fast" is slim. If you were writing a performance dependent application you would write the whole application in assembly. Also I already know the different assembly syntax's of inline assembly. I also know how parameters are passed. You don't need to prove to me you know this stuff. I don't care if you do, or don't understand it. I am offering my advice based on what is presented. Quote Link to comment Share on other sites More sharing options...
Steve8x Posted September 15, 2008 Author Share Posted September 15, 2008 well since the show is doing reverse engineering segments now, I thought I'd post that! it wasn't meant specifically for you but anyone who reads this thread ;) It could possibly help someone get interested in doing their "homework" But thanks for the idea, maybe I will do the whole damn thing in assembly! Quote Link to comment Share on other sites More sharing options...
digip Posted September 16, 2008 Share Posted September 16, 2008 I went to Borders yesterday to look for Books on ASM and Debugging and Dissasemblers, and they had nothing. Know of any good books(aside from looking online, I'd rather have some offline material to go over while at work) to get started? Like an ASM Bible or something. How did you get started with ASM? Quote Link to comment Share on other sites More sharing options...
dr0p Posted September 16, 2008 Share Posted September 16, 2008 Easier than using Audacity ^_^ ASM in the source is pretty awesome too. Quote Link to comment Share on other sites More sharing options...
high6 Posted September 16, 2008 Share Posted September 16, 2008 I went to Borders yesterday to look for Books on ASM and Debugging and Dissasemblers, and they had nothing. Know of any good books(aside from looking online, I'd rather have some offline material to go over while at work) to get started? Like an ASM Bible or something. How did you get started with ASM? http://www.tuts4you.com/ Welcome to Tuts 4 You the home of Reverse Code Engineering! This site is dedicated to all the researchers and reverse engineers interested in Reverse Code Engineering (RCE) techniques and practices and all things related. You will be able to find a wide breadth of information retained on this site to help in your research ranging from; anti-debugging, virtual machines, unpacking, coding, disassembling, debugging, keygenning, cryptography and much, much more. On the left is the main control menu which you can use to tour around this site for the areas you wish to view and access. All latest releases are shown on the right under Latest Downloads menu. Before you begin browsing this site you may also want to take a few minutes to read through the FAQ page because a lot of common questions that get asked about this site have already been answered there. Should you have any questions or queries regarding RCE please do not feel afraid to ask on the community forums. A nice site for reversing resources. And a good tutorial series for learning reversing. http://www.tuts4you.com/download.php?list.17 Quote Link to comment Share on other sites More sharing options...
jollyrancher82 Posted September 16, 2008 Share Posted September 16, 2008 http://www.amazon.com/Reversing-Secrets-En...0293&sr=8-1 Quote Link to comment Share on other sites More sharing options...
digip Posted September 16, 2008 Share Posted September 16, 2008 http://www.amazon.com/Reversing-Secrets-En...0293&sr=8-1 Thank you.. Quote Link to comment Share on other sites More sharing options...
CrashandDie Posted September 18, 2008 Share Posted September 18, 2008 Disclaimer: Had to cut the post in two, too many quotes I advertise it as C++, because I never started with C... I went str8 to C++. Even thought they are similar, they are different still... The problem is, it's not real C++. Is it? You can't say you use a certain language, but use everything that defines another language. That's what I'm trying to say when I say "pick one and stick with it". This project doesn't need C++. Regular C would have been more than enough. Object Oriented Programming? I don't think you've looked at the code enough... Well my Winsock CLASSES are in there in EasySockets.h and in my code I create xClient objects... I can create a client object or a server object and use them... In this app I only need to use the client object... Maybe you missed the parts which contained this line? Maybe you haven't read my answer enough. I said I hadn't looked at your code. I said I was making wild assumptions. But one class in a whole project is hardly OOP. Really. I didn't miss anything. xClient* cli = new xClient; that creates a new xClient object, and also a pointer to it... then it can be used like so: cli->ConnectToServer("hak5.org", 80); sendx(cli->serversock, buffertosend, sendbuffersize); recvx(cli->serversock, recvbuffer, numberofbytestorecieve); //if done close connection or do more sending and receiving first cli->Close(); //clean up delete cli; Excepted this isn't Object Oriented Programming. You're just using it as a struct to hold a bit of data. If you honestly believe this is OOP, you're way off. Sorry to have to be the one to break it to you.[1] I created the xClient + xServer classes as I started using winsock in a lot of my apps, and I disliked repeatedly having the same code everywhere. I mean that's why we create functions right? Make functions which do all the dirty work, then you can just call them. Which in turn makes your code look more neat. So I created a simple class for client and server communication which works very well ;) Bla bla bla, you reinvented the wheel, good for you. There's just one problem. You say "I dislike having the same code everywhere". But you still do. You still copy those same sources around to all your projects. You still have the same code in a shitload of places. And no, we don't create functions which do all the dirty work. We create functions, member functions, methods, or whatever you want to call them because some action is redundant. If it happens once, you don't create a function. If it happens twice, you consider it. The third time, you create the function. Code is about structure. Not about hiding stuff. Well your not always going to be allocating memory for an 'object'. I always use new for creating class objects, but for raw memory, where a buffer will be, or some other kind of data which is just data and does not include functions, Allocating memory is allocating memory. How you do it shouldn't matter, as long as the memory is allocated I don't see a problem with it... That being said as long as your not allocating the memory on the STACK, your fine... As stack memory is limited and shouldn't be used for large buffers... I think you're just talking bull right there. I think everything we talk about, you google it up and find something to answer. You don't have to do that. How you allocate memory doesn't matter? Does it fuck! new/delete are what give C++ the concept of objects. Without those the whole language wouldn't exist. And yes, you can implement basic OO features into a C project, but the reason people adopt C++, is that it already has everything. You don't need to reinvent the wheel. The reason C was such an amazing hit, was that before C, most languages did memory management. They had garbage collectors, they'd do everything. But they wouldn't allow you to fiddle with the memory directly. Then C came around, and said "hey, I'll do your memory allocation, but you can still play with my privates if you want to". And that was that. Going against how a given language handles memory allocation is like going against everything it is good for, because in essence, that's what it comes down to. We don't care about the syntax. But the way it plays with our variables? That's still what is bloody important. So like I said, pick one, and stick with it. You took C++ because it sounded nice, and because everyone was talking about it, but you're not using half what it's good for. You'll have to make a decision at some point, you can't keep bastardising both languages. as for the char* yes char* is a pointer to a single character, but there isn't a way to make something point to many characters at once... and it wouldn't make sense either... What I mean is, even though its a pointer to 1 character, what comes after it? usually another character, and another and another, until a NULL terminating character is reached. null terminator is binary 0 Now this was epic. What the fuck are you on about? Nothing comes behind a char*. A char* contains the address to a spot of memory that supposedly contains one single char. It is only by convention that we accept other characters behind that one, and that we keep reading them until we encounter 0-valued char. Stop trying to bullshit your way out of this. We don't give a rat's ass about the "NULL is binary 0". Of course it is. Has this become "name the greatest obviousnesses ?" NULL is hex 0. NULL is octal 0. NULL doesn't exist in Klingon. <snip random BS> So you see what I'm getting at? No. (Continued on the following page) [1]: But don't worry, you're not really an idiot. You were just taught the wrong stuff. Or you didn't bother understanding what you were being taught, but in any case, a lot of developers think they understand OOP, when really, they're just being cocky and are completely oblivious to the whole package. "Sticking feathers up your butt does not make you a chicken". Quote Link to comment Share on other sites More sharing options...
CrashandDie Posted September 18, 2008 Share Posted September 18, 2008 Disclaimer: First part of the post on the previous page, or here C++ is very strict with syntax while assembly is not... So type casting must be used frequently, And I'm fine with that. But I like being able to relax with ASM and just deal with DWORDS! :) I don't see what this has to do with the subject, but ok, I will answer. C++, and C alike, is extremely lax when it comes to syntax. Way more than assembly. You obviously have no idea how many implicit conversions your compiler does for you, without even warning you. And yes, sometimes you have to do an explicit conversion, but in no way is this a very cumbersome task. Standard conversions are used for integral promotions (e.g., enum to int), integral conversions (e.g., int to unsigned int), floating point conversions (e.g., float to double), floating-integral conversions (e.g., int to float), arithmetic conversions (e.g., converting operands to the type of the widest operand before evaluation), pointer conversions (e.g., derived class pointer to base class pointer), reference conversions (e.g., derived class reference to base class reference), and pointer-to-member conversions. And I suppose that you do casts like: foo = (bar *) foobar; In which case I suggest you pick up a copy of the new C++ standard, and read up about the C++ cast operators. Because, yes, again: if you are using the line above, you are using old C-style coding. Not C++. I suggest you read up about static_cast, const_cast, dynamic_cast, and reinterpret_cast. I guess it just depends on if you like manually handling memory allocation for your strings yourself... Manually allocating strings is stupid. It's the best way to get a buffer overflow. It's the best way to start writing over your own variables, or worse yet, write on memory that the running user owns, and you start corrupting the data allocated to other programs. char* is archaic, and should not be used in C++. I am starting to see the goodness of using std::string though, and I will definitely start using that instead of char* You don't have to, but if you don't, don't use C++. the header files to put classes and functions in, I will (for the most part) stop putting functions and classes in header files, only because of the "inline" issue which you mentioned, that's something I wasn't aware of thanks for letting me know that... Also I won't ever put a ton of shit in a few files... But I also wont put a little code in a million files! I'll find somewhere in the middle and stay there ;) Small example: Nokia-N810-23-14:~# ls /root/liqbase_www_jpeg/ APP_VER_BUILD liqbook.c liqgraffiti.c mk_micro.c APP_VER_MAJOR liqbook.h liqgraffiti.o mk_style.c APP_VER_MINOR liqbook.o liqgraffiti_details.c mk_style.o COPYING liqbookprogress.c liqimage.c mkfileselect.c Maemo.org.jpg liqbookprogress.o liqimage.h mkfileselect.o Makefile liqbrain liqimage.o mkproject.c NCI_bacon_alpha_small.png liqbrain.c liqkeyboard.c mkproject.o NCI_bacon_small.png liqcamera.c liqkeyboard.o mkrun.sh NCI_bacon_tiny.png liqcamera.h liqmenu.c mkrun.sh_inner.sh berlin-map-metro-big.png liqcamera.o liqmenu.o mksketch.c cancel.png liqcanvas.c liqreader.c mksketch.o car.jpg liqcanvas.h liqreader.o n810.jpg catshower.jpg liqcanvas.o liqreader_readme.txt ok.png data liqcanvas_xv.c liqscroll.c plane.png debian liqcanvas_xv.o liqscroll.o pybook description liqcliprect.c liqspeedtest.c q.c dictnode.c liqcliprect.h liqspeedtest.o q.h dictnode.h liqcliprect.o liqstars.c q.o errs.txt liqdialog.c liqstars.h qcard.c filebuf.c liqdialog.h liqstars.o qcard.h filebuf.h liqdialog.o liqtextbuffer.c qcard.o filebuf.o liqdoc.c liqtextbuffer.h qcell.c kcup.sh liqdoc.h liqtextbuffer.o qcell.h killbadapps.sh liqdoc.o liqtile.c qcell.o liq_xsurface.c liqdraw.c liqtile.h qfontlibrary.c liq_xsurface.h liqdraw.h liqtile.o qfontlibrary.h liq_xsurface.o liqdraw.o liqtile_easyrun.c qfontlibrary.o liq_xsurface_stable.c liqdrawframe.c liqtile_easyrun.o qstyle.c liqapp.c liqdrawframe.h liqui2.c qstyle.h liqapp.h liqdrawframe.o liqui2.o qstyle.o liqapp.o liqed.c liquidesign.c qstylelibrary.c liqart.c liqed.o liquidesign.o qstylelibrary.h liqart.o liqed_rotate.c liqwww.c qstylelibrary.o liqart2.c liqfloat.c liqwww.o qtile.c liqart2.o liqfloat.o liqx.c qtile.h liqbase liqfloatgallery.c lucon.ttf qtile.o liqbase-example.txt liqfloatgallery.o makefile-orig qtilemedia.c liqbase.c liqfloatpic.c marble_800_480.jpg qtilemedia.h liqbase.o liqfloatpic.o marble_dark_200_120.jpg rounded.png liqbase_bookhistory.dat liqfont.c marble_dark_400_240.jpg sun.png liqbase_readme.txt liqfont.h marble_dark_800_480.jpg yuv.png liqbase_run.sh liqfont.o mk_core.c liqbirds.c liqgame.c mk_core.h liqbirds.o liqgame.o mk_core.o Nokia-N810-23-14:~# Do you honestly believe this would be manageable if it wasn't very strictly categorised? And this is a tiny project. As for picking up C++? Try to remake the project as a straight C project, naming the files .c instead of .cpp I really doubt it will compile without modifications. That's how I know its C++! I don't need to prove to myself that it's not C++. I know that much. It might be something that you like to call C++, but it definitely isn't C++. In C++, like TomB said, you'd have inheritance, polymorphism, abstraction, and data encapsulation. You don't provide a whole lot of those. Don't mentally masturbate yourself into thinking you're writing awesome C++ code. It's just bastardised rubbish code. std::string I'm starting to like it! It's an awesome class and is really an excellent way to go, it does solve a huge number of problems that C should never have brought upon us in the first place. Quote Link to comment Share on other sites More sharing options...
Steve8x Posted September 19, 2008 Author Share Posted September 19, 2008 OK Well maybe I'm missing something? Since it is a small project, if you wouldn't mind spending a little time. Would you mind re-doing the project in what you call "REAL C++"? because frankly now I'm not really sure what I should change to make it so... After All I'm just in it to learn, and if you showed me how to do it properly I'd be very grateful. Then you wouldn't have to tell me I'm doing it wrong anymore would you? Since I'd be doing it right. :) I just want to do it the right way! you know? For me its just not so clear which way is the right way... as for one thing i'm confused about in using std::string... how would I read from a file, or recv a winsock buffer into a std::string? The required memory gets allocated automatically when using std::string correct? Also I'm having some problems separating the class into a .h and a .cpp file... when I do it, and include nothing in the main cpp file, its as if I can't use the class? If I include the header, I get errors, same with including the .cpp? So I'm at a loss at how to do that properly as well... I suppose that's why I've been putting functions and classes in header files... anyway thanks for your time, and your posts.. Quote Link to comment Share on other sites More sharing options...
jollyrancher82 Posted September 19, 2008 Share Posted September 19, 2008 Your heads should start/end like the following: #ifndef __BLAH_HEADER__ #define __BLAH_HEADER__ // code here..... #endif This is what's called an include guard and makes sure you don't include the header more than once in the actual code when you #include "blah.h" in more than one file of your code. Quote Link to comment Share on other sites More sharing options...
Steve8x Posted October 30, 2008 Author Share Posted October 30, 2008 Version 2.1 is now released... I divided the project up into separate files and used include guards in my headers! ;) It should now go along with C++ standards... And I must say I like it better this way :) Also it just might work on Vista now that I've improved the code as well... @CrashAndDie: Yes I was aware I was using old fashioned C-Style casts. I find this easier to write foo = (bar*)foobar; than foo = reinterpret_cast<bar*>foobar; I will use the newer casts though. But newer C++ casts basically do the same thing a C casts?, just if problems arise in your app, if you used the C++ casts, those problems would be easier to find. Check out my new project organization: [root@127.0.0.1] $ ls BitstreamFont.h M'SpaceJuke.h VeraMono.ttf EasyControls.cpp M'SpaceJuke.vcproj base64.cpp EasyControls.h M'SpaceJuke.vcproj base64.h EasySockets.cpp Release mspace.ico EasySockets.h StrFunctions.cpp resource.h M'SpaceJuke.cpp StrFunctions.h rsrc.rc [Thu Oct 30 - 01:08:48] ~/My Documents/Visual Studio 2008/Projects/M'SpaceJuke/M'SpaceJuke I am still using char* however... but only because I can't seem to figure out, or find anywhere on the web that says how to read a file into a std::string, or recieve a buffer from winsock in a std::string for example, if I'm reading a file normally I do it like so: DWORD fileSize = 0; char* filebuffer = new char[1000]; FILE* f = fopen("somefile.txt", "rb"); fileSize = GetFileSize(f); fread(filebuffer, fileSize, 1, f); now say I didn't want to use char* and wanted to use std::string instead? I could create an std::string from the char* but that would defy the point. I would still be using char* to read the file!! And it would be wasteful having two things of the same in memory at once... (although you could free the memory for the char* but still) So is it even possible to read from a file into a std::string? Quote Link to comment Share on other sites More sharing options...
sumo2003 Posted October 30, 2008 Share Posted October 30, 2008 well here is a very stupid question to ask, do you have to be logged into your myspace account to even have this proggy to work. <_< Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.