Server displaying text instead of HTML - html

I'm attempting to make a C server that will take inputs and be able to spit them back out to the user via html format where the server works as a user interface. My current issue I cant seem to figure out is why the C server spits out the HTML code as text at localhost:3838 instead of displaying it as a proper web page.
How can I solve this and have it be able to work to send user commands back to the server and spit out the proper response? Do I do this by using recieve and then putting the message into a buffer, parsing that message, and then putting that response into a buffer to send back using send?
CSERVER.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define PORT "3838" //port being connected to
#define MAXLEN 800
#define BACKLOG 10 //number of pending connections to be held in queue
//format of html page
char header []=
"<!DOCTYPE html>\n"
"<html>\n"
"<head>\n"
"<title>Web-Based Remote Command Server</title>\n"
"</head>\n"
"<body>\n\n";
char input []=
"<form action= \"/run\" method= \"get\"> \n"
"Command: <input type=\"text\" size=\"100\" name=\"command\">\n"
"<input type=\"submit\" value=\"Run\">\n"
"</form>";
char output []= "<p>Command that was run:</p>\n"
"<pre>Your server will include the command that was just run here.</pre>\n\n"
"<p>Standard Output:</p>\n""<pre>Your server will include the stdout results here.</pre>\n\n"
"<p>Standard Error:</p>\n"
"<pre>Your server will include the stderr results here.</pre>\n\n"
"</body>\n""</html>";
char *buff = header;
void sigchld_handler(int s)
{
(void)s; // quiet unused variable warning
// waitpid() might overwrite errno, so we save and restore it:
int saved_errno = errno;
while(waitpid(-1, NULL, WNOHANG) > 0);
errno = saved_errno;
}
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main (void){
int sockfd;
int new_fd;
struct addrinfo hints;
struct addrinfo *serverinfo;
struct addrinfo *p;
struct sockaddr_storage client_addr;
socklen_t addrsize;
struct sigaction sa;
int yes = 1;
char s[INET6_ADDRSTRLEN];
int status;
memset(&hints, 0, sizeof hints); //makes struct empty
hints.ai_family = AF_UNSPEC; //IPv4 or v6
hints.ai_socktype = SOCK_STREAM; //TCP type need
hints.ai_flags = AI_PASSIVE; //Fill in IP for us
//if can't get address info print error
if((status = getaddrinfo(NULL, PORT, &hints, &serverinfo)) != 0){
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 1;
}
for(p = serverinfo; p != NULL; p = p->ai_next){
if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
perror("server: socket");
continue;
}
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
perror("setsockopt");
exit(1);
}
if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1){
close(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(serverinfo);
if(p == NULL){
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
if(listen(sockfd, BACKLOG) == -1){
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections....\n");
while(1){
addrsize = sizeof client_addr;
new_fd = accept(sockfd, (struct sockaddr *)&client_addr, &addrsize);
if(new_fd == -1){
perror("Did not accept");
continue;
}
inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), s, sizeof s);
printf("server: got connection from %s\n", s);
if(!fork()){
close(sockfd);
int bufsize = 1024;
char *buffer = malloc(bufsize);
recv(new_fd, buffer, bufsize, 0);
write(new_fd, "HTTP/1.1 200 OK\n", 16);
write(new_fd, "Content-length: 46\n", 19);
write(new_fd, "Content-type: text/html\n\n", 25);
write(new_fd, "<html><head>\n<title>The Web Page</title>\n</head>\n</html>", 46);
if(send(new_fd, header, MAXLEN, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd);
}
return 0;
}

You need to add the response headers like this one :
for example the response header send by SO for this page is:
HTTP/2.0 200 OK
cache-control: private
content-type: text/html; charset=utf-8
content-encoding: gzip
x-frame-options: SAMEORIGIN
x-request-guid: 599a5768-3cc6-4b94-86e1-e1d1daa8acd5
strict-transport-security: max-age=15552000
content-security-policy: upgrade-insecure-requests
accept-ranges: bytes
date: Tue, 07 May 2019 13:17:15 GMT
via: 1.1 varnish
x-served-by: cache-lcy19237-LCY
x-cache: MISS
x-cache-hits: 0
x-timer: S1557235035.073229,VS0,VE89
vary: Accept-Encoding,Fastly-SSL
x-dns-prefetch-control: off
content-length: 35669
X-Firefox-Spdy: h2

Related

How to get the URL from a localhost server without using libcurl

I've made a custom HTTP server that serves an HTML page with some text, an input text box for entering a command, and a submit button. Upon receiving a form submission, the server is supposed to run the given command and serve a response containing the results.
The issue I cant quite figure out is how to get the URLs of form submission requests so as to parse out the command to run. As presently implemented, the server runs on localhost:3838, and when the client browses to that URL the server responds correctly with the form. When the user enters (say) the command ls in the text box and clicks the "run" submission button, a request is issued to localhost:3838/run?command=ls. How can I obtain that URL in the server, so as to parse out and execute the command?
Here's the present server code:
CwebServer.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define PORT "3838" //port being connected to
#define MAXLEN 800
#define BACKLOG 10 //number of pending connections to be held in queue
//format of html page
char header []=
"HTTP/1.1 200 Ok\r\n"
"Content-Type: text/html; charset=UTF-8\r\n\r\n"
"<!DOCTYPE html>\r\n"
"<html>\n"
"<head>\n"
"<title>Web-Based Remote Command Server</title>\r\n"
"</head>\n"
"<body>\n\n";
char input []=
"<form action= \"/run\" method= \"GET\"> \n"
"Command: <input type=\"text\" size=\"100\" name=\"command\">\n"
"<input type=\"submit\" value=\"Run\">\n"
"</form>";
char output []=
"<p>Command that was run and testing this:</p>\n"
"<pre>Your server will include the command that was just run here.</pre>\n\n"
"<p>Standard Output:</p>\n""<pre>Your server will include the stdout results here.</pre>\n\n"
"<p>Standard Error:</p>\n"
"<pre>Your server will include the stderr results here.</pre>\r\n\r\n"
"</body>\r\n""</html>\r\n";
char *buff = header;
void sigchld_handler(int s)
{
(void)s; // quiet unused variable warning
// waitpid() might overwrite errno, so we save and restore it:
int saved_errno = errno;
while(waitpid(-1, NULL, WNOHANG) > 0);
errno = saved_errno;
}
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main (void){
int sockfd;
int new_fd;
struct addrinfo hints;
struct addrinfo *serverinfo;
struct addrinfo *p;
struct sockaddr_storage client_addr;
socklen_t addrsize;
struct sigaction sa;
int yes = 1;
char s[INET6_ADDRSTRLEN];
int status;
memset(&hints, 0, sizeof hints); //makes struct empty
hints.ai_family = AF_UNSPEC; //IPv4 or v6
hints.ai_socktype = SOCK_STREAM; //TCP type need
hints.ai_flags = AI_PASSIVE; //Fill in IP for us
//if can't get address info print error
if((status = getaddrinfo(NULL, PORT, &hints, &serverinfo)) != 0){
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 1;
}
for(p = serverinfo; p != NULL; p = p->ai_next){
if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
perror("server: socket");
continue;
}
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
perror("setsockopt");
exit(1);
}
if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1){
close(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(serverinfo);
if(p == NULL){
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
if(listen(sockfd, BACKLOG) == -1){
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections....\n");
while(1){
addrsize = sizeof client_addr;
new_fd = accept(sockfd, (struct sockaddr *)&client_addr, &addrsize);
if(new_fd == -1){
perror("Did not accept");
continue;
}
inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), s, sizeof s);
printf("server: got connection from %s\n", s);
if(!fork()){
close(sockfd);
int bufsize = 1024;
char *buffer = malloc(bufsize);
send(new_fd, header, bufsize, 0);
//write(new_fd, "HTTP/1.1 200 OK\n", 16);
//write(new_fd, "Content-length: 46\n", 19);
//write(new_fd, "Content-type: text/html\n\n", 25);
//write(new_fd, "<html><head>\n<head>\n<title>The CAvengers Web Page</title>\n</head>\n</html>", 46);
if(send(new_fd, buffer, MAXLEN, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd);
}
return 0;
}
Web servers and clients communicate via the HTTP protocol. That's what makes them web servers as opposed to some other kind. HTTP is a request / response protocol: the client sends a request to the server that contains information about what it's requesting, and the server processes that request to determine how to respond.
Your particular server seems to intend to implement HTTP 1.1. This is not the most recent version of the protocol, but that's ok. Pretty much every HTTP client in the world understands that dialect. But yours is a pretty minimally-functioning server, responding to every established connection with the same HTTP response, even if the client does not actually send an HTTP request.
Your question is how to get the request URI. The answer is to read it from the client, via the connected socket returned by accept(). The read() or recv() function would be appropos for that. The format you should expect the client to use is described in the HTTP specifications I linked above, but in very brief, you should expect the request to start with the request method name (GET), at least one space, the request URI, and a carriage-return / linefeed pair. You will need to parse the request URI to distinguish between an initial request for the form and a form submission, and in the latter case you will be able to parse the query parameters as well.
DO NOTE, however, that although HTTP is a comparatively simple protocol, it is still much more complicated than I've just described.

C program giving weird output from HTML GET input and prints at bottom of HTML page

I made a C webserver that is able to display an HTML page and then take input from a text box. So far it works to display basic commands like ls but for some reason when i enter into the text box the command ls -l | wc -l it will only act as if i typed in ls -l | w and wont process the command because of this. Based on how im tokenizing i dont understand why it wont go past this line? In the textbox that ends up being the input it comes as ls+-l+%7C+wc+-l which is why i had to separate it in this way. Also my output displays at the bottom of the html page, how can i place it in the correct output areas?
Server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <poll.h>
#define PORT "3838" //port being connected to
#define MAXLEN 800
#define BACKLOG 10 //number of pending connections to be held in queue
//format of html page
char header []=
"HTTP/1.1 200 Ok\r\n"
"Content-Type: text/html; charset=UTF-8\r\n\r\n"
"<!DOCTYPE html>\r\n"
"<html>\n"
"<head>\n"
"<title>Web-Based Remote Command Server</title>\r\n"
"</head>\n"
"<body>\n\n";
char input []=
"<form action= \"/run\" method= \"GET\"> \n"
"Command: <input type=\"text\" size=\"100\" name=\"command\">\n"
"<input type=\"submit\" value=\"Run\">\n"
"</form>";
char output []=
"<p>Command that was run and testing this:</p>\n"
"<pre>Your server will include the command that was just run here.</pre>\n\n"
"<p>Standard Output:</p>\n""<pre>Your server will include the stdout results here.</pre>\n\n";
char outputerr[]=
"<p>Standard Error:</p>\n"
"<pre>Your server will include the stderr results here.</pre>\r\n\r\n"
"</body>\r\n""</html>\r\n";
char *buff = header;
void sigchld_handler(int s)
{
(void)s; // quiet unused variable warning
// waitpid() might overwrite errno, so we save and restore it:
int saved_errno = errno;
while(waitpid(-1, NULL, WNOHANG) > 0);
errno = saved_errno;
}
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
char *parse(char *command){
char * newCommand = (char *) malloc(sizeof(char)*50);
int tgt = 0;
newCommand = strtok(command, " ");
//printf("%s\n", newCommand);
newCommand = strtok(NULL, "/run?command= ");
//printf("%s\n", newCommand);
for(int src = 0; src< strlen(newCommand); src++){
if(newCommand[src] == '+')
{
newCommand[src] = ' ';
}
else if(newCommand[src] == '%')
{
newCommand[src] = ' ';
}
else if(newCommand[src] == '7')
{
newCommand[src] = ' ';
}
else if(newCommand[src] == 'C')
{
newCommand[src] = '|';
}
}
return newCommand;
}
char * execution(char *command){
//printf("yo:%s\n",command );
int piper[2];
size_t len = 0;
pipe(piper);
char* output = malloc(1000 * sizeof(char));
memset(output, '\0', 1000* sizeof(char));
pid_t pid = fork();
if(pid != 0)// parent
{
wait(NULL);
close(piper[1]);
int n = sizeof(output);
struct pollfd * poll_fd = malloc(sizeof(struct pollfd));
poll_fd->fd = piper[0];
poll_fd->events = POLLIN;
//wait(NULL);
//printf("done\n");
//printf("AAA %s", output);
if(poll(poll_fd, 1, 0) == 1){ // pipe data check
read(piper[0], output, 1000);
}
//printf("the command is %s\n", output);
//read(&output,output, piper[0]);
// printf("%s\n",piper[0]);
// dup2(piper[1],1);
// close(0)
}
else{
//dup2(piper[1], 1);
//printf("run : %s", command);
close(1);
dup(piper[1]);
//close(0);
execlp(command, command, NULL);
exit(1);
}
// dup2 execute and print it out in parent
// if(*(commands+1)!=NULL) // redirect stdout as long as were not at the last row
// {
// dup2(piper[1],1);
// close(piper[0]);
// }
return output;
}
int main (void){
int sockfd;
int new_fd;
struct addrinfo hints;
struct addrinfo *serverinfo;
struct addrinfo *p;
struct sockaddr_storage client_addr;
socklen_t addrsize;
struct sigaction sa;
int yes = 1;
char s[INET6_ADDRSTRLEN];
int status;
memset(&hints, 0, sizeof hints); //makes struct empty
hints.ai_family = AF_UNSPEC; //IPv4 or v6
hints.ai_socktype = SOCK_STREAM; //TCP type need
hints.ai_flags = AI_PASSIVE; //Fill in IP for us
//if can't get address info print error
if((status = getaddrinfo(NULL, PORT, &hints, &serverinfo)) != 0){
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 1;
}
for(p = serverinfo; p != NULL; p = p->ai_next){
if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
perror("server: socket");
continue;
}
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
perror("setsockopt");
exit(1);
}
if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1){
close(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(serverinfo);
if(p == NULL){
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
if(listen(sockfd, BACKLOG) == -1){
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections....\n");
while(1){
addrsize = sizeof client_addr;
new_fd = accept(sockfd, (struct sockaddr *)&client_addr, &addrsize);
if(new_fd == -1){
perror("Did not accept");
continue;
}
inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), s, sizeof s);
printf("server: got connection from %s\n", s);
if(!fork()){
close(sockfd);
int bufsize = 1024;
char *buffer = malloc(bufsize);
recv(new_fd, buffer, bufsize, 0);
send(new_fd, header, bufsize, 0);
//printf("%s\n", buffer);
//printf("%s\n", parse(buffer));
//printf("%s\n", execution(parse(buffer)));
//int length = strlen(output);
//output [length + 1] = execution(parse(buffer));
//write(new_fd, "HTTP/1.1 200 OK\n", 16);
//write(new_fd, "Content-length: 46\n", 19);
//write(new_fd, "Content-type: text/html\n\n", 25);
//write(new_fd, "<html><head>\n<head>\n<title>The CAvengers Web Page</title>\n</head>\n</html>", 46);
if(send(new_fd, execution(parse(buffer)), 1000, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd);
}
return 0;
}

C:HTTP webserver - the image "http://localhost.... cannot be displayed because it contains errors

It's my first time dabbling with socket programming and I stumbled upon this amazing code from https://dzone.com/articles/web-server-c.
WHAT WE NEED TO DO: implement a simple HTTP web server that uses the web browser(input from the user) as a client
Here it is:
/*
* WebServer.c
*
* Created on: Nov 3, 2012
* Author: pavithra
*
* A web server in C language using only the standard libraries.
* The port number is passed as an argument.
*
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#define EOL "\r\n"
#define EOL_SIZE 2
typedef struct {
char *ext;
char *mediatype;
} extn;
//Possible media types
extn extensions[] ={
{"gif", "image/gif" },
{"txt", "text/plain" },
{"jpg", "image/jpg" },
{"jpeg","image/jpeg"},
{"png", "image/png" },
{"ico", "image/ico" },
{"zip", "image/zip" },
{"gz", "image/gz" },
{"tar", "image/tar" },
{"htm", "text/html" },
{"html","text/html" },
{"php", "text/html" },
{"pdf","application/pdf"},
{"zip","application/octet-stream"},
{"rar","application/octet-stream"},
{0,0} };
//find webroot, add design
/*
A helper function
*/
void error(const char *msg) {
perror(msg);
exit(1);
}
/*
A helper function
*/
int get_file_size(int fd) {
struct stat stat_struct;
if (fstat(fd, &stat_struct) == -1)
return (1);
return (int) stat_struct.st_size;
}
/*
A helper function
*/
void send_new(int fd, char *msg) {
int len = strlen(msg);
if (send(fd, msg, len, 0) == -1) {
printf("Error in send\n");
}
}
/*
This function recieves the buffer
until an "End of line(EOL)" byte is recieved
*/
int recv_new(int fd, char *buffer) {
char *p = buffer; // Use of a pointer to the buffer rather than dealing with the buffer directly
int eol_matched = 0; // Use to check whether the recieved byte is matched with the buffer byte or not
while (recv(fd, p, 1, 0) != 0) // Start receiving 1 byte at a time
{
if (*p == EOL[eol_matched]) // if the byte matches with the first eol byte that is '\r'
{
++eol_matched;
if (eol_matched == EOL_SIZE) // if both the bytes matches with the EOL
{
*(p + 1 - EOL_SIZE) = '\0'; // End the string
return (strlen(buffer)); // Return the bytes recieved
}
} else {
eol_matched = 0;
}
p++; // Increment the pointer to receive next byte
}
return (0);
}
/*
A helper function: Returns the
web root location.
*/
char* webroot() {
// open the file "kill.txt" for reading
FILE *in = fopen("kill.txt", "rt");
// read the first line from the file
char buff[1000];
fgets(buff, 1000, in);
// close the stream
fclose(in);
char* nl_ptr = strrchr(buff, '\n');
if (nl_ptr != NULL)
*nl_ptr = '\0';
return strdup(buff);
}
/*
Handles php requests
*/
void php_cgi(char* script_path, int fd) {
send_new(fd, "HTTP/1.1 200 OK\n Server: Web Server in C\n Connection: close\n");
dup2(fd, STDOUT_FILENO);
char script[500];
strcpy(script, "SCRIPT_FILENAME=");
strcat(script, script_path);
putenv("GATEWAY_INTERFACE=CGI/1.1");
putenv(script);
putenv("QUERY_STRING=");
putenv("REQUEST_METHOD=GET");
putenv("REDIRECT_STATUS=true");
putenv("SERVER_PROTOCOL=HTTP/1.1");
putenv("REMOTE_HOST=127.0.0.1");
execl("/usr/bin/php-cgi", "php-cgi", NULL);
}
/*
This function parses the HTTP requests,
arrange resource locations,
check for supported media types,
serves files in a web root,
sends the HTTP error codes.
*/
int connection(int fd) {
char request[500], resource[500], *ptr;
int fd1, length;
if (recv_new(fd, request) == 0) {
printf("Receive Failed\n");
}
printf("%s\n", request);
// Check for a valid browser request
ptr = strstr(request, " HTTP/");
if (ptr == NULL) {
printf("NOT HTTP !\n");
} else {
*ptr = 0;
ptr = NULL;
if (strncmp(request, "GET ", 4) == 0) {
ptr = request + 4;
}
if (ptr == NULL) {
printf("Unknown Request ! \n");
} else {
if (ptr[strlen(ptr) - 1] == '/') {
strcat(ptr, "test.html");
}
strcpy(resource, webroot());
strcat(resource, ptr);
char* s = strchr(ptr, '.');
int i;
for (i = 0; extensions[i].ext != NULL; i++) {
if (strcmp(s + 1, extensions[i].ext) == 0) {
fd1 = open(resource, O_RDONLY, 0);
printf("Opening \"%s\"\n", resource);
if (fd1 == -1) {
printf("404 File not found Error\n");
send_new(fd, "HTTP/1.1 404 Not Found\r\n");
send_new(fd, "Server : Web Server in C\r\n\r\n");
send_new(fd, "<html><head><title>404 Not Found</head></title>");
send_new(fd, "<body><p>404 Not Found: The requested resource could not be found!</p></body></html>\r\n");
//Handling php requests
} else if (strcmp(extensions[i].ext, "php") == 0) {
php_cgi(resource, fd);
sleep(1);
close(fd);
exit(1);
} else {
printf("200 OK, Content-Type: %s\n\n",
extensions[i].mediatype);
send_new(fd, "HTTP/1.1 200 OK\r\n");
send_new(fd, "Server : Web Server in C\r\n\r\n");
if (ptr == request + 4) // if it is a GET request
{
if ((length = get_file_size(fd1)) == -1)
printf("Error in getting size !\n");
size_t total_bytes_sent = 0;
ssize_t bytes_sent;
while (total_bytes_sent < length) {
//Zero copy optimization
if ((bytes_sent = sendfile(fd, fd1, 0,
length - total_bytes_sent)) <= 0) {
if (errno == EINTR || errno == EAGAIN) {
continue;
}
perror("sendfile");
return -1;
}
total_bytes_sent += bytes_sent;
}
//why is it not appearing up to 11:30
}
}
break;
}
int size = sizeof(extensions) / sizeof(extensions[0]);
if (i == size - 2) {
printf("415 Unsupported Media Type\n");
send_new(fd, "HTTP/1.1 415 Unsupported Media Type\r\n");
send_new(fd, "Server : Web Server in C\r\n\r\n");
send_new(fd, "<html><head><title>415 Unsupported Media Type</head></title>");
send_new(fd, "<body><p>415 Unsupported Media Type!</p></body></html>");
}
}
close(fd);
}
}
shutdown(fd, SHUT_RDWR);
}
int main(int argc, char *argv[]) {
int sockfd, newsockfd, portno, pid;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
if (argc < 2) {
fprintf(stderr, "ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd, 5);
clilen = sizeof(cli_addr);
/*
Server runs forever, forking off a separate
process for each connection.
*/
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
pid = fork();
if (pid < 0)
error("ERROR on fork");
if (pid == 0) {
close(sockfd);
connection(newsockfd);
exit(0);
} else
close(newsockfd);
} /* end of while */
close(sockfd);
return 0; /* we never get here */
}
NOTE: the kill.txt contains the directory of the server, the files(jpegs, gifs, etc.: /home/user/Desktop)
PROBLEM:
1. After I compile the program and execute it on my web browser as "localhost:port number/file" this is what appears on my web browser:
the image "http://localhost.... cannot be displayed because it contains errors.
And this is what appears on my terminal:
GET /sample5.gif HTTP/1.1
Opening "/home/user/Desktop/sample5.gif"
200 OK, Content-Type: image/gif
GET /favicon.ico HTTP/1.1
Opening "/home/user/Desktop/favicon.ico"
404 File not found Error
How do I fix this? Any help/comment would be greatly appreciated! Thanks.
Where is that favicon.ico bit coming from? /I looked this up and apparently having that favicon.ico bit is quite normal (can somebody please confirm this?)/
… I stumbled upon this amazing code from …
It is indeed amazing how bad it is.
At the end of the function int connection(int fd) there's:
close(fd);
}
}
shutdown(fd, SHUT_RDWR);
}
Browsers don't like the connection being reset by peer (due to close()) before it's tidily shut down. Move the close() after the shutdown().
The program neglects to reap child processes, thus a zombie process remains after each request. #include <signal.h> and add sigignore(SIGCHLD); at the start of main().
If the action for the SIGCHLD signal is set to SIG_IGN, child
processes of the calling processes will not be transformed into zombie
processes when they terminate.

How do I make cout stop outputting text after the page is full?

I've made a simple web browser using winsock2 and I have it cout the response from the server but it sends sum 21000 bytes and I need to be able to copy and paste the html, javascript, css, etc for testing the gui I made. It always fills up the terminal and I can't see where it starts I just end up in the middle of a lot of javascript. I want it to be like in the cmd where it stops and ask if you want to continue.
#include <windows.h>
#include <winsock2.h>
#include <conio.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#define SCK_VERSION2 0x0202
#define DEFAULT_BUFLEN 21000
#define DEFAULT_PORT 27015
namespace Globals{
string input = "";
char recvbuf[DEFAULT_BUFLEN];
const char* carf = recvbuf;
}
using namespace Globals;
HWND staticText2 = CreateWindowEx(WS_EX_PALETTEWINDOW, TEXT("Static"), TEXT("Email"), /* email */
WS_CHILD | WS_VISIBLE, 122, 80, 44, 20,
/*hwnd*/NULL, NULL, NULL, NULL);
int sck() {
//----------------------
// Declare and initialize variables.
WSADATA wsaData;
int iResult;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;
char name[500] = "";
char ipADDRESS[500] = "";
char sPORT[500] = "";
sockaddr_in sName;
int sNameSize = sizeof(sName);
char const* sendbuf = "GET /?gws_rd=ssl HTTP/1.1\r\n"
"Host: www.google.com:80\r\n"
"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)\r\n"
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
"Accept-Language: en-us,en;q=0.5\r\n"
//"Accept-Encoding: gzip,deflate\r\n"
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
"Keep-Alive: 300\r\n"
"Connection: keep-alive\r\n"
"Pragma: no-cache\r\n"
"DNT: 1"
"Cookie:
"Cookie:
"Cache-Control: no-cache\r\n\r\n";
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN; //23.214.132.132 GoDaddy.com
int WSAERROR = WSAGetLastError(); //190.93.243.15
//system("color 04"); //172.16.100.114 Mrs.Hall
//----------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
//----------------------
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %i\n", WSAGetLastError() );
WSACleanup();
return 1;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
printf("IP ADDRESS: 74.125.196.191 is Google 216.58.208.37 is mail.google.com 129.66.24.10 is iNow\n");
cin >> ipADDRESS;
printf("PORT: \n");
cin >> sPORT;
//system("color 04");
u_short PORT = strtoul(sPORT, NULL, 0);
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr(ipADDRESS); //74.125.196.191
clientService.sin_port = htons(PORT); //135: msrpc, 445: microsoft-ds, 554: rtsp, 1025: NFS-or-IIS, 1026: LSA-or-nterm
//1027: IIS, 1028: uknown, 1029: ms-lsa, 139: weird behavior
//----------------------
// Connect to server.
iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
if ( iResult == SOCKET_ERROR) {
closesocket (ConnectSocket);
printf("Unable to connect to server: %i\n", WSAGetLastError());
WSACleanup();
return 1;
}
//----------------------
//Get local host name
iResult = gethostname(name, sizeof(name));
if (iResult == NO_ERROR) {
printf("Host Name: %s\n", name);
}
else if (iResult == SOCKET_ERROR) {
printf("Could not resolve host name: %i", WSAGetLastError());
}
//------------------------
//Get peer name
iResult = getpeername(ConnectSocket, (struct sockaddr*)&sName, &sNameSize);
if (iResult == NO_ERROR)
printf("Peer Name: %s\n", inet_ntoa(sName.sin_addr));
else if (iResult == SOCKET_ERROR)
printf("Could not get peer name: %i\n", WSAGetLastError());
//-------------------------
// Send an initial buffer
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
else
printf("Bytes Sent: %i\n", iResult);
//-----------------------------
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 ) {
printf("Bytes received: %d\n", iResult);
cout << "From Server" << recvbuf << endl;//printf("From server: %s\n", recvbuf);
}
else if ( iResult == 0 )
printf("Connection closed\n");
else if (WSAERROR == WSAETIMEDOUT)
printf("recv failed: WSAETIMEDOUT\n");
} while( iResult > 0 );
// cleanup
closesocket(ConnectSocket);
WSACleanup();
system("PAUSE");
return 0;
}
int main() {
sck();
MessageBox(NULL, "Successful", "Result:", MB_OK);
}
That's my code
Just realized all I have to do is go to the webpage and change the cookie to what I made it in my program using the EditThisCookie plugin, then copy the source. XD

Browser display the image file sent from C server as a long string of characters

I have been working on creating a small C server to which browsers can connect and make "GET" requests for files. I ran the basic structure of the server using the typical "socket", "bind", "listen", and "accept". Then I used the file descriptor "accept" in order to invoke "write" or "send" calls to the client, which makes "GET" requests in the form of
http://ip_address:port/request
The first step I took was reading from the accept_fd (returned by accept) and get the first line of it, which was "GET /request HTTP/1.1\r\n". Then I use this to create a proper HTTP headers to send files over.
GET /image_file.gif HTTP/1.1\r\n
\r\n
HTTP/1.1 200 OK\r\n
Content-Type: image.gif\r\n
Content-Length: 9184\r\n
\r\n
The content length was fetched from the st_size of the file statistics and corresponds to the file I want to send over, so this tells me I am dealing with the right file. I use "fopen" with "r" for reading and store the content with "fread" into a big character array which I made. Then finally, I sent the buffer in which the content of the file is stored using "send" and the client browser receives it, but the contents displayed are some gibberish string of unrecognizable characters (possibly binary).
GIF89awÄ��ëQiò‹›òŒ›øÅÍìRiæ&Cýðòîn‚õ¨´éC\úÓÙè4Pûâæó™§í`uð}Žö¶Àõ©
Here is a snippet of what it looks like on the browser instead of an image file. I have been trying to solve this problem for four days and tried various things like sending each part of the HTTP headers individually instead of sending it all at once, sending the image file one byte at a time using "fgetc" and "write" but none of these attempts succeeded. Is there something wrong with what I am doing to send an image file over? (and the html files too. when I try to send it over, all the tags appear as though it was a text file instead of the browser interpreting and formatting the page.)
#include <arpa/inet.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define STAT_200 " 200 OK\r\n"
#define STAT_404 " 404 Not Found\r\n"
#define STAT_501 " 501 Not Implemented\r\n"
#define F_DIR "Content-Type: text/directory\r\n"
#define F_GIF "Content-Type: image/gif\r\n"
#define F_HTML "Content-Type: text/html\r\n"
#define F_JPEG "Content-Type: image/jpeg\r\n"
#define F_JPG "Content-Type: image/jpg\r\n"
#define F_TXT "Content-Type: text/plain\r\n"
typedef enum {cgi, gif, html, jpeg, jpg, plain} ext;
ext get_ext(char *file) {
if (strstr(file, ".cgi") != NULL)
return cgi;
if (strstr(file, ".gif") != NULL)
return gif;
if (strstr(file, ".html") != NULL)
return html;
if (strstr(file, ".jpeg") != NULL)
return jpeg;
if (strstr(file, ".jpg") != NULL)
return jpg;
if (strstr(file, ".txt") != NULL)
return plain;
}
void parse(int accept_fd) {
char *response = (char *) malloc(sizeof(char) * 512);
char *content = (char *) malloc(sizeof(char) * 512);
if (read(accept_fd, content, 512) < 0) {
perror("read error");
exit(1);
}
char *part_end = strstr(content, "\n");
*(part_end + 1) = 0; // still has \r\n
strcat(response, content);
strcat(response, "\r\n");
// send(accept_fd, content, strlen(content), MSG_CONFIRM);
// send(accept_fd, "\r\n", 2, MSG_CONFIRM); // empty line
*(part_end - 1) = 0; // no more \r\n
char *type = (char *) malloc(sizeof(char) * 256); // "GET"
char *request = (char *) malloc(sizeof(char) * 256); // "/request"
char *version = (char *) malloc(sizeof(char) * 256); // "HTTP/x.x"
strcpy(type, content);
strcpy(request, strstr(content, "/"));
strcpy(version, strstr(content, "HTTP"));
part_end = strstr(type, "/");
*(part_end - 1) = 0;
part_end = strstr(request, "HTTP");
*(part_end - 1) = 0;
strcat(response, version);
// send(accept_fd, version, strlen(version), MSG_CONFIRM); // write the "HTTP/x.x"
if (strcmp(type, "GET") != 0) { // 501
strcat(response, STAT_501);
// send(accept_fd, STAT_501, strlen(STAT_501), MSG_CONFIRM);
}
struct stat f_stat;
int stat_fd;
char *cwd = (char *) malloc(sizeof(char) * 256);
char *f_name = (char *) malloc(sizeof(char) * 256);
if ((cwd = getcwd(cwd, 256)) == NULL) {
perror("getcwd error");
exit(1);
}
strcpy(f_name, cwd);
strcat(f_name, request);
if ((stat_fd = stat(f_name, &f_stat)) < 0) { // 404
strcat(response, STAT_404);
// send(accept_fd, STAT_404, strlen(STAT_404), MSG_CONFIRM);
}
if S_ISDIR(f_stat.st_mode) { // 200
strcat(response, STAT_200);
strcat(response, F_DIR);
strcat(response, "\r\n");
// send(accept_fd, STAT_200, strlen(STAT_200), MSG_CONFIRM); // # stat
// send(accept_fd, "Content-Type: text/directory\r\n", 30, MSG_CONFIRM);
// send(accept_fd, "\r\n", 2, MSG_CONFIRM);
write(accept_fd, response, strlen(response));
int red;
if ((red = dup2(accept_fd, STDOUT_FILENO)) < 0) {
perror("dup error");
exit(1);
}
if (execlp("ls", "ls", f_name, NULL) < 0) {
perror("exec error");
exit(1);
}
close(accept_fd);
exit(0);
} else if S_ISREG(f_stat.st_mode) { // 200
strcat(response, STAT_200);
// send(accept_fd, STAT_200, strlen(STAT_200), MSG_CONFIRM); // # stat
ext f_ext = get_ext(f_name);
if (f_ext == cgi) {
int red;
if ((red = dup2(accept_fd, STDOUT_FILENO)) < 0) {
perror("dup error");
exit(1);
}
if (execlp(f_name, f_name, NULL) < 0) {
perror("exec family error");
exit(1);
}
close(accept_fd);
exit(0);
} else if (f_ext == gif) {
strcat(response, F_GIF);
// send(accept_fd, F_GIF, strlen(F_GIF), MSG_CONFIRM);
FILE *f_open;
char *f_cont = (char *) malloc(sizeof(char) * 524288);
size_t f_size = f_stat.st_size;
char *con_len = (char *) malloc(sizeof(char) * 64);
sprintf(con_len, "Content-Length: %d\r\n\r\n", (int) f_size);
strcat(response, con_len);
write(accept_fd, response, strlen(response));
// send(accept_fd, con_len, strlen(con_len), MSG_CONFIRM); // Content-length: #\r\n
if ((f_open = fopen(f_name, "r")) == NULL) {
perror("fopen error");
exit(1);
}
// int i;
// char ch;
// for (i = 0; i < f_size; i++) {
// ch = fgetc(f_open);
// send(accept_fd, &ch, 1, MSG_CONFIRM);
// }
fread(f_cont, sizeof(char), f_size, f_open);
send(accept_fd, f_cont, f_size, MSG_CONFIRM);
close(accept_fd);
exit(0);
}
Here is the relevant part of the code, and I checked repeatedly whether I missed any \r or \n in the header by checking the string lengths, but no good. People who have experiences with this, can you note where the mistake is? Am I misusing any functions anywhere? I got rid of the part where it sends html files because it failed before so I was mainly working on transferring a gif file over.
It turns out the headers are supposed to start from the third line of what I thought was the correct header. So it should look like this:
HTTP/1.1 200 OK\r\n
Content-Type: text/html\r\n
\r\n
[file content]