Advertisement
Guest User

Untitled

a guest
Dec 9th, 2019
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.30 KB | None | 0 0
  1. #define _GNU_SOURCE
  2.  
  3. #include <arpa/inet.h>
  4. #include <netdb.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/socket.h>
  9. #include <unistd.h>
  10.  
  11. typedef struct Url {
  12.     char* scheme;
  13.     char* login;
  14.     char* password;
  15.     char* hostname;
  16.     char* port;
  17.     char* path;
  18.     char* query;
  19.     char* fragment;
  20. } Url;
  21.  
  22.  
  23. int parser(char* url, Url* parsing, int flag);
  24. int parse_origin(char* origin, char* end, Url* parsing);
  25. char* check_login_password(char* origin, Url* parsing);
  26. int check_scheme(char* str, char** port);
  27. char* parse_path(char* origin, Url* parsing);
  28. char* parse_query(char* path, Url* parsing);
  29. char* parse_fragment(char* query, Url* parsing);
  30. char* parse_for_request(char* origin, Url* parsing);
  31.  
  32.  
  33. void init_sockaddr (struct sockaddr_in *name,
  34.                 const char* hostname,
  35.                 uint16_t port);
  36. char* do_request(Url* parsing);
  37.  
  38. int parse_recieve(char* buffer);
  39. int write_rec_to_file(char* buffer, FILE* file, int sock);
  40.  
  41. void free_url(Url* parsing);
  42.  
  43.  
  44. int main(int argc, char **argv) {
  45.     if (argc != 2) {
  46.         return -3;
  47.     }
  48.  
  49.     char buffer[4096] = {};
  50.  
  51.     Url* parsing = calloc(1, sizeof(Url));
  52.  
  53.     if(!parsing) {
  54.         return -4;
  55.     }
  56.  
  57.     char* url = argv[1];
  58.  
  59.     struct sockaddr_in address = {};
  60.  
  61.     int sock = socket(AF_INET, SOCK_STREAM, 0);
  62.  
  63.     if (parser(url, parsing, 0)) {
  64.         return -1;
  65.     }
  66.  
  67.     char* request_m = do_request(parsing);
  68.  
  69.     init_sockaddr(&address, parsing->hostname, atoi(parsing->port));
  70.  
  71.     if (connect(sock, (struct sockaddr*)&address, sizeof(address)) < 0) {
  72.         free(request_m);
  73.         free_url(parsing);
  74.         free(parsing);
  75.         return -2;
  76.     }
  77.  
  78.     send(sock, request_m, strlen(request_m) + 1, 0);
  79.     free(request_m);
  80.  
  81.     FILE* file = fopen("file", "w");
  82.     if (!file) {
  83.         free_url(parsing);
  84.         free(parsing);
  85.     }
  86.  
  87.     write_rec_to_file(buffer, file, sock);
  88.  
  89.     free_url(parsing);
  90.     free(parsing);
  91.     close(sock);
  92.     fclose(file);
  93.  
  94.     return 0;
  95. }
  96.  
  97. char* check_login_password(char* origin, Url* parsing) {
  98.     char* field = strstr(origin, "@");
  99.  
  100.     if (!field) {
  101.         parsing->password = NULL;
  102.         parsing->login = NULL;
  103.         return NULL;
  104.     }
  105.  
  106.     char* separator = strstr(origin, ":");
  107.     if (!separator) {
  108.         return field + 1;
  109.     }
  110.  
  111.     asprintf(&parsing->login, "%.*s", (int)(separator - origin), origin);
  112.     asprintf(&parsing->password,"%.*s", (int)(field - separator - 1), separator + 1);
  113.  
  114.     return field + 1;
  115. }
  116.  
  117.  
  118. int parse_origin(char* origin, char* end, Url* parsing) {
  119.     char* host = check_login_password(origin, parsing);
  120.  
  121.     if (host) {
  122.         origin = host;
  123.     }
  124.  
  125.     char* port = strstr(origin, ":");
  126.  
  127.     if (port) {
  128.         asprintf(&parsing->hostname, "%.*s", (int)(port - origin), origin);
  129.         asprintf(&parsing->port, "%.*s", (int)(end - port - 1), port + 1);
  130.         return 0;
  131.     }
  132.  
  133.     asprintf(&parsing->hostname, "%.*s", (int)(end - origin), origin);
  134.     return 1;
  135. }
  136.  
  137. int check_scheme(char* str, char** port) {
  138.     int flag_http = 0;
  139.     int flag_https = 0;
  140.  
  141.     if (!strcmp(str, "http")) {
  142.         flag_http = 1;
  143.         *port = "80";
  144.         return 1;
  145.     }
  146.  
  147.     if (!strcmp(str, "https")) {
  148.         flag_https = 1;
  149.         *port = "443";
  150.         return 1;
  151.     }
  152.  
  153.     return 0;
  154. }
  155.  
  156. char* parse_path(char* origin, Url* parsing) {
  157.     if (!(origin + 1)) {
  158.         return NULL;
  159.     }
  160.  
  161.     int i = 0;
  162.     while (origin[i] && origin[i] != '?' && origin[i] != '#') {
  163.         i++;
  164.     }
  165.  
  166.     asprintf(&parsing->path, "%.*s", (int)(i), origin);
  167.     return origin + i;
  168. }
  169.  
  170. char* parse_query(char* path, Url* parsing) {
  171.     if (!(path + 1)) {
  172.         return NULL;
  173.     }
  174.  
  175.     int i = 0;
  176.     while (path[i] && path[i] != '#') {
  177.         i++;
  178.     }
  179.  
  180.     asprintf(&parsing->query, "%.*s", (int)(i), path);
  181.     return path + i;
  182. }
  183.  
  184. char* parse_fragment(char* query, Url* parsing) {
  185.     if (!(query + 1)) {
  186.         return NULL;
  187.     }
  188.  
  189.     int i = 0;
  190.     while (query[i]) {
  191.         i++;
  192.     }
  193.  
  194.     asprintf(&parsing->fragment, "%.*s", (int)(i), query);
  195.     return query;
  196. }
  197.  
  198. char* parse_for_request(char* origin, Url* parsing) {
  199.     if (!(origin + 1)) {
  200.         return NULL;
  201.     }
  202.  
  203.     int i = 0;
  204.     while (origin[i] && origin[i] != '#') {
  205.         i++;
  206.     }
  207.  
  208.     asprintf(&parsing->path, "%.*s", (int)(i), origin);
  209.     return origin + i;
  210. }
  211.  
  212. int parser(char* url, Url* parsing, int flag) {
  213.     char* str = NULL;
  214.     int size = strlen(url);
  215.     char* field = strstr(url, "://");
  216.  
  217.     if (!field) {
  218.         return -1;
  219.     }
  220.  
  221.     asprintf(&str, "%.*s", (int)(field - url), url);
  222.  
  223.     if (!check_scheme(str, &parsing->port)) {
  224.         return -2;
  225.     }
  226.  
  227.     parsing->scheme = str;
  228.     char* origin = strstr(field + 3, "/");
  229.  
  230.     if (!origin) {
  231.         parse_origin(field + 3, url + size, parsing);
  232.         asprintf(&parsing->path, "%.*s", 1, str);
  233.         return 0;
  234.     }
  235.  
  236.     parse_origin(field + 3, origin, parsing);
  237.     char* path = parse_for_request(origin, parsing);
  238.  
  239.     if (flag != 0) {
  240.         path = parse_path(origin, parsing);
  241.     }
  242.  
  243.     if (!*(path) || !path || *(path) == '#') {
  244.         if (*(path) == '#') {
  245.             char* fragment = parse_fragment(path, parsing);
  246.         }
  247.         return 0;
  248.     }
  249.  
  250.     char* query = parse_query(path, parsing);
  251.  
  252.     if (!*(query) || !query) {
  253.         return 0;
  254.     }
  255.  
  256.     char* fragment = parse_fragment(query, parsing);
  257.     return 0;
  258.  
  259. }
  260.  
  261.  
  262. void init_sockaddr (struct sockaddr_in *name,
  263.                 const char* hostname,
  264.                 uint16_t port) {
  265.  
  266.   struct hostent* hostinfo;
  267.  
  268.   name->sin_family = AF_INET;
  269.   name->sin_port = htons(80);
  270.   hostinfo = gethostbyname(hostname);
  271.  
  272.   if (hostinfo == NULL) {
  273.       fprintf (stderr, "Unknown host %s.\n", hostname);
  274.       exit (EXIT_FAILURE);
  275.     }
  276.  
  277.   name->sin_addr = *(struct in_addr*)hostinfo->h_addr;
  278. }
  279.  
  280.  
  281. char* do_request(Url* parsing) {
  282.     char* request = NULL;
  283.     int size = strlen(parsing->path);
  284.     int host_size = strlen(parsing->hostname) + 11;
  285.     int new_size = asprintf(&request, "GET %.*s HTTP/1.1\r\n", size, parsing->path);
  286.     char* new_request = realloc(request, new_size + host_size);
  287.  
  288.     if (!new_request) {
  289.         free(request);
  290.         return NULL;
  291.     }
  292.  
  293.     request = new_request;
  294.     snprintf(request + new_size, host_size, "Host: %s\r\n\r\n", parsing->hostname);
  295.  
  296.     return request;
  297. }
  298.  
  299.  
  300. int parse_recieve(char* buffer) {
  301.     char* new_line = strstr(buffer, "\r\n");
  302.  
  303.     if (!new_line) {
  304.         return -1;
  305.     }
  306.  
  307.     char* check_str = NULL;
  308.     int size = asprintf(&check_str, "%.*s", (int)(new_line - buffer), buffer);
  309.    
  310.     char* ok = strstr(check_str, "200 OK");
  311.  
  312.     if (!ok) {
  313.         free(check_str);
  314.         return -2;
  315.     }
  316.  
  317.     free(check_str);
  318.     return 0;
  319. }
  320.  
  321. void free_url(Url* parsing) {
  322.     if (parsing->scheme) {
  323.         free(parsing->scheme);
  324.     }
  325.     if (parsing->login) {
  326.         free(parsing->login);
  327.     }
  328.     if (parsing->password) {
  329.         free(parsing->password);
  330.     }
  331.     if (parsing->hostname) {
  332.         free(parsing->hostname);
  333.     }
  334.     if (parsing->port) {
  335.         //free(parsing->port);
  336.     }
  337.     if (parsing->path) {
  338.         free(parsing->path);
  339.     }
  340.     if (parsing->query) {
  341.         free(parsing->query);
  342.     }
  343.     if (parsing->fragment) {
  344.         free(parsing->fragment);
  345.     }
  346.  
  347. }
  348.  
  349. int write_rec_to_file(char* buffer, FILE* file, int sock) {
  350.     int nbytes_total = 0;
  351.     int flag = 0;
  352.     int i = 0;
  353.  
  354.     char* check = NULL;
  355.     char* end = NULL;
  356.  
  357.     while ((nbytes_total = read(sock, buffer, 4095)) > 0) {
  358.         if (!i && parse_recieve(buffer)) {
  359.             return 0;
  360.         }
  361.  
  362.         if (!flag) {
  363.             end = strstr(buffer, "\r\n\r\n");
  364.             if (!end) {
  365.                 i++;
  366.                 continue;
  367.             }
  368.  
  369.             flag = 1;
  370.             write(fileno(file), buffer + (end - buffer) + 4, nbytes_total - (end - buffer) - 4);
  371.             i++;
  372.             continue;
  373.         }
  374.  
  375.         check = strstr(buffer, "HTTP/1.1 400");
  376.  
  377.         if (check) {
  378.             write(fileno(file), buffer, check - buffer);
  379.             break;
  380.         }
  381.  
  382.         write(fileno(file), buffer, nbytes_total);
  383.         i++;
  384.     }
  385.     return 1;
  386. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement