fiveworlds Posted January 19, 2017 Posted January 19, 2017 Currently trying to learn some C in my spare time. I wanted to try creating a https server with winsock. I am not sure if it is possible in pure C I found a tutorial on how to create a telnet server in C http://www.binarytides.com/winsock-socket-programming-tutorial/ which was helpful but doesn't work over http or https
Unity+ Posted January 19, 2017 Posted January 19, 2017 Currently trying to learn some C in my spare time. I wanted to try creating a https server with winsock. I am not sure if it is possible in pure C I found a tutorial on how to create a telnet server in C http://www.binarytides.com/winsock-socket-programming-tutorial/ which was helpful but doesn't work over http or https It essentially is possible. For it to work, you would run the server on port 80 and, for testing purposes, would send the "client"(in this case, the browser) whatever you want to send it. In this case, you could open an html file in C and send that info to the client, where the browser will display it. /* Live Server on port 8888 */ #include<io.h> #include<stdio.h> #include<winsock2.h> #pragma comment(lib,"ws2_32.lib") //Winsock Library int main(int argc , char *argv[]) { WSADATA wsa; SOCKET s , new_socket; struct sockaddr_in server , client; int c; char *message; printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) { printf("Failed. Error Code : %d",WSAGetLastError()); return 1; } printf("Initialised.\n"); //Create a socket if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET) { printf("Could not create socket : %d" , WSAGetLastError()); } printf("Socket created.\n"); //Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons( 80 ); //Bind if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR) { printf("Bind failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } puts("Bind done"); //Listen to incoming connections listen(s , 3); //Accept and incoming connection puts("Waiting for incoming connections..."); c = sizeof(struct sockaddr_in); while( (new_socket = accept(s , (struct sockaddr *)&client, &c)) != INVALID_SOCKET ) { puts("Connection accepted"); //Reply to the client message = "Hello Client , I have received your connection. But I have to go now, bye\n"; send(new_socket , message , strlen(message) , 0); } if (new_socket == INVALID_SOCKET) { printf("accept failed with error code : %d" , WSAGetLastError()); return 1; } closesocket(s); WSACleanup(); return 0; } However, you also can specify the port in the url and keep the same port used in the example. 1
fiveworlds Posted January 19, 2017 Author Posted January 19, 2017 (edited) Yeah I tried that too but it doesn't work 100% properly. The page only occasionally loads anything. //Reply to the client message = "<!DOCTYPE html><html lang='en'><head><link rel='stylesheet' href='css/test.css'/><title>test</title><meta charset='utf-8' /></head><body><div role='navigation' id='mySidenav' class='sidenav'><div id='split-bar'></div><nav id='navbar'><a>Home</a><a>Login</a><a>Register</a><a>Contact</a><a>Forgotten Password</a></nav></div></body></html>"; send(new_socket, message, strlen(message), 0); What I am sometimes getting back when I try to load the page in the browser. <html lang="en"><head><link href="css/test.css" rel="stylesheet"></head></html> So something is wrong somewhere. Maybe the formatting needs to be a certain way?? If it was totally wrong nothing at all would load. Hmm it appears to load in chrome but it is also continuously loading so maybe I need to close the connection to the client once the data is sent???? Edit: The following seems to work ok in microsoft edge. But it isn't working in any other browser. // socketprogramming4.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include<io.h> #include<stdio.h> #include<winsock2.h> #pragma comment(lib,"ws2_32.lib") //Winsock Library int main(int argc, char *argv[]) { WSADATA wsa; SOCKET s, new_socket; struct sockaddr_in server, client; int c; char *message; printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("Failed. Error Code : %d", WSAGetLastError()); return 1; } printf("Initialised.\n"); //Create a socket if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { printf("Could not create socket : %d", WSAGetLastError()); } printf("Socket created.\n"); //Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(80); //Bind if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) { printf("Bind failed with error code : %d", WSAGetLastError()); exit(EXIT_FAILURE); } puts("Bind done"); //Listen to incoming connections listen(s, 3); //Accept and incoming connection puts("Waiting for incoming connections..."); c = sizeof(struct sockaddr_in); while ((new_socket = accept(s, (struct sockaddr *)&client, &c)) != INVALID_SOCKET) { puts("Connection accepted"); //Reply to the client message = "<!DOCTYPE html><html lang='en'><head><link rel='stylesheet' href='css/test.css'/><title>test</title><meta charset='utf-8' /></head><body><div role='navigation' id='mySidenav' class='sidenav'><div id='split-bar'></div><nav id='navbar'><a>Home</a><a>Login</a><a>Register</a><a>Contact</a><a>Forgotten Password</a></nav></div></body></html>"; send(new_socket, message, strlen(message), 0); closesocket(new_socket); } if (new_socket == INVALID_SOCKET) { printf("accept failed with error code : %d", WSAGetLastError()); return 1; } closesocket(s); WSACleanup(); return 0; } I think the socket may be closing too quickly for the other browsers maybe there is a way to make it wait until all the data has been sent before closing?? Edit: Okay so I found the function I needed which is shutdown(socket,1); which stops sending data but allows data to be received from the client. // socketprogramming4.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include<io.h> #include<stdio.h> #include<stdlib.h> #include <dos.h> #include<winsock2.h> #pragma comment(lib,"ws2_32.lib") //Winsock Library bool send_all(int socket, void *buffer, size_t length) { char *ptr = (char*)buffer; while (length > 0) { int i = send(socket, ptr, length, 0); if (i < 1) return false; ptr += i; length -= i; } shutdown(socket, 1); return true; } int main(int argc, char *argv[]) { WSADATA wsa; SOCKET s, new_socket; struct sockaddr_in server, client; int c; char *message, server_reply[2000]; int recv_size; printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("Failed. Error Code : %d", WSAGetLastError()); return 1; } printf("Initialised.\n"); //Create a socket if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { printf("Could not create socket : %d", WSAGetLastError()); } printf("Socket created.\n"); //Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(80); //Bind if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) { printf("Bind failed with error code : %d", WSAGetLastError()); exit(EXIT_FAILURE); } puts("Bind done"); //Listen to incoming connections listen(s, 3); //Accept and incoming connection puts("Waiting for incoming connections..."); c = sizeof(struct sockaddr_in); while ((new_socket = accept(s, (struct sockaddr *)&client, &c)) != INVALID_SOCKET) { puts("Connection accepted"); //Reply to the client message = "<!DOCTYPE html><html lang='en'><head><title>test</title><meta charset='utf-8' /></head><body><div role='navigation' id='mySidenav' class='sidenav'><div id='split-bar'></div><nav id='navbar'><a>Home</a><a>Login</a><a>Register</a><a>Contact</a><a>Forgotten Password</a></nav></div></body></html>"; send_all(new_socket, message, strlen(message)); } if (new_socket == INVALID_SOCKET) { printf("accept failed with error code : %d", WSAGetLastError()); return 1; } closesocket(s); WSACleanup(); return 0; } Hmm now how do I get the request url so I can implement a filesystem? Edited January 19, 2017 by fiveworlds
Unity+ Posted January 20, 2017 Posted January 20, 2017 Hmm now how do I get the request url so I can implement a filesystem? Can you specify what you mean by this?
fiveworlds Posted January 20, 2017 Author Posted January 20, 2017 Like reading the Get requests turns out I had to use recv. Have a look. #include "stdafx.h" #include <io.h> #include <stdio.h> #include <stdlib.h> #include <dos.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") //Winsock Library bool send_all(int socket, void *buffer, size_t length) { char *ptr = (char*)buffer; while (length > 0) { int i = send(socket, ptr, length, 0); if (i < 1) return false; ptr += i; length -= i; } shutdown(socket, 1); return true; } int strpos(char *haystack, char *needle) { char *p = strstr(haystack, needle); if (p) return p - haystack; return -1; } int main(int argc, char *argv[]) { WSADATA wsa; SOCKET s, new_socket; struct sockaddr_in server, client; int c; char *message, server_reply[2000]; int recv_size; printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("Failed. Error Code : %d", WSAGetLastError()); return 1; } printf("Initialised.\n"); //Create a socket if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { printf("Could not create socket : %d", WSAGetLastError()); } printf("Socket created.\n"); //Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(80); //Bind if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) { printf("Bind failed with error code : %d", WSAGetLastError()); exit(EXIT_FAILURE); } puts("Bind done"); //Listen to incoming connections listen(s, 3); //Accept and incoming connection puts("Waiting for incoming connections..."); c = sizeof(struct sockaddr_in); while ((new_socket = accept(s, (struct sockaddr *)&client, &c)) != INVALID_SOCKET) { if ((recv_size = recv(new_socket, server_reply, 2000, 0)) == SOCKET_ERROR) { puts("recv failed"); } else { puts(server_reply); } //Receive a reply from the server if (strstr(server_reply, "GET / HTTP/1.1") != NULL) { message = "<!DOCTYPE html><html><head><link type='text/css' rel='stylesheet' href='index.css' /></head><body><a href='test'>Testing</a></body></html>"; send_all(new_socket, message, strlen(message)); } else if (strstr(server_reply, "index.css") != NULL) { message = "Content-Type: Text/Css"; send_all(new_socket, message, strlen(message)); message = "body{background:blue;}"; send_all(new_socket, message, strlen(message)); } else if (strstr(server_reply, "favicon.ico") != NULL) { message = " "; send_all(new_socket, message, strlen(message)); } else { message = ""; send_all(new_socket, message, strlen(message)); } } if (new_socket == INVALID_SOCKET) { printf("accept failed with error code : %d", WSAGetLastError()); return 1; } closesocket(s); WSACleanup(); return 0; } For the moment I am just using search strings. There is an error with mime types which cause errors to be thrown in the browser when I try to load an image or an external css stylesheet. I'm not sure how to set the headers properly.
Sensei Posted January 20, 2017 Posted January 20, 2017 (edited) message = "Content-Type: Text/Css"; send_all(new_socket, message, strlen(message)); message = "body{background:blue;}"; send_all(new_socket, message, strlen(message)); 1st send_all() disabled sending (shutdown()) then how can you send 2nd time again after that? shutdown() should looks like: shutdown( socket, SD_SEND); You didn't closesocket( new_socket ); You don't have proper HTTP-Response message.. https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html Nor HTTP-Headers https://en.wikipedia.org/wiki/List_of_HTTP_header_fields https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html They MUST have CRLF each line.... And being separated by empty CRLF from the main reply body.. It would be good for you to take some personal firewall with built-in sniffer (f.e. Sygate Personal Firewall), or stand-alone TCP/IP packet sniffer, and try to connect from web browser to local installed Apache, and look in TCP/IP packet viewer what is sent and what is received from proper HTTP server.. Look at MSDN how nicely WinSock functions are described f.e. https://msdn.microsoft.com/en-us/library/windows/desktop/ms740149(v=vs.85).aspx On the bottom there are examples of how to use these functions, including error handling, which you ignored.. Edited January 20, 2017 by Sensei 1
fiveworlds Posted January 20, 2017 Author Posted January 20, 2017 (edited) shutdown() should looks like:shutdown( socket, SD_SEND); shutdown(socket,1) does the same thing. They MUST have CRLF each line.... And being separated by empty CRLF from the main reply body.. So I just need to add CRLF?? I dunno maybe there is a function on MSDN to generate it. The received header data doesn't have CRLF. GET / HTTP/1.1 Accept: text/html, application/xhtml+xml, image/jxr, */* Accept-Language: en-IE User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393 Accept-Encoding: gzip, deflate Host: localhost Connection: Keep-Alive ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ GET /index.css HTTP/1.1 Accept: text/css, */* Referer: http://localhost/ Accept-Language: en-IE User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393 Accept-Encoding: gzip, deflate Host: localhost Connection: Keep-Alive ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠8|ø look in TCP/IP packet viewer what is sent and what is received from proper HTTP server.. I wireshark or something like that?? Yeah I could give it a whirl. Generally the packets are formatted though it generally isn't a raw response. Maybe fiddler would work?? On the bottom there are examples of how to use these functions, including error handling, which you ignored.. No I didn't I read them and https://msdn.microsoft.com/en-us/library/windows/desktop/ms740673(v=vs.85).aspx trying to figure stuff out and it isn't exactly the same as what I want anyway since it's C++ Edited January 20, 2017 by fiveworlds
Sensei Posted January 20, 2017 Posted January 20, 2017 (edited) shutdown(socket,1) does the same thing. Do you want to learn programming correctly, or not? Any IT employer would tell you the same: Don't use hard-coded integers, when they are defined as macros/enums. And when they are not (your own code), make them, with meaningful names. So I just need to add CRLF?? I dunno maybe there is a function on MSDN to generate it. The received header data doesn't have CRLF. CRLF = Carrier Return, Line Feed, https://en.wikipedia.org/wiki/Carriage_return They are two characters to add to strings returned to client by server. Basically you do it by printf( "Text....\r\n" ); \r is CR \n is LF \r\n is CRLF Example HTTP response from HTTP server such as Apache: After each line there is CRLF f.e. code in C/C++: send(s,"HTTP/1.1 200 OK\r\n" ); send(s,"Content-Type: text/html\r\n" ); send(s,"\r\n" ); // empty CRLF send(s,html_body_string ); No I didn't I read them and https://msdn.microsoft.com/en-us/library/windows/desktop/ms740673(v=vs.85).aspx trying to figure stuff out and it isn't exactly the same as what I want anyway since it's C++ In MSDN examples, C and C++ are pretty much the same, as they are not using C++ classes nor any C++ specific features. They could simply call it "Example in C/C++" or "Ëxample in C". Edited January 20, 2017 by Sensei 2
fiveworlds Posted January 20, 2017 Author Posted January 20, 2017 Okay so message = "HTTP/1.1 200 OK\r\nServer: test\r\nDate : Thu, 13 Jul 2000 05 : 46 : 53 GMT\r\nContent-Type: text/css\r\n\r\nbody{ background:blue; }"; send_all(new_socket, message, strlen(message)); Seems to be working.
Sensei Posted January 20, 2017 Posted January 20, 2017 It should be: "Date: Thu, 13 Jul 2000 05:46:53 GMT\r\n" No space between Date and colon, and time in format hh:mm:ss (without spaces and colon). ps. You should/need to read www.w3.org links that I gave in post #6 (and even better entire HTTP protocol specification). f.e. Date header is described here https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1 Not without a reason there is so many times repeated word "MUST".. Rules are very strict.
fiveworlds Posted January 20, 2017 Author Posted January 20, 2017 Alright I'm going to London tomorrow so I won't be able to work on this for a few days.
fiveworlds Posted January 26, 2017 Author Posted January 26, 2017 (edited) Okay so now the problem is with loading images. They seem to be loading forever for some reason. // socketprogramming4.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <io.h> #include <stdio.h> #include <stdlib.h> #include <dos.h> #include <winsock2.h> #include "Sendfile.h" #pragma comment(lib,"ws2_32.lib") //Winsock Library char dest[MAXCHAR]; bool send_all(int socket, void *buffer, size_t length) { char *ptr = (char*)buffer; while (length > 0) { int i = send(socket, ptr, length, 0); if (i < 1) return false; ptr += i; length -= i; } shutdown(socket, SD_SEND); return true; } char* strncat_s_tester(const char * initialDest, const char * src, int count) { char* temp; strcpy_s(dest, _countof(dest), initialDest); errno_t err = strncat_s(dest, _countof(dest), src, count); temp = (char*) dest; return temp; } int strpos(char *haystack, char *needle) { char *p = strstr(haystack, needle); if (p) return p - haystack; return -1; } int main(int argc, char *argv[]) { WSADATA wsa; SOCKET s, new_socket; struct sockaddr_in server, client; int c; char *message, server_reply[2000]; int recv_size; printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("Failed. Error Code : %d", WSAGetLastError()); return 1; } printf("Initialised.\n"); //Create a socket if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { printf("Could not create socket : %d", WSAGetLastError()); } printf("Socket created.\n"); //Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(80); //Bind if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) { printf("Bind failed with error code : %d", WSAGetLastError()); exit(EXIT_FAILURE); } puts("Bind done"); //Listen to incoming connections listen(s, 3); //Accept and incoming connection puts("Waiting for incoming connections..."); c = sizeof(struct sockaddr_in); while ((new_socket = accept(s, (struct sockaddr *)&client, &c)) != INVALID_SOCKET) { if ((recv_size = recv(new_socket, server_reply, 2000, 0)) == SOCKET_ERROR) { puts("recv failed"); } else { puts(server_reply); } //Receive a reply from the server if (strstr(server_reply, "GET / HTTP/1.1") != NULL) { Sendfile::sendfile(new_socket, "index.html"); } else if (strstr(server_reply, "index.css") != NULL) { Sendfile::sendfile(new_socket,"index.css"); } else if (strstr(server_reply, "favicon.ico") != NULL) { Sendfile::sendfile(new_socket, "favicon.ico"); } else if (strstr(server_reply, "favicon.png") != NULL) { Sendfile::sendfile(new_socket, "favicon.png"); } else { message = "File Not Found"; send_all(new_socket, message, strlen(message)); } } if (new_socket == INVALID_SOCKET) { printf("accept failed with error code : %d", WSAGetLastError()); return 1; } closesocket(s); WSACleanup(); return 0; }MimeHelper.cpp #include "StdAfx.h" #include <Windows.h> #include "MimeHelper.h" #include <algorithm> #include <string> const char MimeTypes[][2][128] = { {"***","Content-Type: application/octet-stream\r\n"}, {"CSV","Content-Type: text/csv\r\n"}, {"TSV","Content-Type: text/tab-separated-values\r\n"}, {"TAB","Content-Type: text/tab-separated-values\r\n"}, {"HTML","Content-Type: text/html\r\n"}, {"HTM","Content-Type: text/html\r\n"}, {"DOC","Content-Type: application/msword\r\n"}, {"DOCX","Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document\r\n"}, {"ODS","Content-Type: application/x-vnd.oasis.opendocument.spreadsheet\r\n"}, {"ODT","Content-Type: application/vnd.oasis.opendocument.text\r\n"}, {"RTF","Content-Type: application/rtf\r\n"}, {"SXW","Content-Type: application/vnd.sun.xml.writer\r\n"}, {"TXT","Content-Type: text/plain\r\n"}, {"XLS","Content-Type: application/vnd.ms-excel\r\n"}, {"XLSX","Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\r\n"}, {"PDF","Content-Type: application/pdf\r\n"}, {"PPT","Content-Type: application/vnd.ms-powerpoint\r\n"}, {"PPS","Content-Type: application/vnd.ms-powerpoint\r\n"}, {"PPTX","Content-Type: application/vnd.openxmlformats-officedocument.presentationml.presentation\r\n"}, {"WMF","Content-Type: image/x-wmf\r\n"}, {"ATOM","Content-Type: application/atom+xml\r\n"}, {"XML","Content-Type: application/xml\r\n"}, {"JSON","Content-Type: application/json\r\n"}, {"JS","Content-Type: application/javascript\r\n"}, {"OGG","Content-Type: application/ogg\r\n"}, {"PS","Content-Type: application/postscript\r\n"}, {"WOFF","Content-Type: application/x-woff\r\n"}, {"XHTML","Content-Type: application/xhtml+xml\r\n"}, {"XHT","Content-Type: application/xhtml+xml\r\n"}, {"ZIP","Content-Type: application/zip\r\n"}, {"GZ","Content-Type: application/x-gzip\r\n"}, {"RAR","Content-Type: application/rar\r\n"}, {"RM","Content-Type: application/vnd.rn-realmedia\r\n"}, {"RMVB","Content-Type: application/vnd.rn-realmedia-vbr\r\n"}, {"SWF","Content-Type: application/x-shockwave-flash\r\n"}, {"AU","Content-Type: audio/basic\r\n"}, {"SND","Content-Type: audio/basic\r\n"}, {"MID","Content-Type: audio/mid\r\n"}, {"RMI","Content-Type: audio/mid\r\n"}, {"MP3","Content-Type: audio/mpeg\r\n"}, {"AIF","Content-Type: audio/x-aiff\r\n"}, {"AIFC","Content-Type: audio/x-aiff\r\n"}, {"AIFF","Content-Type: audio/x-aiff\r\n"}, {"M3U","Content-Type: audio/x-mpegurl\r\n"}, {"RA","Content-Type: audio/vnd.rn-realaudio\r\n"}, {"RAM","Content-Type: audio/vnd.rn-realaudio\r\n"}, {"WAV","Content-Type: audio/x-wave\r\n"}, {"WMA","Content-Type: audio/x-ms-wma\r\n"}, {"M4A","Content-Type: audio/x-m4a\r\n"}, {"BMP","Content-Type: image/bmp\r\n"}, {"GIF","Content-Type: image/gif\r\n"}, {"JPE","Content-Type: image/jpeg\r\n"}, {"JPEG","Content-Type: image/jpeg\r\n"}, {"JPG","Content-Type: image/jpeg\r\n"}, {"JFIF","Content-Type: image/jpeg\r\n"}, {"PNG","Content-Type: image/png\r\n"}, {"SVG","Content-Type: image/svg+xml\r\n"}, {"TIF","Content-Type: image/tiff\r\n"}, {"TIFF","Content-Type: image/tiff\r\n"}, {"ICO","Content-Type: image/vnd.microsoft.icon\r\n"}, {"CSS","Content-Type: text/css\r\n"}, {"BAS","Content-Type: text/plain\r\n"}, {"C","Content-Type: text/plain\r\n"}, {"H","Content-Type: text/plain\r\n"}, {"RTX","Content-Type: text/richtext\r\n"}, {"MP2","Content-Type: video/mpeg\r\n"}, {"MPA","Content-Type: video/mpeg\r\n"}, {"MPE","Content-Type: video/mpeg\r\n"}, {"MPEG","Content-Type: video/mpeg\r\n"}, {"MPG","Content-Type: video/mpeg\r\n"}, {"MPV2","Content-Type: video/mpeg\r\n"}, {"MOV","Content-Type: video/quicktime\r\n"}, {"QT","Content-Type: video/quicktime\r\n"}, {"LSF","Content-Type: video/x-la-asf\r\n"}, {"LSX","Content-Type: video/x-la-asf\r\n"}, {"ASF","Content-Type: video/x-ms-asf\r\n"}, {"ASR","Content-Type: video/x-ms-asf\r\n"}, {"ASX","Content-Type: video/x-ms-asf\r\n"}, {"AVI","Content-Type: video/x-msvideo\r\n"}, {"3GP","Content-Type: video/3gpp\r\n"}, {"3GPP","Content-Type: video/3gpp\r\n"}, {"3G2","Content-Type: video/3gpp2\r\n"}, {"MOVIE","Content-Type: video/x-sgi-movie\r\n"}, {"MP4","Content-Type: video/mp4\r\n"}, {"WMV","Content-Type: video/x-ms-wmv\r\n"}, {"WEBM","Content-Type: video/webm\r\n"}, {"M4V","Content-Type: video/x-m4v\r\n"}, {"FLV","Content-Type: video/x-flv\r\n"} }; char* get_filename_ext(char* filename) { char* dot = strrchr(filename, '.'); if (!dot || dot == filename) return ""; return dot + 1; } char* ConvertToUpper(char* szSource) { if (szSource == NULL) return NULL; int i = 0; char *str = strdup(szSource); while (str[i]) { if (str[i] >= 97 && str[i] <= 122) str[i] -= 32; i++; } return (str); } const char* MimeHelper::GetMimeTypeFromFileName(char* szFileExt) { szFileExt = get_filename_ext(szFileExt); szFileExt = ConvertToUpper(szFileExt); for (int i = 0; i < sizeof (MimeTypes) / sizeof (MimeTypes[0]); i++) { if (strcmp(MimeTypes[i][0], szFileExt) == 0) { return MimeTypes[i][1]; } } return MimeTypes[0][1]; }sendfile.cpp #include "StdAfx.h" #include "StdAfx.h" #include <Windows.h> #include "MimeHelper.h" #include <algorithm> #include <string> #include "time.h" #include <memory.h> #include "Sendfile.h" #include <stdlib.h> const char* Sendfile::sendfile(int socket, char* filename) { char dest[MAXCHAR]; struct tm newtime; __time32_t aclock; char *message, *date, *contentType, buffer[32], *contentlength = ""; const char *BOUNDARY = "\r\n", *SERVERNAME = "Server: test\r\n", *HTTP_OK = "HTTP/1.1 200 OK\r\n"; _time32(&aclock); // Get time in seconds. _localtime32_s(&newtime, &aclock); // Convert time to struct tm form. errno_t errNum; FILE *fp; int i; errNum = asctime_s(buffer, 32, &newtime); if (errNum) { printf("Error code: %d", (int)errNum); return "false"; } //open and get the file handle if ((fp = fopen(filename, "rb")) == NULL) { return "HTTP 404"; shutdown(socket, 1); } else { //Set Http ok header send(socket, HTTP_OK, strlen(HTTP_OK), 0); //Set servername header send(socket, SERVERNAME, strlen(SERVERNAME), 0); //Set the current date message = "Date : "; date = (char*)buffer; strcpy_s(dest, _countof(dest), message); errNum = strncat_s(dest, _countof(dest), date, strlen(date)); message = (char*)dest; send(socket, message, strlen(message), 0); //Set the content mime-type contentType = (char*)MimeHelper::GetMimeTypeFromFileName(filename); send(socket, contentType, strlen(contentType), 0); //Set the Content-Length fseek(fp, 0L, SEEK_END); i = ftell(fp); rewind(fp); message = "Content-Length: "; sprintf(buffer, "%d", i); contentlength = buffer; strcpy_s(dest, _countof(dest), message); errNum = strncat_s(dest, _countof(dest), contentlength, strlen(contentlength)); message = (char*)dest; send(socket, message, strlen(message), 0); send(socket, "\r\n", strlen("\r\n"), 0); //Set the content boundary send(socket, BOUNDARY, strlen(BOUNDARY), 0); while (fgets(message, 80, fp) != NULL) { send(socket, message, strlen(message), 0); } fclose(fp); } shutdown(socket, 1); return "true"; } Edited January 26, 2017 by fiveworlds
Sensei Posted January 26, 2017 Posted January 26, 2017 (edited) char* ConvertToUpper(char* szSource) { if (szSource == NULL) return NULL; int i = 0; char *str = strdup(szSource); while (str[i]) { if (str[i] >= 97 && str[i] <= 122) str[i] -= 32; i++; } return (str); } C/C++ have built-in linked libraries functions for checking whether char is letter, whether it's upper or lower letter, or to making upper or lower letter from other one.. http://www.cplusplus.com/reference/cctype/islower/ http://www.cplusplus.com/reference/cctype/isupper/ http://www.cplusplus.com/reference/cctype/isalpha/ http://www.cplusplus.com/reference/cctype/toupper/ http://www.cplusplus.com/reference/cctype/tolower/ You didn't even need it. You could use case-insensitive string comparison function stricmp() instead. //Set the current date message = "Date : "; Here you made the same error as before. There is no space after Date and colon.. const char MimeTypes[][2][128] = { (....) {"M4V","Content-Type: video/x-m4v\r\n"}, {"FLV","Content-Type: video/x-flv\r\n"} }; I would use NULL- terminated array instead of above (or better C++ classes and objects instead)... f.e. struct MIMEEntry { char *m_Extension; char *m_ContentType; bool m_Binary; // binary or text }; static MIMEEntry entries[] = { { "m4v", "video/x-m4v", true }, { "html", "text/html", false }, (.... ) { NULL }, }; Then in loop you're just checking whether entry is NULL or not, to stop enumeration.. Why don't you make function for sending headers? f.e. int send_header( socket, const char *row ) { // send row, // send \r\n } Then sending HTTP response will look like: send_header( s, "HTTP/1.1 OK" ); send_header( s, "Content-Type: text/html" ); send_header( s, "Content-Length: 123" ); send_header( s, "" ); // empty You could easily add logging there, if needed, and see what data are send to client.. while (fgets(message, 80, fp) != NULL) { send(socket, message, strlen(message), 0); } ?!?! strlen()? Image is not ASCII string... fgets() is NOT for reading binary files. It's for text files only.. You don't read documentation of functions which you're using.. http://www.cplusplus.com/reference/cstdio/fgets/ "Get string from stream" I see that you're using this code for either text files (.html, .css) and for binary (.png), so you will have to use fgets() only to text files (and fopen() in "r" mode!) and fread() only to binary files (and fopen() in "rb" mode!) Also 80 row length is way to small.. Soon you will forget you made such limit, and have longer row, and it'll fail, and again you won't know why it failed.. shutdown(socket, 1); And again the same... errNum = asctime_s(buffer, 32, &newtime); if (errNum) { printf("Error code: %d", (int)errNum); return "false"; } //open and get the file handle if ((fp = fopen(filename, "rb")) == NULL) { return "HTTP 404"; shutdown(socket, 1); } Here is also not appropriate error handling.. You have to send error to client! Through TCP/IP socket.. In HTTP response.. const char* Sendfile::sendfile(int socket, char* filename) { char dest[MAXCHAR]; MAXCHAR is NOT size of string buffer (char array)... It's equal to 127 (2^7-1 = 127) The largest signed char value. Similar like MAXSHORT is 32767 (2^15-1) and MAXINT is 2147483647 (2^31-1)... Make your own f.e. #define BUFFERSIZE 1024 char buffer[ BUFFERSIZE ]; sprintf( buffer, "Content-Length: %d", get_file_size( filename ) ); send_header( s, buffer ); sprintf( buffer, "Content-Type: %s", get_file_type( filename ) ); send_header( s, buffer ); Edited January 26, 2017 by Sensei 1
fiveworlds Posted January 26, 2017 Author Posted January 26, 2017 (edited) Okay so I changed Sendfile.cpp and it appears to be sending images now. #include "StdAfx.h" #include <Windows.h> #include "MimeHelper.h" #include <algorithm> #include <string> #include "time.h" #include <memory.h> #include "Sendfile.h" #include <stdlib.h> #include <iostream> #include <fstream> void sendHeader(int socket, char *header) { char dest[3000]; const char* CRLF = "\r\n"; errno_t headerError; strcpy_s(dest, _countof(dest), header); headerError = strncat_s(dest, _countof(dest), CRLF, strlen(CRLF)); if (headerError) { printf("Error code: %d", (int)headerError); } header = (char*)dest; send(socket, header, strlen(header), 0); } void sendDateHeader(int socket) { struct tm newtime; __time32_t aclock; const char* CRLF = "\r\n"; char *dateHeader, buff[MAXCHAR], buffer[32], *date; errno_t errDate; _time32(&aclock); // Get time in seconds. _localtime32_s(&newtime, &aclock); // Convert time to struct tm form. errDate = asctime_s(buff, 32, &newtime); if (errDate) { printf("Error code: %d", (int)errDate); } //get the current date dateHeader = "Date: "; date = (char*)buff; strcpy_s(buff, _countof(buff), dateHeader); errDate = strncat_s(buff, _countof(buff), date, strlen(date)); if (errDate) { printf("Error code: %d", (int)errDate); } dateHeader = (char*)buff; strcpy_s(buff, _countof(buff), dateHeader); errDate = strncat_s(buff, _countof(buff), CRLF, strlen(CRLF)); if (errDate) { printf("Error code: %d", (int)errDate); } dateHeader = (char*)buff; send(socket, dateHeader, strlen(dateHeader), 0); } void sendContentLength(int socket, int length) { char *message,*contentlength,buffer[32],dest[MAXCHAR]; errno_t errNum; message = "Content-Length: "; sprintf(buffer, "%d", length); contentlength = buffer; strcpy_s(dest, _countof(dest), message); errNum = strncat_s(dest, _countof(dest), contentlength, strlen(contentlength)); message = (char*)dest; send(socket, message, strlen(message), 0); } void sendTextFile(int socket, char* filename, char* contentType) { char *filedata = ""; char *BOUNDARY = "\r\n", *SERVERNAME = "Server: test", *HTTP_OK = "HTTP/1.1 200 OK"; FILE *fp; std::ifstream is(filename, std::ifstream::binary); if (is) { // get length of file: is.seekg(0, is.end); int length = is.tellg(); is.seekg(0, is.beg); sendHeader(socket, HTTP_OK);//Set Http ok header sendHeader(socket, SERVERNAME);//Set servername header sendHeader(socket, contentType);//Set the content mime-type sendContentLength(socket, length);//Set the content-length sendDateHeader(socket);//Set the current date send(socket, BOUNDARY, strlen(BOUNDARY), 0);//set the content boundary char * buffer = new char[length]; std::cout << "Reading " << length << " characters... "; // read data as a block: is.read(buffer, length); if (is) std::cout << "all characters read successfully."; else std::cout << "error: only " << is.gcount() << " could be read"; is.close(); send(socket, buffer, length, 0); delete[] buffer; } else { printf("error"); } } const char* Sendfile::sendfile(int socket, char* filename) { char* contentType; contentType = (char*)MimeHelper::GetMimeTypeFromFileName(filename); if(strstr(contentType, "text") != NULL) { sendTextFile(socket, filename, contentType); } else { sendTextFile(socket, filename, contentType); } shutdown(socket, 1); return "true"; } I don't know how to recieve post requests yet. Get requests are simple enough. Edited January 26, 2017 by fiveworlds
Sensei Posted January 26, 2017 Posted January 26, 2017 (edited) If you made sendDateHeader() it should use sendHeader(), not send() directly, not attach CRLF by itself, don't you see it? You're reusing MAXCHAR over and over again, while MAXCHAR is not size of buffer... ps. "Appears to be working" is not enough.. f.e. error handling is way below limits... ps2. Thx, ydoaPs, but put some thought in this stuff.. I can't handle it by myself... I am writing how to do it, and then it's ignored, and made worser way... Edited January 26, 2017 by Sensei
fiveworlds Posted January 26, 2017 Author Posted January 26, 2017 You're reusing MAXCHAR over and over again,while MAXCHAR is not size of buffer... #define is for macros. Why would I use it for a constant?? If you made sendDateHeader() it should use sendHeader(), not send() directly, not attach CRLF by itself, don't you see it? That's a tiny change. #include "StdAfx.h" #include <Windows.h> #include "MimeHelper.h" #include <algorithm> #include <string> #include "time.h" #include <memory.h> #include "Sendfile.h" #include <stdlib.h> #include <iostream> #include <fstream> void sendHeader(int socket, char *header) { char dest[3000]; const char* CRLF = "\r\n"; errno_t headerError; strcpy_s(dest, _countof(dest), header); headerError = strncat_s(dest, _countof(dest), CRLF, strlen(CRLF)); if (headerError) { printf("Error code: %d", (int)headerError); } header = (char*)dest; send(socket, header, strlen(header), 0); } void sendDateHeader(int socket) { struct tm newtime; __time32_t aclock; const char* CRLF = "\r\n"; char *dateHeader, buff[3000], buffer[32], *date; errno_t errDate; _time32(&aclock); // Get time in seconds. _localtime32_s(&newtime, &aclock); // Convert time to struct tm form. errDate = asctime_s(buff, 32, &newtime); if (errDate) { printf("Error code: %d", (int)errDate); } //get the current date dateHeader = "Date: "; date = (char*)buff; strcpy_s(buff, _countof(buff), dateHeader); errDate = strncat_s(buff, _countof(buff), date, strlen(date)); if (errDate) { printf("Error code: %d", (int)errDate); } dateHeader = (char*)buff; sendHeader(socket, dateHeader); } void sendContentLength(int socket, int length) { char *message,*contentlength,buffer[32],dest[3000]; errno_t errNum; message = "Content-Length: "; sprintf(buffer, "%d", length); contentlength = buffer; sendHeader(socket, contentlength); } void sendTextFile(int socket, char* filename, char* contentType) { char *filedata = ""; char *BOUNDARY = "\r\n", *SERVERNAME = "Server: test", *HTTP_OK = "HTTP/1.1 200 OK"; FILE *fp; std::ifstream is(filename, std::ifstream::binary); if (is) { // get length of file: is.seekg(0, is.end); int length = is.tellg(); is.seekg(0, is.beg); sendHeader(socket, HTTP_OK);//Set Http ok header sendHeader(socket, SERVERNAME);//Set servername header sendHeader(socket, contentType);//Set the content mime-type sendContentLength(socket, length);//Set the content-length sendDateHeader(socket);//Set the current date sendHeader(socket, "");//set the content boundary char * buffer = new char[length]; std::cout << "Reading " << length << " characters... "; // read data as a block: is.read(buffer, length); if (is) std::cout << "all characters read successfully."; else std::cout << "error: only " << is.gcount() << " could be read"; is.close(); send(socket, buffer, length, 0); delete[] buffer; } else { printf("error"); } } const char* Sendfile::sendfile(int socket, char* filename) { char* contentType; contentType = (char*)MimeHelper::GetMimeTypeFromFileName(filename); if(strstr(contentType, "text") != NULL) { sendTextFile(socket, filename, contentType); } else { sendTextFile(socket, filename, contentType); } shutdown(socket, 1); return "true"; } Turns out I just needed to add an else if to get the post request data. else if (strstr(server_reply, "POST / HTTP/1.1") != NULL) { Sendfile::sendfile(new_socket, "index.html"); } The subsequent post header data POST / HTTP/1.1 Host: localhost Connection: keep-alive Content-Length: 9 Cache-Control: max-age=0 Origin: http://localhost Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36 Content-Type: application/x-www-form-urlencoded Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Referer: http://localhost/ Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.8 test=test╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
Sensei Posted January 26, 2017 Posted January 26, 2017 (edited) #define is for macros. Why would I use it for a constant?? They are the same in C. Check for example PI... #define M_PI 3.14159265... in header file math.h You can/SHOULD make your own when needed... The subsequent post header data Slightly confused, by why you might need it... You don't need/use POST at all... POST can be called only from forms, from HTML code... Edited January 26, 2017 by Sensei
fiveworlds Posted January 27, 2017 Author Posted January 27, 2017 Slightly confused, by why you might need it... You don't need/use POST at all... POST can be called only from forms, from HTML code... It's a https web server i'm trying to make. So I want to use forms from HTML code. The files are included as resources in the project folder. <!DOCTYPE html> <html> <head> <link type='text/css' rel='stylesheet' href='index.css' /> <link rel='shortcut icon' type='image/x-icon' href='favicon.ico' /> </head> <body> <a href='test'>Testing</a> <img src="favicon.png" /> <form method="post"> <input type="text" name="test" /> <input type="submit" /> </form> </body> </html> Using a constant #include "StdAfx.h" #include <Windows.h> #include "MimeHelper.h" #include <algorithm> #include <string> #include "time.h" #include <memory.h> #include "Sendfile.h" #include <stdlib.h> #include <iostream> #include <fstream> const int BUFFERSIZE = 3000; void sendHeader(int socket, char *header) { char dest[BUFFERSIZE]; const char* CRLF = "\r\n"; errno_t headerError; strcpy_s(dest, _countof(dest), header); headerError = strncat_s(dest, _countof(dest), CRLF, strlen(CRLF)); if (headerError) { printf("Error code: %d", (int)headerError); } header = (char*)dest; send(socket, header, strlen(header), 0); } void sendDateHeader(int socket) { struct tm newtime; __time32_t aclock; const char* CRLF = "\r\n"; char *dateHeader, buff[BUFFERSIZE], buffer[32], *date; errno_t errDate; _time32(&aclock); // Get time in seconds. _localtime32_s(&newtime, &aclock); // Convert time to struct tm form. errDate = asctime_s(buff, 32, &newtime); if (errDate) { printf("Error code: %d", (int)errDate); } //get the current date dateHeader = "Date: "; date = (char*)buff; strcpy_s(buff, _countof(buff), dateHeader); errDate = strncat_s(buff, _countof(buff), date, strlen(date)); if (errDate) { printf("Error code: %d", (int)errDate); } dateHeader = (char*)buff; sendHeader(socket, dateHeader); } void sendContentLength(int socket, int length) { char *message,*contentlength,buffer[32],dest[BUFFERSIZE]; errno_t errNum; message = "Content-Length: "; sprintf(buffer, "%d", length); contentlength = buffer; sendHeader(socket, contentlength); } void sendTextFile(int socket, char* filename, char* contentType) { char *filedata = ""; char *BOUNDARY = "\r\n", *SERVERNAME = "Server: test", *HTTP_OK = "HTTP/1.1 200 OK"; FILE *fp; std::ifstream is(filename, std::ifstream::binary); if (is) { // get length of file: is.seekg(0, is.end); int length = is.tellg(); is.seekg(0, is.beg); sendHeader(socket, HTTP_OK);//Set Http ok header sendHeader(socket, SERVERNAME);//Set servername header sendHeader(socket, contentType);//Set the content mime-type sendContentLength(socket, length);//Set the content-length sendDateHeader(socket);//Set the current date sendHeader(socket, "");//set the content boundary char * buffer = new char[length]; std::cout << "Reading " << length << " characters... "; // read data as a block: is.read(buffer, length); if (is) std::cout << "all characters read successfully."; else std::cout << "error: only " << is.gcount() << " could be read"; is.close(); send(socket, buffer, length, 0); delete[] buffer; } else { printf("error"); } } const char* Sendfile::sendfile(int socket, char* filename) { char* contentType; contentType = (char*)MimeHelper::GetMimeTypeFromFileName(filename); if(strstr(contentType, "text") != NULL) { sendTextFile(socket, filename, contentType); } else { sendTextFile(socket, filename, contentType); } shutdown(socket, 1); return "true"; } Using the #define macro properly. #define max(A,B) ((A) >(B) ? (A):(B)) #define is like a function but isn't it performs inline substitution so that. x = max(p+q,r+s); is replaced by x = ((p+q) > (r+s) ? (p+q) : (r+s)); at compile time.
Sensei Posted January 27, 2017 Posted January 27, 2017 (edited) It's a https web server i'm trying to make. You must be kidding us... You have no idea how to make HTTP, and you want to make HTTPS.. ?! All your work, disagree with this... HTTPS don't listen on port 80 like in posts #3, #5, #12... You have no bloody idea, nor willingness to know about either HTTP, nor HTTPS... Otherwise you would be very busy reading all day long, for months, protocol specifications... Forms don't use HTTPS (HTTP-Secure protocol!). You must made yet another mistake, sending message through POST, is not equivalent to HTTPS (secure HTTP)... Edited January 27, 2017 by Sensei
fiveworlds Posted January 27, 2017 Author Posted January 27, 2017 (edited) You have no idea how to make HTTP,and you want to make HTTPS.. ?! Yeah it should be a fun project. You have no bloody idea, nor willingness to know about either HTTP, nor HTTPS... Otherwise you would be very busy reading all day long, for months, protocol specifications... I know most of the protocols already. I learn by doing schools can be so frustrating like that who learns anything from reading books?? You must made yet another mistake, sending message through POST, is not equivalent to HTTPS (secure HTTP)... Not over http. Forms don't use HTTPS Browsers encrypt with https. HTTPS don't listen on port 80 That's right https works on every port. However Browsers use 443. Oh and consts are variables kept in memory for faster runtimes on repetitive tasks. #define is not kept in memory. Edited January 27, 2017 by fiveworlds
Sensei Posted January 27, 2017 Posted January 27, 2017 (edited) First, you should learn how to send content compressed by gzip/deflate, then multi-segment, then the next stage is to dream about the real encryption.. What we're doing on forum is not even tip of iceberg.. Edited January 27, 2017 by Sensei
fiveworlds Posted January 27, 2017 Author Posted January 27, 2017 (edited) First, you should learn how to send content compressed by gzip/deflate, then multi-segment, then the next stage is to dream about the real encryption.. What we're doing on forum is not even tip of iceberg.. Yes but it is good to learn. For instance if I wanted to make a game with payment processing then I have to know how to setup ssl sockets because most payment providers won't accept payment from insecure connections. Hewlett Packard has a tutorial on setting up an ssl socket http://h41379.www4.hpe.com/doc/83final/ba554_90007/ch04s03.html using the openSSL API but it is pointless following it until other stuff (like loading images) works properly. At the moment I want to make a code editor with syntax highlighting which will run a web server with https and open the page in google chrome when I click the run button. ps zip data is sent with a boundary given by a multipart/form-data post request. Like so not exactly sure how to receive that content in C though. -----------------------------25312170725491 Content-Disposition: form-data; name="test"; filename="ColorCode_1_0_2.zip" Content-Type: application/x-zip-compressed CRLF content -----------------------------25312170725491 What I am receiving at the moment looks like -----------------------------1137250621972 Content-Disposition: form-data; name="test"; filename="ColorCode_1_0_2.zip" Content-Type: application/x-zip-compressed PK in firefox so obviously the recv is cutting off halfway. Edited January 27, 2017 by fiveworlds
Unity+ Posted January 28, 2017 Posted January 28, 2017 You must be kidding us... You have no idea how to make HTTP, and you want to make HTTPS.. ?! All your work, disagree with this... HTTPS don't listen on port 80 like in posts #3, #5, #12... You have no bloody idea, nor willingness to know about either HTTP, nor HTTPS... Otherwise you would be very busy reading all day long, for months, protocol specifications... Forms don't use HTTPS (HTTP-Secure protocol!). You must made yet another mistake, sending message through POST, is not equivalent to HTTPS (secure HTTP)... Could you refrain from making hostile posts? It would be better if the learner was able to learn about the concepts instead of being deterred from actually learning the material...
Sensei Posted January 28, 2017 Posted January 28, 2017 (edited) Yes but it is good to learn. One thing we agree on. I am glad you're thinking this way. But you're trying always do everything as the less work as possible and learning involved, starting from not reading docs of C/C++ functions that you're using, ignoring reading docs I gave link to etc.. You're searching for and copying code from somebody else example, and then learning how to not do it, if they contained errors/mistakes. Like this shutdown(s,1).. You wouldn't know that SD_SEND is 1, unless you would not get this constant from some poor C/C++ example that you found on the net.. Search for examples, but when they contain functions that you never heard about, that you never used, search for their proper documentation, and read them all. You will often see that in C/C++ examples somebody not correctly used them.. f.e. didn't handle error codes to show error to user.. For instance if I wanted to make a game with payment processing then I have to know how to setup ssl sockets because most payment providers won't accept payment from insecure connections. But you don't need SSL to do such functionality at all.. Make PayPal button to press by user. https://developer.paypal.com/docs/classic/paypal-payments-standard/integration-guide/create_payment_button/ It can be called from not secure HTML page.. Edited January 28, 2017 by Sensei
fiveworlds Posted January 28, 2017 Author Posted January 28, 2017 So I cleaned up the headers and now they match those sent by the Apache httpd as far as I can tell (apart from servername). //Sendfile.cpp #include "StdAfx.h" #include <Windows.h> #include "MimeHelper.h" #include <algorithm> #include <string> #include "time.h" #include <memory.h> #include "Sendfile.h" #include <stdlib.h> #include <iostream> #include <fstream> #include <tchar.h> #include <strsafe.h> #define LastModifiedBuffer 49 #define GMTLENGTH 37 int sendHeader(int socket, char *header) { char dest[3000]; const char* CRLF = "\r\n"; errno_t headerError; strcpy_s(dest, _countof(dest), header); headerError = strncat_s(dest, _countof(dest), CRLF, strlen(CRLF)); if (headerError) { printf("Error code: %d", (int)headerError); return 0; } header = (char*)dest; send(socket, header, strlen(header), 0); return 1; } int sendDateHeader(int socket) { SYSTEMTIME st; GetSystemTime(&st); char int_to_day[][7] = { { "Mon" },{ "Tue" },{ "Wed" }, { "Thu" },{ "Fri" },{ "Sat" }, { "Sun" } }; char int_to_month[][12] = { { "Jan" },{ "Feb" },{ "Mar" }, { "Apr" },{ "May" },{ "Jun" }, { "Jul" },{ "Aug" },{ "Sep" }, { "Oct" },{ "Nov" },{ "Dec" }, }; char GMT[GMTLENGTH]; sprintf_s(GMT, GMTLENGTH, "Date: %s, %d %s %02d %02d:%02d:%02d GMT", int_to_day[st.wDayOfWeek], st.wDay, int_to_month[st.wMonth], st.wYear, st.wHour, st.wMinute, st.wSecond); char* dateHeader = GMT; sendHeader(socket, GMT); return 1; } int sendContentLength(int socket, int length) { char *message, *contentlength, buffer[32], dest[3000]; errno_t errNum; sprintf_s(buffer, sizeof(buffer),"Content-Length: %d", length); contentlength = buffer; printf(contentlength); printf("\n");printf("\n"); sendHeader(socket, contentlength); return 1; } // GetLastWriteTime - Retrieves the last-write time and converts // the time to a string // // Return value - TRUE if successful, FALSE otherwise // hFile - Valid file handle // lpszString - Pointer to buffer to receive string #define LastModifiedBuffer 49 BOOL GetLastWriteTime(int socket, HANDLE hFile, LPTSTR lpszString, DWORD dwSize) { FILETIME ftCreate, ftAccess, ftWrite; SYSTEMTIME stUTC, stLocal; DWORD dwRet; char LastModified[LastModifiedBuffer]; // Retrieve the file times for the file. if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)) return FALSE; // Convert the last-write time to local time. FileTimeToSystemTime(&ftWrite, &stUTC); SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal); char int_to_day[][7] = { { "Mon" },{ "Tue" },{ "Wed" }, { "Thu" },{ "Fri" },{ "Sat" }, { "Sun" } }; char int_to_month[][12] = { { "Jan" },{ "Feb" },{ "Mar" }, { "Apr" },{ "May" },{ "Jun" }, { "Jul" },{ "Aug" },{ "Sep" }, { "Oct" },{ "Nov" },{ "Dec" }, }; // Build a string showing the date and time. sprintf_s(LastModified, LastModifiedBuffer, "Last-Modified: %s, %d %s %02d %02d:%02d:%02d GMT", int_to_day[stLocal.wDayOfWeek], stLocal.wDay, int_to_month[stLocal.wMonth], stLocal.wYear, stLocal.wHour, stLocal.wMinute, stLocal.wSecond); sendHeader(socket, LastModified); } wchar_t *convertCharArrayToLPCWSTR(const char* charArray) { wchar_t* wString = new wchar_t[4096]; MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096); return wString; } int sendLastModified(int socket, char* file) { HANDLE hFile; TCHAR szBuf[MAX_PATH]; LPCWSTR filename = convertCharArrayToLPCWSTR(file); hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("CreateFile failed with %d\n", GetLastError()); Sleep(2000); return 0; } GetLastWriteTime(socket, hFile, szBuf, MAX_PATH); CloseHandle(hFile); } void sendTextFile(int socket, char* filename, char* contentType) { char *filedata = ""; char *BOUNDARY = "\r\n", *SERVERNAME = "Server: test", *ETAG = "Etag: 19b-5471fb7cf045b", *ACCEPTRANGES = "Accept-Ranges: bytes", *HTTP_OK = "HTTP/1.1 200 OK", *KEEPALIVE = "Keep-Alive: timeout=5, max=100", *CONNECTION = "Connection: Keep-Alive"; FILE *fp; std::ifstream is(filename, std::ifstream::binary); if (is) { // get length of file: is.seekg(0, is.end); int length = is.tellg(); is.seekg(0, is.beg); if (sendHeader(socket, HTTP_OK) == 0) //Set Http ok header { ///Error Handling } if (sendDateHeader(socket) == 0)//Set the content-length { ///Error Handling } if (sendHeader(socket, SERVERNAME) == 0) //Set servername header { ///Error Handling } if (sendLastModified(socket, filename) == 0) //Set servername header { ///Error Handling } if (sendHeader(socket, ETAG) == 0) //Set the etag header { ///Error Handling } if (sendHeader(socket, ACCEPTRANGES) == 0) //Set the accept-ranges header { ///Error Handling } if (sendContentLength(socket, length) == 0) //Set the content-length { ///Error Handling } if (sendHeader(socket, KEEPALIVE) == 0) //Set the content mime-type header { ///Error Handling } if (sendHeader(socket, CONNECTION) == 0) //Set the content mime-type header { ///Error Handling } if (sendHeader(socket, contentType) == 0) //Set the content mime-type header { ///Error Handling } if (sendHeader(socket, "") == 0)//set the content boundary { ///Error Handling } char * buffer = new char[length]; std::cout << "Reading " << length << " characters... "; // read data as a block: is.read(buffer, length); if (is) { std::cout << "all characters read successfully."; } else { std::cout << "error: only " << is.gcount() << " could be read"; } is.close(); send(socket, buffer, length, 0); delete[] buffer; } else { printf("error"); } } const char* Sendfile::sendfile(int socket, char* filename) { char* contentType; contentType = (char*)MimeHelper::GetMimeTypeFromFileName(filename); if (strstr(contentType, "text") != NULL) { sendTextFile(socket, filename, contentType); } else { sendTextFile(socket, filename, contentType); } shutdown(socket, 1); return "true"; } But you don't need SSL to do such functionality at all..Make PayPal button to press by user. Hmm SSL is to stop man in the middle attacks via script and form injection into transferred packets from getting access to user data by securely sending data. But you're trying always do everything as the less work as possible and learning involved, Wrong I try and test absolutely everything I use. Which takes longer than just reading the material.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now