💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Upload › files › 7eac294ae1907c41c45754a8a6a… captured on 2023-03-20 at 18:34:12. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

0 /* See LICENSE for license details. */

1 #ifdef __FreeBSD__

2 #define __BSD_VISIBLE 1

3 #include <sys/types.h>

4 #include <sys/socket.h>

5 #include <sys/uio.h>

6 #endif

7 #include "server.h"

8 #include "parser.h"

9 #include <stdint.h>

10 #include <stdlib.h>

11 #include <string.h>

12 #include <strings.h>

13 #include <sys/types.h>

14 #include <time.h>

15 #include <unistd.h>

16 #include <fcntl.h>

17 #include <stdio.h>

18 #include <poll.h>

19 #ifdef __sun

20 #include <signal.h>

21 #endif

22 #define _GNU_SOURCE

23 size_t strlcpy(char*, const char*, size_t);

24

25 char header[] =

26 "HTTP/1.0 200 OK\r\n"

27 "Connection: close\r\n"

28 "Content-Length: %d\r\n"

29 "Content-Type: %s\r\n"

30 "Server: uploadservice\r\n\r\n";

31

32 void

33 print_now()

34 {

35 time_t now = time(NULL);

36 struct tm tm = *localtime(&now);

37 printf("[%d/%02d/%02d %02d:%02d:%02d] ",

38 tm.tm_year+1900, tm.tm_mon + 1, tm.tm_mday,

39 tm.tm_hour, tm.tm_min, tm.tm_sec);

40 }

41

42 int listener = 0;

43

44 #include <sys/stat.h>

45 #include <sys/socket.h>

46 #include <netinet/in.h>

47

48 char data_error[] =

49 "<html>\n"

50 "<head>\n"

51 " <title>Fatal error</title>\n"

52 "</head>\n"

53 "<body>\n"

54 " <h1>An error occured</h1>\n"

55 "</body>\n"

56 "</html>\n";

57

58 char data_upload[] =

59 "<html>\n"

60 "<head>\n"

61 " <title>File uploaded</title>\n"

62 "</head>\n"

63 "<body>\n"

64 " <a href=\"/\">Go back</a>\n"

65 " <h1>File succesfully uploaded</h1>\n"

66 " <p>Download link : <a href=\"%s\">%s</a></p>\n"

67 "</body>\n"

68 "</html>\n";

69

70 int

71 path_to_url(const char* path, char* url, int len)

72 {

73 int j = 0;

74 int i = 0;

75 for (; path[i] && j < len; i++) {

76 char c = path[i];

77 if ((c >= 'a' && c <= 'z') ||

78 (c >= 'A' && c <= 'Z') ||

79 (c >= '0' && c <= '9') ||

80 c == '.' || c == '/' || c == '_') {

81 url[j] = path[i];

82 j++;

83 continue;

84 }

85 snprintf(&url[j], len - j, "%%%02X", c);

86 j += 3;

87 }

88 url[j] = '\0';

89 return j;

90 }

91

92 int

93 server_upload(struct http_request* req)

94 {

95 char file_name[256], path[1024], url[2048];

96 char *start, *name_ptr, *slash_ptr;

97 int name_fail, fd, len;

98

99 /* path + name */

100 start = strstr(req->packet, "\r\n\r\n");

101 if (!start) start = req->packet;

102 name_ptr = strstr(start, "filename=\"");

103 name_fail = 1;

104 if (name_ptr) {

105 char* name_end;

106

107 name_ptr += sizeof("filename=\"") - 1;

108 name_end = strstr(name_ptr, "\"\r\n");

109 if (name_end && (size_t)(name_end - name_ptr) <

110 sizeof(file_name)) {

111 strlcpy(file_name, name_ptr, name_end - name_ptr + 1);

112 name_fail = 0;

113 }

114 }

115 if (name_fail)

116 strlcpy(file_name, "generic.dat", sizeof(file_name));

117 snprintf(path, sizeof(path), "/download/%08X%08X/%s",

118 (unsigned)(rand() * rand() + rand()),

119 (unsigned)(rand() * rand() - rand()), file_name);

120

121 start = strstr(start+4, "\r\n\r\n");

122 if (!start) start = req->content;

123 slash_ptr = strrchr(path, '/');

124 if (!slash_ptr) return -1;

125 *slash_ptr = '\0';

126 mkdir(&path[1], 0700);

127 *slash_ptr = '/';

128 fd = open((char*)&path[1], O_RDWR|O_CREAT, 0600);

129 if (fd < 0)

130 return -1;

131 req->data = fd;

132 path_to_url(path, url, sizeof(url));

133 len = snprintf(req->updata, sizeof(req->updata),

134 data_upload, url, file_name);

135 snprintf(req->header, sizeof(req->header), header, len, "text/html");

136 http_parse(req);

137 return 0;

138 }

139

140 int

141 server_init(int port)

142 {

143 #ifdef DEBUG

144 struct linger sl;

145 #endif

146 struct sockaddr_in addr;

147 listener = socket(AF_INET, SOCK_STREAM, 0);

148 if (listener == -1) {

149 printf("Failed to create socket\n");

150 return -1;

151 }

152 #ifdef DEBUG

153 /* instant reset, useful for testing */

154 sl.l_onoff = 1;

155 sl.l_linger = 0;

156 setsockopt(listener, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl));

157 #endif

158 #ifdef __sun

159 signal(SIGPIPE, SIG_IGN);

160 #endif

161

162 memset(&addr, 0, sizeof(addr));

163 addr.sin_family = AF_INET;

164 addr.sin_addr.s_addr = htonl(INADDR_ANY);

165 addr.sin_port = htons(port);

166 if (bind(listener, (struct sockaddr*)&addr, sizeof(addr))) {

167 printf("Failed to bind socket on port %d\n", port);

168 return -1;

169 }

170 if (listen(listener, 5)) {

171 printf("Failed to listen on port %d\n", port);

172 return -1;

173 }

174 print_now();

175 printf("Listening on port %d\n", port);

176 fflush(stdout); /* to print log in sfm on illumos */

177 return 0;

178 }

179

180 int

181 server_accept(struct http_request* req)

182 {

183 unsigned int len;

184 int socket;

185

186 memset(req, 0, sizeof(struct http_request));

187 req->data = -1;

188 len = sizeof(req->addr);

189 socket = accept(listener, (struct sockaddr*)&req->addr, &len);

190 if (socket == -1) {

191 printf("Failed to accept socket\n");

192 return -1;

193 }

194 req->socket = socket;

195 return 0;

196 }

197

198 int

199 server_recv(struct http_request* req)

200 {

201 char *data_ptr, *end;

202 int bytes, blen;

203

204 bytes = recv(req->socket,

205 (req->data > -1) ? req->packet : &req->packet[req->size],

206 (req->data > -1) ? sizeof(req->packet):

207 (sizeof(req->packet) - req->size), 0);

208 if (bytes <= 0) return -1;

209 if (!req->boundary_found) {

210 char* ptr = strstr(&req->packet[req->size], "boundary=");

211 if (ptr) {

212 char* start = ptr + sizeof("boundary=");

213 ptr = start;

214 while (ptr++ && *ptr != '\r');

215 strlcpy(req->boundary, start, ptr - start);

216 req->boundary_found = 1;

217 }

218 }

219 req->size += bytes;

220 data_ptr = req->packet;

221 end = NULL;

222 blen = 0;

223 if (req->boundary_found)

224 blen = strnlen(req->boundary, sizeof(req->boundary));

225 while (req->data < 0 && req->boundary_found) {

226 char* ptr = strstr(req->packet, req->boundary);

227 if (!ptr) break;

228 ptr = strstr(ptr + blen, req->boundary);

229 if (!ptr) break;

230 req->content = ptr + strnlen(req->boundary,

231 sizeof(req->boundary));

232 req->length = req->size - (req->content - req->packet);

233 server_upload(req);

234 end = strstr(req->packet + req->size - blen - 8,

235 req->boundary);

236 data_ptr = strstr(req->content + 4, "\r\n\r\n") + 4;

237 bytes = req->size - (data_ptr - req->packet);

238 break;

239 }

240 if (req->data > -1) {

241 char packet[4096];

242 size_t size;

243 if (!end && data_ptr == req->packet)

244 end = strstr(data_ptr + bytes - blen - 8,

245 req->boundary);

246 write(req->data, data_ptr,

247 end?(end - data_ptr - 4):bytes);

248 if (!end) return 1;

249 size = snprintf(packet, sizeof(packet), "%s%s",

250 req->header, req->updata);

251 bytes = 0;

252 while ((size_t)bytes < size) {

253 int ret = send(req->socket, &packet[bytes],

254 size - bytes, 0);

255 if (ret <= 0) break;

256 bytes += ret;

257 }

258 return 2;

259 }

260 if (!req->boundary_found &&

261 req->packet[req->size - 1] == '\n' &&

262 req->packet[req->size - 2] == '\r' &&

263 req->packet[req->size - 3] == '\n' &&

264 req->packet[req->size - 4] == '\r') {

265 return 0;

266 }

267 return 1;

268 }

269

270 #define MAX_REQUESTS 1024

271 #define TIMEOUT_SINCE_STARTED 1200000

272 #define TIMEOUT_SINCE_LAST 10000

273 struct http_request requests[MAX_REQUESTS];

274 struct pollfd fds[MAX_REQUESTS];

275 size_t requests_count = 0;

276

277 int

278 new_request()

279 {

280 int new = 1;

281 size_t i = 0;

282 time_t now = time(NULL);

283 for (; i < requests_count; i++) {

284 if (requests[i].done ||

285 now - requests[i].started >= TIMEOUT_SINCE_STARTED ||

286 now - requests[i].last >= TIMEOUT_SINCE_LAST) {

287 new = 0;

288 break;

289 }

290 }

291 if (new && i >= sizeof(requests)/sizeof(struct http_request) - 1)

292 return -1;

293 if (server_accept(&requests[i]))

294 return -1;

295 fds[i + 1].fd = requests[i].socket;

296 fds[i + 1].events = POLLIN;

297 requests[i].last = requests[i].started = time(NULL);

298 if (new)

299 requests_count++;

300 return 0;

301 }

302

303 void

304 print_req(struct http_request* req, int code)

305 {

306 uint8_t *ptr;

307 print_now();

308 ptr = (uint8_t*)&req->addr.sin_addr.s_addr;

309 printf("%d.%d.%d.%d, requested [%d]\n",

310 ptr[0], ptr[1], ptr[2], ptr[3], code);

311 fflush(stdout); /* to print log in sfm on illumos */

312 }

313

314 int

315 server_serve(struct http_request* req)

316 {

317 char packet[4096];

318 size_t l;

319

320 memset(packet, 0, sizeof(packet));

321 l = snprintf(packet, sizeof(packet),

322 header, sizeof(data_error) - 1, "text/html");

323 if (l >= sizeof(packet)) {

324 printf("packet buffer overflowing");

325 return -1;

326 }

327 l += strlcpy(&packet[l], data_error, sizeof(packet) - l);

328 send(req->socket, packet, l + 1, 0);

329 return 404;

330 }

331

332 int

333 server_thread()

334 {

335 size_t i;

336 memset(requests, 0, sizeof(requests));

337 for (i = 1; i < sizeof(fds)/sizeof(struct pollfd); i++) {

338 fds[i].fd = -1;

339 fds[i].events = POLLIN;

340 }

341 fds[0].fd = listener;

342 fds[0].events = POLLIN;

343 while (1) {

344 int nfds, ready;

345 size_t i;

346

347 nfds = requests_count + 1;

348 ready = poll(fds, nfds, -1);

349 if (ready == -1) break;

350 if (fds[0].revents == POLLIN && new_request()) {

351 print_now();

352 printf("Failed to accept client\n");

353 fflush(stdout);

354 }

355 for (i = 0; i < requests_count; i++) {

356 int ret = 0;

357 struct http_request* req = &requests[i];

358 switch (fds[i + 1].revents) {

359 case 0:

360 break;

361 case POLLOUT:

362 goto clean;

363 case POLLIN:

364 requests[i].last = time(NULL);

365 ret = server_recv(req);

366 if (ret == 1) continue;

367 if (ret == 2) print_req(req, 200);

368 if (ret == 0) {

369 if (req->data > -1) {

370 close(req->data);

371 req->data = -1;

372 }

373 http_parse(req);

374 print_req(req, server_serve(req));

375 if (req->data > -1) {

376 fds[i + 1].events = POLLOUT;

377 break;

378 }

379 }

380 clean:

381 if (req->data > -1) {

382 close(req->data);

383 req->data = -1;

384 }

385

386 close(req->socket);

387 req->socket = -1;

388 req->done = 1;

389 if (i + 1 == requests_count)

390 requests_count--;

391 memset(&fds[i + 1], 0, sizeof(struct pollfd));

392 fds[i + 1].fd = -1;

393 fds[i + 1].events = POLLIN;

394 break;

395 default:

396 fds[i + 1].fd = -1;

397 fds[i + 1].events = POLLIN;

398 }

399 }

400 }

401 return 0;

402 }

403

404 int

405 server_stop()

406 {

407 close(listener);

408 return 0;

409 }

410