C言語でのHTTPサーバーでPOSTリクエストのファイルアップロードが正しく処理されない

C

1#include <stdio.h>2#include <stdlib.h>3#include <string.h>4#include <unistd.h>5#include <sys/socket.h>6#include <netinet/in.h>7#include <arpa/inet.h>8#include <fcntl.h>9#include <errno.h>10#include <sys/stat.h>11#include <sys/types.h>12#include <sys/wait.h>13 14#define PORT 808015#define BUFSIZE 819216 17void error(const char *msg) {18 perror(msg);19 exit(1);20}21 22void handle_request(int newsockfd) {23 char buffer[BUFSIZE];24 int n;25 char boundary[256];26 27 // Read the initial request into the buffer28 n = read(newsockfd, buffer, BUFSIZE - 1);29 if (n < 0) error("ERROR reading from socket");30 buffer[n] = 0;31 32 printf("Here is the message: %s\n", buffer);33 34 if (strncmp(buffer, "GET ", 4) == 0) {35 // Handle GET request36 char *filepath = strtok(buffer + 4, " ");37 if (strcmp(filepath, "/") == 0) {38 filepath = "/index.html";39 }40 41 char fullpath[BUFSIZE] = ".";42 strncat(fullpath, filepath, BUFSIZE - strlen(fullpath) - 1);43 44 int filefd = open(fullpath, O_RDONLY);45 if (filefd < 0) {46 char *not_found = "HTTP/1.1 404 Not Found\r\nContent-Length: 13\r\n\r\n404 Not Found";47 write(newsockfd, not_found, strlen(not_found));48 } else {49 char response[BUFSIZE];50 sprintf(response, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");51 write(newsockfd, response, strlen(response));52 53 while ((n = read(filefd, buffer, BUFSIZE)) > 0) {54 write(newsockfd, buffer, n);55 }56 close(filefd);57 }58 } else if (strncmp(buffer, "POST ", 5) == 0) {59 // Handle POST request60 char *content_length_str = strstr(buffer, "Content-Length: ");61 int content_length = 0;62 if (content_length_str) {63 sscanf(content_length_str, "Content-Length: %d", &content_length);64 }65 66 char *content_type_str = strstr(buffer, "Content-Type: multipart/form-data; boundary=");67 if (content_type_str) {68 sscanf(content_type_str, "Content-Type: multipart/form-data; boundary=%s", boundary);69 }70 71 // Read the remaining data of the request72 if (n < content_length) {73 int remaining = content_length - n;74 char *full_request = malloc(content_length + 1);75 memcpy(full_request, buffer, n);76 int read_bytes = read(newsockfd, full_request + n, remaining);77 if (read_bytes < 0) {78 error("ERROR reading remaining bytes from socket");79 }80 full_request[content_length] = 0;81 strcpy(buffer, full_request);82 free(full_request);83 }84 85 char *part_start = strstr(buffer, boundary);86 if (part_start) {87 part_start += strlen(boundary) + 2; // Skip boundary and \r\n88 89 while (part_start && *part_start != '-' && *part_start != 0) {90 char *header_end = strstr(part_start, "\r\n\r\n");91 if (header_end) {92 header_end += 4; // Skip past \r\n\r\n93 94 char *part_end = strstr(header_end, boundary);95 if (part_end) {96 part_end -= 2; // Exclude trailing \r\n97 98 // Check for Content-Disposition header with filename99 char *content_disposition = strstr(part_start, "Content-Disposition: ");100 if (content_disposition && strstr(content_disposition, "filename=")) {101 size_t data_length = part_end - header_end;102 if (data_length > 0) {103 FILE *file = fopen("upload.jpg", "wb");104 if (file) {105 fwrite(header_end, 1, data_length, file);106 fclose(file);107 108 char *ok_response = "HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nOK";109 write(newsockfd, ok_response, strlen(ok_response));110 } else {111 char *internal_error = "HTTP/1.1 500 Internal Server Error\r\nContent-Length: 21\r\n\r\n500 Internal Server Error";112 write(newsockfd, internal_error, strlen(internal_error));113 }114 } else {115 char *bad_request = "HTTP/1.1 400 Bad Request\r\nContent-Length: 27\r\n\r\n400 Bad Request: No file data";116 write(newsockfd, bad_request, strlen(bad_request));117 }118 }119 120 part_start = part_end + strlen(boundary) + 2; // Skip past boundary and \r\n121 } else {122 break;123 }124 } else {125 break;126 }127 }128 } else {129 char *bad_request = "HTTP/1.1 400 Bad Request\r\nContent-Length: 15\r\n\r\n400 Bad Request";130 write(newsockfd, bad_request, strlen(bad_request));131 }132 } else {133 char *bad_request = "HTTP/1.1 400 Bad Request\r\nContent-Length: 15\r\n\r\n400 Bad Request";134 write(newsockfd, bad_request, strlen(bad_request));135 }136}137 138int main() {139 int server_fd, new_socket;140 struct sockaddr_in address;141 int addrlen = sizeof(address);142 143 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {144 perror("Socket creation failed");145 exit(EXIT_FAILURE);146 }147 148 address.sin_family = AF_INET;149 address.sin_addr.s_addr = INADDR_ANY;150 address.sin_port = htons(PORT);151 152 if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {153 perror("Bind failed");154 close(server_fd);155 exit(EXIT_FAILURE);156 }157 158 if (listen(server_fd, 10) < 0) {159 perror("Listen failed");160 close(server_fd);161 exit(EXIT_FAILURE);162 }163 164 printf("Server is listening on port 8080\n");165 166 while (1) {167 printf("Waiting for connections...\n");168 169 if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {170 perror("Accept failed");171 continue;172 }173 174 pid_t pid = fork();175 if (pid < 0) {176 perror("Fork failed");177 close(new_socket);178 continue;179 }180 181 if (pid == 0) {182 close(server_fd);183 handle_request(new_socket);184 exit(0);185 } else {186 close(new_socket);187 waitpid(-1, NULL, WNOHANG); // Prevent zombie processes188 }189 }190 191 close(server_fd);192 return 0;193}194

コメントを投稿

0 コメント