Jump to content

Recommended Posts

Posted

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.

Posted (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 by fiveworlds
Posted

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.

Posted (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 by Sensei
Posted (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 by fiveworlds
Posted (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:

post-100882-0-76496000-1484909170_thumb.png

 

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 by Sensei
Posted

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.

Posted

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.

Posted (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 by fiveworlds
Posted (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 by Sensei
Posted (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 by fiveworlds
Posted (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 by Sensei
Posted
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╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
Posted (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 by Sensei
Posted
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.

Posted (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 by Sensei
Posted (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 by fiveworlds
Posted (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 by Sensei
Posted (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 by fiveworlds
Posted

 

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...

Posted (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 by Sensei
Posted
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.

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.