-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver-helper.c
More file actions
183 lines (156 loc) · 5.1 KB
/
Copy pathserver-helper.c
File metadata and controls
183 lines (156 loc) · 5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <strings.h>
#include <string.h>
#include <netdb.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#define BUFFER_LEN 4096
#define STATUS_OK 200
#define STATUS_NOT_FOUND 404
#define _XOPEN_SOURCE_EXTENDED 1
// returns the extension of the file
char *fileExtention(char *filepath){
// checks for the last occurence of dot to find the file extn
char *separtor = strrchr(filepath, '.');
if(!separtor || separtor == filepath) return NULL;
return separtor + 1;
}
// returns the mime type of the file extension
char *mimeType(char *extn){
if(extn){
// checks file extn and returns correct type
if (strcmp(extn, "html") == 0)
return "text/html";
if (strcmp(extn, "jpg") == 0)
return "image/jpeg";
if (strcmp(extn, "css") == 0)
return "text/css";
if (strcmp(extn, "js") == 0)
return "application/javascript";
}
// else returns octet-stream for all other types
return "application/octet-stream";
}
// parses the request recieved by the server
int parseReq(int newsockfd, char* filepath, char* rootpath){
// stores the request header
char buffer[BUFFER_LEN];
// stores the size of the request header
int header_size = 0;
// stores the request apart from header
char discard[BUFFER_LEN];
bzero(buffer, BUFFER_LEN);
while(header_size < (BUFFER_LEN-1)) {
// read the request one character at a time to check for 2CRLFs
char ch;
// n is the number of characters read, can be less than 1
int n = recv(newsockfd, &ch, 1, 0);
if (n<=0){
return n;
}
if (ch == '\n'){
break;
}
if (ch == '\r'){
continue;
}
buffer[header_size] = ch;
header_size++;
}
// Null-terminate string
buffer[header_size] = '\0';
// read the rest of the request to be discarded
recv(newsockfd, discard, BUFFER_LEN, 0);
printf("header_size is %d\n",header_size);
printf("%s\n", buffer);
// extracts the http method
char *method;
method = strtok(buffer, " \r\n");
printf("extracting method: %s\n",method);
// exits if the request is not GET
if (strncmp(method, "GET", strlen("GET")) != 0) {
return -1;
}
// extracts file path for a GET request
int filepath_length;
for(filepath_length = 4; filepath_length < header_size; filepath_length++){
if(buffer[filepath_length] == ' '){
break;
}
filepath[filepath_length-4] = buffer[filepath_length];
}
// Null-terminate string
filepath[filepath_length-4] = '\0';
return 1;
}
// sends the appropriate header for a request
void responseHeader(int newsockfd, char *filepath, int status){
char *contentType;
char *statusLine;
// assigns the correct status and content type for a response header
switch (status) {
case 200:
statusLine = "200 OK";
contentType = mimeType(fileExtention(filepath));
break;
case 404:
statusLine = "404 Not Found";
contentType = mimeType("html");
break;
}
// structures the response header
char buffer[BUFFER_LEN];
bzero(buffer, BUFFER_LEN);
snprintf(buffer, BUFFER_LEN, ("HTTP/1.0 %s\r\nContent-Type: %s\r\n\r\n"),statusLine,contentType);
printf("response header: %s", buffer);
// sends the response header using a buffer
char* ch = buffer;
int bufferLen = strlen(buffer);
while(bufferLen > 0){
int n = send(newsockfd, ch, bufferLen,0);
bufferLen -= n;
ch += n;
}
}
// serves the request by adding appropriate response body
// or file contents
void serveReq(int newsockfd, char *root, char *filepath){
// the actual path of the file requested
// rootpath + filepath(url)
char path[BUFFER_LEN];
snprintf(path, sizeof(path), "%s%s",root, filepath);
printf("filepath is %s\n", path);
// searches for the real path of the file
char real_path[BUFFER_LEN];
(void) realpath(path, real_path);
// deals with path escape problem
if ((strncmp(real_path, root, strlen(root))!=0)||
(strncmp(real_path, path, strlen(filepath))!=0)){
responseHeader(newsockfd, path, STATUS_NOT_FOUND);
}
// sending the file content using a buffer
int bytes = 0;
char buffer[BUFFER_LEN];
FILE* file = fopen(path, "r");
// if the file exist, sends the requested file with 200 status
if (file) {
// send response header
responseHeader(newsockfd, path, STATUS_OK);
// handle up to BUFFER_LEN bytes each time
while ((bytes = fread(buffer, sizeof(*buffer), sizeof(buffer), file)) > 0) {
send(newsockfd, buffer, bytes, 0);
}
fclose(file);
}
// file requested doesnt exist, response header sent with 404 status
else{
responseHeader(newsockfd, path, STATUS_NOT_FOUND);
}
}