WebGet & WebPost Utilities
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

libweb.c 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. /**
  2. * @PROJECT WebGet Downloader
  3. * @COPYRIGHT See COPYING in the top level directory
  4. * @FILE libweb.c
  5. * @PURPOSE Common Web Library
  6. * @DEVELOPERS Al Globus <globus@nas.nasa.gov>
  7. * Rafal Kupiec <belliash@asiotec.eu.org>
  8. * Jef Poskanzer <jef@mail.acme.com>
  9. */
  10. #include <unistd.h>
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <ctype.h>
  15. #include <signal.h>
  16. #include <fcntl.h>
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include <sys/socket.h>
  20. #include <netinet/in.h>
  21. #include <netdb.h>
  22. #include <cyassl/openssl/ssl.h>
  23. #include <cyassl/openssl/err.h>
  24. #include <cyassl/error.h>
  25. #ifdef CROSS_BUILD
  26. #include <cyassl/cyassl_error.h>
  27. #endif
  28. #include "libweb.h"
  29. int b64_encode(unsigned char* ptr, int len, char* space, int size) {
  30. int ptr_idx, space_idx, phase;
  31. char c;
  32. space_idx = 0;
  33. phase = 0;
  34. for(ptr_idx = 0; ptr_idx < len; ++ptr_idx) {
  35. switch(phase) {
  36. case 0:
  37. c = b64_encode_table[ptr[ptr_idx] >> 2];
  38. if(space_idx < size) {
  39. space[space_idx++] = c;
  40. }
  41. c = b64_encode_table[(ptr[ptr_idx] & 0x3) << 4];
  42. if(space_idx < size) {
  43. space[space_idx++] = c;
  44. }
  45. ++phase;
  46. break;
  47. case 1:
  48. space[space_idx - 1] = b64_encode_table[b64_decode_table[(int) ((unsigned char) space[space_idx - 1])] | (ptr[ptr_idx] >> 4)];
  49. c = b64_encode_table[(ptr[ptr_idx] & 0xf) << 2];
  50. if(space_idx < size) {
  51. space[space_idx++] = c;
  52. }
  53. ++phase;
  54. break;
  55. case 2:
  56. space[space_idx - 1] = b64_encode_table[b64_decode_table[(int) ((unsigned char) space[space_idx - 1])] | (ptr[ptr_idx] >> 6)];
  57. c = b64_encode_table[ptr[ptr_idx] & 0x3f];
  58. if(space_idx < size) {
  59. space[space_idx++] = c;
  60. }
  61. phase = 0;
  62. break;
  63. }
  64. }
  65. while(phase++ < 3) {
  66. if(space_idx < size) {
  67. space[space_idx++] = '=';
  68. }
  69. }
  70. return space_idx;
  71. }
  72. void check(void* ptr) {
  73. if(ptr == (void*) 0) {
  74. (void) fprintf(stderr, "%s: out of memory\n", argv0);
  75. exit(1);
  76. }
  77. }
  78. off_t file_bytes(const char* filename) {
  79. struct stat sb;
  80. if(stat(filename, &sb) < 0) {
  81. perror(filename);
  82. exit(1);
  83. }
  84. return sb.st_size;
  85. }
  86. int file_copy(const char* filename, char* buf) {
  87. int fd;
  88. struct stat sb;
  89. off_t bytes;
  90. fd = open(filename, O_RDONLY);
  91. if(fd == -1) {
  92. perror(filename);
  93. exit(-1);
  94. }
  95. if(fstat(fd, &sb) != 0) {
  96. perror(filename);
  97. exit(-1);
  98. }
  99. bytes = sb.st_size;
  100. if(read(fd, buf, bytes) != bytes) {
  101. perror(filename);
  102. exit(-1);
  103. }
  104. (void) close(fd);
  105. return bytes;
  106. }
  107. int getURL(char* url, char* referer, char* user_agent, char* auth_token, int ncookies, char** cookies, char* header_name, char* header_value) {
  108. char* s;
  109. int protocol;
  110. char host[2000];
  111. int host_len;
  112. unsigned short port;
  113. char* file = (char*) 0;
  114. char* http = "http://";
  115. int http_len = strlen( http );
  116. char* https = "https://";
  117. int https_len = strlen( https );
  118. int proto_len;
  119. if(url == (char*) 0) {
  120. (void) fprintf(stderr, "%s: null URL\n", argv0);
  121. exit(1);
  122. }
  123. if(strncmp(http, url, http_len) == 0) {
  124. proto_len = http_len;
  125. protocol = PROTO_HTTP;
  126. } else if(strncmp(https, url, https_len) == 0) {
  127. proto_len = https_len;
  128. protocol = PROTO_HTTPS;
  129. } else {
  130. (void) fprintf(stderr, "%s: non-http URL\n", argv0);
  131. exit(1);
  132. }
  133. for(s = url + proto_len; *s != '\0' && *s != ':' && *s != '/'; ++s);
  134. host_len = s - url;
  135. host_len -= proto_len;
  136. strncpy(host, url + proto_len, host_len);
  137. host[host_len] = '\0';
  138. if(*s == ':') {
  139. port = (unsigned short) atoi(++s);
  140. while(*s != '\0' && *s != '/')
  141. ++s;
  142. } else {
  143. if(protocol == PROTO_HTTPS) {
  144. port = 443;
  145. } else {
  146. port = 80;
  147. }
  148. }
  149. if(*s == '\0') {
  150. file = "/";
  151. } else {
  152. file = s;
  153. }
  154. return getURLbyParts(protocol, host, port, file, referer, user_agent, auth_token, ncookies, cookies, header_name, header_value);
  155. }
  156. int getURLbyParts(int protocol, char* host, unsigned short port, char* file, char* referer, char* user_agent, char* auth_token, int ncookies, char** cookies, char* header_name, char* header_value) {
  157. int sockfd;
  158. SSL_CTX* ssl_ctx = (SSL_CTX*) 0;
  159. SSL* ssl = (SSL*) 0;
  160. char buf[20000];
  161. int i, bytes, b, header_state, status;
  162. (void) alarm(timeout);
  163. sockfd = open_client_socket(host, port);
  164. if(protocol == PROTO_HTTPS) {
  165. int r;
  166. ssl_ctx = SSL_CTX_new(TLSv1_client_method());
  167. SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, 0);
  168. ssl = SSL_new(ssl_ctx);
  169. SSL_set_fd(ssl, sockfd);
  170. r = SSL_connect(ssl);
  171. if(r <= 0) {
  172. (void) fprintf(stderr, "%s: %s - SSL connection failed - %d\n", argv0, url, r);
  173. exit(1);
  174. }
  175. }
  176. (void) alarm(timeout);
  177. bytes = snprintf(buf, sizeof(buf), "GET %s HTTP/1.0\r\n", file);
  178. bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "Host: %s\r\n", host);
  179. if(referer != (char*) 0) {
  180. bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "Referer: %s\r\n", referer);
  181. }
  182. bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "User-Agent: %s\r\n", user_agent);
  183. bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "Accept: */*\r\n");
  184. bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "Accept-Language: en\r\n");
  185. bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "Accept-Charset: iso-8859-1,*,utf-8\r\n");
  186. if(auth_token != (char*) 0) {
  187. char token_buf[1000];
  188. token_buf[b64_encode((unsigned char*) auth_token, strlen( auth_token ), token_buf, sizeof(token_buf))] = '\0';
  189. bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "Authorization: Basic %s\r\n", token_buf);
  190. }
  191. for(i = 0; i < ncookies; ++i) {
  192. bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "Cookie: %s\r\n", cookies[i]);
  193. }
  194. if(header_name != (char*) 0) {
  195. bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "%s: %s\r\n", header_name, header_value);
  196. }
  197. bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "\r\n");
  198. if (protocol == PROTO_HTTPS)
  199. (void) SSL_write(ssl, buf, bytes);
  200. else
  201. (void) write(sockfd, buf, bytes);
  202. (void) alarm(timeout);
  203. header_state = HDST_LINE1_PROTOCOL;
  204. status = 0;
  205. for(;;) {
  206. if(protocol == PROTO_HTTPS) {
  207. bytes = SSL_read(ssl, buf, sizeof(buf));
  208. } else {
  209. bytes = read(sockfd, buf, sizeof(buf));
  210. }
  211. if(bytes <= 0) {
  212. break;
  213. }
  214. for(b = 0; b < bytes; ++b) {
  215. if(verbose) {
  216. (void) write(1, &buf[b], 1);
  217. }
  218. switch(header_state) {
  219. case HDST_LINE1_PROTOCOL:
  220. switch(buf[b]) {
  221. case ' ': case '\t':
  222. header_state = HDST_LINE1_WHITESPACE;
  223. break;
  224. case '\n':
  225. header_state = HDST_LF;
  226. break;
  227. case '\r':
  228. header_state = HDST_CR;
  229. break;
  230. }
  231. break;
  232. case HDST_LINE1_WHITESPACE:
  233. switch(buf[b]) {
  234. case '0':
  235. case '1':
  236. case '2':
  237. case '3':
  238. case '4':
  239. case '5':
  240. case '6':
  241. case '7':
  242. case '8':
  243. case '9':
  244. status = buf[b] - '0';
  245. header_state = HDST_LINE1_STATUS;
  246. break;
  247. case '\n':
  248. header_state = HDST_LF;
  249. break;
  250. case '\r':
  251. header_state = HDST_CR;
  252. break;
  253. default:
  254. header_state = HDST_TEXT;
  255. break;
  256. }
  257. break;
  258. case HDST_LINE1_STATUS:
  259. switch(buf[b]) {
  260. case '0':
  261. case '1':
  262. case '2':
  263. case '3':
  264. case '4':
  265. case '5':
  266. case '6':
  267. case '7':
  268. case '8':
  269. case '9':
  270. status = status * 10 + buf[b] - '0';
  271. break;
  272. case '\n':
  273. header_state = HDST_LF;
  274. break;
  275. case '\r':
  276. header_state = HDST_CR;
  277. break;
  278. default:
  279. header_state = HDST_TEXT;
  280. break;
  281. }
  282. break;
  283. case HDST_BOL:
  284. switch(buf[b]) {
  285. case '\n':
  286. header_state = HDST_LF;
  287. break;
  288. case '\r':
  289. header_state = HDST_CR;
  290. break;
  291. default:
  292. header_state = HDST_TEXT;
  293. break;
  294. }
  295. break;
  296. case HDST_TEXT:
  297. switch(buf[b]) {
  298. case '\n':
  299. header_state = HDST_LF;
  300. break;
  301. case '\r':
  302. header_state = HDST_CR;
  303. break;
  304. }
  305. break;
  306. case HDST_LF:
  307. switch(buf[b]) {
  308. case '\n':
  309. goto end_of_headers;
  310. case '\r':
  311. header_state = HDST_CR;
  312. break;
  313. default:
  314. header_state = HDST_TEXT;
  315. break;
  316. }
  317. break;
  318. case HDST_CR:
  319. switch(buf[b]) {
  320. case '\n':
  321. header_state = HDST_CRLF;
  322. break;
  323. case '\r':
  324. goto end_of_headers;
  325. default:
  326. header_state = HDST_TEXT;
  327. break;
  328. }
  329. break;
  330. case HDST_CRLF:
  331. switch(buf[b]) {
  332. case '\n':
  333. goto end_of_headers;
  334. case '\r':
  335. header_state = HDST_CRLFCR;
  336. break;
  337. default:
  338. header_state = HDST_TEXT;
  339. break;
  340. }
  341. break;
  342. case HDST_CRLFCR:
  343. switch(buf[b]) {
  344. case '\n':
  345. case '\r':
  346. goto end_of_headers;
  347. default:
  348. header_state = HDST_TEXT;
  349. break;
  350. }
  351. break;
  352. }
  353. }
  354. }
  355. end_of_headers:
  356. if(bytes > 0) {
  357. ++b;
  358. (void) write(1, &buf[b], bytes - b);
  359. }
  360. for(;;) {
  361. (void) alarm(timeout);
  362. if(protocol == PROTO_HTTPS) {
  363. bytes = SSL_read(ssl, buf, sizeof(buf));
  364. } else {
  365. bytes = read(sockfd, buf, sizeof(buf));
  366. }
  367. if(bytes == 0) {
  368. break;
  369. }
  370. if(bytes < 0) {
  371. show_error("read");
  372. }
  373. (void) write(1, buf, bytes);
  374. }
  375. if(protocol == PROTO_HTTPS) {
  376. SSL_free(ssl);
  377. SSL_CTX_free(ssl_ctx);
  378. }
  379. (void) close(sockfd);
  380. return status;
  381. }
  382. void* malloc_check(size_t size) {
  383. void* ptr = malloc(size);
  384. check(ptr);
  385. return ptr;
  386. }
  387. int open_client_socket(char* hostname, unsigned short port) {
  388. struct addrinfo hints;
  389. char portstr[10];
  390. int gaierr;
  391. struct addrinfo* ai;
  392. struct addrinfo* ai2;
  393. struct addrinfo* aiv4;
  394. struct addrinfo* aiv6;
  395. struct sockaddr_in6 sa;
  396. int sa_len, sock_family, sock_type, sock_protocol;
  397. int sockfd;
  398. (void) memset((void*) &sa, 0, sizeof(sa));
  399. (void) memset(&hints, 0, sizeof(hints));
  400. hints.ai_family = PF_UNSPEC;
  401. hints.ai_socktype = SOCK_STREAM;
  402. (void) snprintf(portstr, sizeof(portstr), "%d", (int) port);
  403. if((gaierr = getaddrinfo(hostname, portstr, &hints, &ai)) != 0) {
  404. (void) fprintf(stderr, "%s: getaddrinfo %s - %s\n", argv0, hostname, gai_strerror(gaierr));
  405. exit(1);
  406. }
  407. aiv4 = (struct addrinfo*) 0;
  408. aiv6 = (struct addrinfo*) 0;
  409. for(ai2 = ai; ai2 != (struct addrinfo*) 0; ai2 = ai2->ai_next) {
  410. switch(ai2->ai_family) {
  411. case AF_INET:
  412. if(aiv4 == (struct addrinfo*) 0) {
  413. aiv4 = ai2;
  414. }
  415. break;
  416. case AF_INET6:
  417. if(aiv6 == (struct addrinfo*) 0) {
  418. aiv6 = ai2;
  419. }
  420. break;
  421. }
  422. }
  423. if(aiv4 != (struct addrinfo*) 0) {
  424. if(sizeof(sa) < aiv4->ai_addrlen) {
  425. (void) fprintf(stderr, "%s - sockaddr too small (%lu < %lu)\n", hostname, (unsigned long) sizeof(sa), (unsigned long) aiv4->ai_addrlen);
  426. exit(1);
  427. }
  428. sock_family = aiv4->ai_family;
  429. sock_type = aiv4->ai_socktype;
  430. sock_protocol = aiv4->ai_protocol;
  431. sa_len = aiv4->ai_addrlen;
  432. (void) memmove(&sa, aiv4->ai_addr, sa_len);
  433. goto ok;
  434. }
  435. if(aiv6 != (struct addrinfo*) 0) {
  436. if(sizeof(sa) < aiv6->ai_addrlen) {
  437. (void) fprintf(stderr, "%s - sockaddr too small (%lu < %lu)\n", hostname, (unsigned long) sizeof(sa), (unsigned long) aiv6->ai_addrlen);
  438. exit(1);
  439. }
  440. sock_family = aiv6->ai_family;
  441. sock_type = aiv6->ai_socktype;
  442. sock_protocol = aiv6->ai_protocol;
  443. sa_len = aiv6->ai_addrlen;
  444. (void) memmove(&sa, aiv6->ai_addr, sa_len);
  445. goto ok;
  446. }
  447. (void) fprintf(stderr, "%s: no valid address found for host %s\n", argv0, hostname);
  448. exit(1);
  449. ok:
  450. freeaddrinfo(ai);
  451. sockfd = socket(sock_family, sock_type, sock_protocol);
  452. if(sockfd < 0) {
  453. show_error("socket");
  454. }
  455. if(connect(sockfd, (struct sockaddr*) &sa, sa_len) < 0) {
  456. show_error("connect");
  457. }
  458. return sockfd;
  459. }
  460. void postURL(char* url, char* referer, char* user_agent, char* auth_token, int ncookies, char** cookies, char* header_name, char* header_value, char** args, int argc) {
  461. char* s;
  462. int protocol;
  463. char host[2000];
  464. int host_len;
  465. unsigned short port;
  466. char* file = 0;
  467. char* http = "http://";
  468. int http_len = strlen(http);
  469. char* https = "https://";
  470. int https_len = strlen(https);
  471. int proto_len;
  472. if(url == (char*) 0) {
  473. (void) fprintf(stderr, "%s: null URL\n", argv0);
  474. exit(1);
  475. }
  476. if(strncmp(http, url, http_len) == 0) {
  477. proto_len = http_len;
  478. protocol = PROTO_HTTP;
  479. } else if(strncmp(https, url, https_len) == 0) {
  480. proto_len = https_len;
  481. protocol = PROTO_HTTPS;
  482. } else {
  483. (void) fprintf(stderr, "%s: non-http URL\n", argv0);
  484. exit(1);
  485. }
  486. for(s = url + proto_len; *s != '\0' && *s != ':' && *s != '/'; ++s);
  487. host_len = s - url;
  488. host_len -= proto_len;
  489. strncpy(host, url + proto_len, host_len);
  490. host[host_len] = '\0';
  491. if(*s == ':') {
  492. port = (unsigned short) atoi(++s);
  493. while(*s != '\0' && *s != '/') {
  494. ++s;
  495. }
  496. } else {
  497. if(protocol == PROTO_HTTPS) {
  498. port = 443;
  499. } else {
  500. port = 80;
  501. }
  502. }
  503. if(*s == '\0') {
  504. file = "/";
  505. } else {
  506. file = s;
  507. }
  508. postURLbyParts(protocol, host, port, file, referer, user_agent, auth_token, ncookies, cookies, header_name, header_value, args, argc);
  509. }
  510. void postURLbyParts(int protocol, char* host, unsigned short port, char* file, char* referer, char* user_agent, char* auth_token, int ncookies, char** cookies, char* header_name, char* header_value, char** args, int argc) {
  511. int sockfd;
  512. SSL_CTX* ssl_ctx = (SSL_CTX*) 0;
  513. SSL* ssl = (SSL*) 0;
  514. char head_buf[20000];
  515. int max_arg, total_bytes;
  516. int multipart, next_arg_is_file;
  517. static const char* const sep = "http_post-content-separator";
  518. char* data_buf;
  519. char* enc_buf;
  520. int head_bytes, data_bytes, i, header_state;
  521. char* eq;
  522. (void) alarm(timeout);
  523. sockfd = open_client_socket(host, port);
  524. if(protocol == PROTO_HTTPS) {
  525. int r;
  526. ssl_ctx = SSL_CTX_new(TLSv1_client_method());
  527. SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, 0);
  528. ssl = SSL_new(ssl_ctx);
  529. SSL_set_fd(ssl, sockfd);
  530. r = SSL_connect(ssl);
  531. if(r <= 0) {
  532. (void) fprintf(stderr, "%s: %s - SSL connection failed - %d\n", argv0, url, r);
  533. exit(1);
  534. }
  535. }
  536. multipart = 0;
  537. total_bytes = max_arg = 0;
  538. next_arg_is_file = 0;
  539. for(i = 0; i < argc ; ++i) {
  540. int l = strlen(args[i]);
  541. if(strcmp(args[i], "-f") == 0) {
  542. multipart = 1;
  543. next_arg_is_file = 1;
  544. continue;
  545. }
  546. total_bytes += l;
  547. if(l > max_arg) {
  548. max_arg = l;
  549. }
  550. if(next_arg_is_file) {
  551. eq = strchr(args[i], '=');
  552. if(eq == (char*) 0) {
  553. (void) fprintf(stderr, "%s: missing filename\n", argv0);
  554. exit(1);
  555. } else {
  556. ++eq;
  557. total_bytes += file_bytes(eq);
  558. }
  559. next_arg_is_file = 0;
  560. }
  561. }
  562. if(multipart) {
  563. for(i = 0; i < argc ; ++i) {
  564. total_bytes += strlen(sep) * 2 + 100;
  565. }
  566. total_bytes += strlen(sep) * 2;
  567. } else {
  568. total_bytes *= 4;
  569. enc_buf = (char*) malloc_check(max_arg * 4);
  570. }
  571. data_buf = (char*) malloc_check(total_bytes);
  572. if(multipart) {
  573. next_arg_is_file = 0;
  574. data_bytes = 0;
  575. for(i = 0; i < argc; ++i) {
  576. if(strcmp(args[i], "-f") == 0) {
  577. next_arg_is_file = 1;
  578. continue;
  579. }
  580. eq = strchr(args[i], '=');
  581. if(eq == (char*) 0) {
  582. data_bytes += sprintf(&data_buf[data_bytes], "--%s\r\nContent-Disposition: form-data\r\n\r\n%s\r\n", sep, args[i]);
  583. } else {
  584. *eq++ = '\0';
  585. if(next_arg_is_file) {
  586. data_bytes += sprintf(&data_buf[data_bytes], "--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n\r\n", sep, args[i], eq);
  587. data_bytes += file_copy(eq, &data_buf[data_bytes]);
  588. data_bytes += sprintf(&data_buf[data_bytes], "\r\n");
  589. next_arg_is_file = 0;
  590. } else {
  591. data_bytes += sprintf(&data_buf[data_bytes], "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n", sep, args[i], eq);
  592. }
  593. }
  594. }
  595. data_bytes += sprintf(&data_buf[data_bytes], "--%s--\r\n", sep);
  596. } else {
  597. data_bytes = 0;
  598. for(i = 0; i < argc ; ++i) {
  599. if(data_bytes > 0) {
  600. data_bytes += sprintf(&data_buf[data_bytes], "&");
  601. }
  602. eq = strchr(args[i], '=');
  603. if(eq == (char*) 0) {
  604. strencode(enc_buf, args[i]);
  605. data_bytes += sprintf(&data_buf[data_bytes], "%s", enc_buf);
  606. } else {
  607. *eq++ = '\0';
  608. strencode(enc_buf, args[i]);
  609. data_bytes += sprintf(&data_buf[data_bytes], "%s=", enc_buf);
  610. strencode(enc_buf, eq);
  611. data_bytes += sprintf(&data_buf[data_bytes], "%s", enc_buf);
  612. }
  613. }
  614. }
  615. (void) alarm(timeout);
  616. head_bytes = snprintf(head_buf, sizeof(head_buf), "POST %s HTTP/1.0\r\n", file);
  617. head_bytes += snprintf(&head_buf[head_bytes], sizeof(head_buf) - head_bytes, "Host: %s\r\n", host);
  618. head_bytes += snprintf(&head_buf[head_bytes], sizeof(head_buf) - head_bytes, "Content-Length: %d\r\n", data_bytes);
  619. if(referer != (char*) 0) {
  620. head_bytes += snprintf(&head_buf[head_bytes], sizeof(head_buf) - head_bytes, "Referer: %s\r\n", referer);
  621. }
  622. head_bytes += snprintf(&head_buf[head_bytes], sizeof(head_buf) - head_bytes, "User-Agent: %s\r\n", user_agent);
  623. if(multipart) {
  624. head_bytes += snprintf(&head_buf[head_bytes], sizeof(head_buf) - head_bytes, "Content-type: multipart/form-data; boundary=\"%s\"\r\n", sep);
  625. } else {
  626. head_bytes += snprintf(&head_buf[head_bytes], sizeof(head_buf) - head_bytes, "Content-type: application/x-www-form-urlencoded\r\n");
  627. }
  628. head_bytes += snprintf(&head_buf[head_bytes], sizeof(head_buf) - head_bytes, "Accept: */*\r\n");
  629. head_bytes += snprintf(&head_buf[head_bytes], sizeof(head_buf) - head_bytes, "Accept-Language: en\r\n");
  630. head_bytes += snprintf(&head_buf[head_bytes], sizeof(head_buf) - head_bytes, "Accept-Charset: iso-8859-1,*,utf-8\r\n");
  631. if(auth_token != (char*) 0) {
  632. char token_buf[1000];
  633. token_buf[b64_encode((unsigned char*) auth_token, strlen(auth_token), token_buf, sizeof(token_buf))] = '\0';
  634. head_bytes += snprintf(&head_buf[head_bytes], sizeof(head_buf) - head_bytes, "Authorization: Basic %s\r\n", token_buf);
  635. }
  636. for(i = 0; i < ncookies; ++i) {
  637. head_bytes += snprintf(&head_buf[head_bytes], sizeof(head_buf) - head_bytes, "Cookie: %s\r\n", cookies[i]);
  638. }
  639. if(header_name != (char*) 0) {
  640. head_bytes += snprintf(&head_buf[head_bytes], sizeof(head_buf) - head_bytes, "%s: %s\r\n", header_name, header_value);
  641. }
  642. head_bytes += snprintf(&head_buf[head_bytes], sizeof(head_buf) - head_bytes, "\r\n");
  643. if(protocol == PROTO_HTTPS) {
  644. (void) SSL_write(ssl, head_buf, head_bytes);
  645. } else {
  646. (void) write(sockfd, head_buf, head_bytes);
  647. }
  648. if(protocol == PROTO_HTTPS) {
  649. (void) SSL_write(ssl, data_buf, data_bytes);
  650. } else {
  651. (void) write(sockfd, data_buf, data_bytes);
  652. }
  653. (void) alarm(timeout);
  654. header_state = HDST_BOL;
  655. for(;;) {
  656. if(protocol == PROTO_HTTPS) {
  657. head_bytes = SSL_read(ssl, head_buf, sizeof(head_buf));
  658. } else {
  659. head_bytes = read(sockfd, head_buf, sizeof(head_buf));
  660. }
  661. if(head_bytes <= 0) {
  662. break;
  663. }
  664. for(i = 0; i < head_bytes; ++i) {
  665. if(verbose) {
  666. (void) write(1, &head_buf[i], 1);
  667. }
  668. switch(header_state) {
  669. case HDST_BOL:
  670. switch(head_buf[i]) {
  671. case '\n':
  672. header_state = HDST_LF;
  673. break;
  674. case '\r':
  675. header_state = HDST_CR;
  676. break;
  677. default:
  678. header_state = HDST_TEXT;
  679. break;
  680. }
  681. break;
  682. case HDST_TEXT:
  683. switch(head_buf[i]) {
  684. case '\n':
  685. header_state = HDST_LF;
  686. break;
  687. case '\r':
  688. header_state = HDST_CR;
  689. break;
  690. }
  691. break;
  692. case HDST_LF:
  693. switch(head_buf[i]) {
  694. case '\n':
  695. goto end_of_headers;
  696. case '\r':
  697. header_state = HDST_CR;
  698. break;
  699. default:
  700. header_state = HDST_TEXT;
  701. break;
  702. }
  703. break;
  704. case HDST_CR:
  705. switch(head_buf[i]) {
  706. case '\n':
  707. header_state = HDST_CRLF;
  708. break;
  709. case '\r':
  710. goto end_of_headers;
  711. default:
  712. header_state = HDST_TEXT;
  713. break;
  714. }
  715. break;
  716. case HDST_CRLF:
  717. switch(head_buf[i]) {
  718. case '\n':
  719. goto end_of_headers;
  720. case '\r':
  721. header_state = HDST_CRLFCR;
  722. break;
  723. default:
  724. header_state = HDST_TEXT;
  725. break;
  726. }
  727. break;
  728. case HDST_CRLFCR:
  729. switch(head_buf[i]) {
  730. case '\n':
  731. case '\r':
  732. goto end_of_headers;
  733. default:
  734. header_state = HDST_TEXT;
  735. break;
  736. }
  737. break;
  738. }
  739. }
  740. }
  741. end_of_headers:
  742. if(head_bytes > 0) {
  743. ++i;
  744. (void) write(1, &head_buf[i], head_bytes - i);
  745. }
  746. for(;;) {
  747. (void) alarm(timeout);
  748. if(protocol == PROTO_HTTPS) {
  749. head_bytes = SSL_read(ssl, head_buf, sizeof(head_buf));
  750. } else {
  751. head_bytes = read(sockfd, head_buf, sizeof(head_buf));
  752. }
  753. if(head_bytes == 0) {
  754. break;
  755. }
  756. if(head_bytes < 0) {
  757. show_error("read");
  758. }
  759. (void) write(1, head_buf, head_bytes);
  760. }
  761. if(protocol == PROTO_HTTPS) {
  762. SSL_free(ssl);
  763. SSL_CTX_free(ssl_ctx);
  764. }
  765. (void) close(sockfd);
  766. }
  767. void show_error(char* cause) {
  768. char buf[5000];
  769. (void) sprintf(buf, "%s: %s - %s", argv0, url, cause);
  770. perror(buf);
  771. exit(1);
  772. }
  773. void sigcatch(int sig) {
  774. (void) fprintf(stderr, "%s: %s - timed out\n", argv0, url);
  775. exit(1);
  776. }
  777. void strencode(char* to, char* from) {
  778. int tolen;
  779. for(tolen = 0; *from != '\0'; ++from) {
  780. if(isalnum(*from) || strchr("/_.", *from) != (char*) 0) {
  781. *to = *from;
  782. ++to;
  783. ++tolen;
  784. } else {
  785. (void) sprintf(to, "%%%02x", (int) *from & 0xff);
  786. to += 3;
  787. tolen += 3;
  788. }
  789. }
  790. *to = '\0';
  791. }
  792. void usage() {
  793. (void) fprintf(stderr, "usage: %s [-c cookie] [-t timeout] [-r referer] [-u user-agent] [-a username:password] [-h header value] [-v] url\n", argv0);
  794. exit(1);
  795. }