Advertisement
dylanweber

c http client code (nonfunctional)

May 3rd, 2015
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.13 KB | None | 0 0
  1. /*
  2.     helloworld.c
  3.     Dylan Weber
  4. */
  5. #include <stdio.h>
  6. #include <stdint.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/socket.h>
  10. #include <sys/types.h>
  11. #include <netdb.h>
  12. #include <unistd.h>
  13. #include <arpa/inet.h>
  14. #include <time.h>
  15.  
  16. typedef struct URLdata {
  17.     char *protocol;
  18.     char *username;
  19.     char *password;
  20.     char *host;
  21.     char *port;
  22.     char *path;
  23. } URLdata;
  24.  
  25. typedef struct HTTPresponse {
  26.     int status;
  27.     char **headers;
  28.     char *content;
  29. } HTTPresponse;
  30.  
  31. URLdata *createURLdata(char *weburl);
  32. void freeURLdata(URLdata *freeURL);
  33. HTTPresponse *requestHTTPresponse(URLdata *requestDestination);
  34. void *get_in_addr(struct sockaddr *sa);
  35. char **generateHeaderList(char *headers);
  36. void freeHTTPresponse(HTTPresponse *freeResponse);
  37. void copyAndTerminateString(char *dest, char *src, int len);
  38. char *base64encode(char *input);
  39.  
  40. int main(int argc, char **argv) {
  41.     if (argc != 2) {
  42.         printf("Usage: helloworld ... destination\r\n");
  43.         return 1;
  44.     }
  45.     URLdata *inputURL = createURLdata(argv[1]);
  46.     HTTPresponse *outputResponse = requestHTTPresponse(inputURL);
  47.     /*printf("Response Code:%d\r\nHeaders:\r\n", outputResponse->status);
  48.     int n;
  49.     for (n = 0; outputResponse->headers[n] != NULL; n++) {
  50.         printf("%d: \"%s\"\r\n", n+1, outputResponse->headers[n]);
  51.     }
  52.     int conlen = strlen(outputResponse->content);
  53.     printf("Content length:%d\r\n", conlen);
  54.     printf("Content:\"%.100s\"%s\r\n", outputResponse->content, (conlen > 100)?"...":"");*/
  55.     freeURLdata(inputURL);
  56.     freeHTTPresponse(outputResponse);
  57.     return 0;
  58. }
  59.  
  60. URLdata *createURLdata(char *weburl) {
  61.     char *postprotocol, *postuserinfo, *postusername, *posthost, *posthostname, *hostloc;
  62.     int isPath = 1, userlen;
  63.    
  64.     URLdata *returnURL = malloc(sizeof(URLdata));
  65.     returnURL->protocol = NULL;
  66.     returnURL->username = NULL;
  67.     returnURL->password = NULL;
  68.     returnURL->host = NULL;
  69.     returnURL->port = NULL;
  70.     returnURL->path = NULL;
  71.    
  72.     if ((postprotocol = strstr(weburl, "://")) == NULL) {
  73.         return returnURL;
  74.     }
  75.     returnURL->protocol = malloc(sizeof(char) * (postprotocol - weburl) + 1);
  76.     copyAndTerminateString(returnURL->protocol, weburl, postprotocol - weburl);
  77.     postprotocol = (postprotocol + (*(postprotocol+3)=='/'?4:3));
  78.     if ((postuserinfo = strstr(postprotocol, "@")) != NULL) {
  79.         if ((postusername = strchr(postprotocol, ':')) != NULL) {
  80.             returnURL->password = malloc(sizeof(char) * (postuserinfo - postusername) + 1);
  81.             copyAndTerminateString(returnURL->password, postusername + 1, postuserinfo - postusername - 1);
  82.         }
  83.         userlen = (postusername?postusername:postuserinfo) - postprotocol;
  84.         returnURL->username = malloc(sizeof(char) * userlen + 1);
  85.         copyAndTerminateString(returnURL->username, postprotocol, userlen);
  86.     }
  87.     hostloc = (postuserinfo?postuserinfo + 1:postprotocol);
  88.     if ((posthost = strchr(hostloc, '/')) == NULL) {
  89.         posthost = hostloc + strlen(hostloc);
  90.         isPath = 0;
  91.     }
  92.     if ((posthostname = strchr(hostloc, ':')) == NULL) {
  93.         posthostname = posthost;
  94.     }
  95.     returnURL->host = malloc(sizeof(char) * (posthostname - hostloc + 1));
  96.     copyAndTerminateString(returnURL->host, hostloc, (posthostname - hostloc));
  97.     if (posthostname != posthost) {
  98.         posthostname++;
  99.         returnURL->port = malloc(sizeof(char) * (posthost - posthostname + 1));
  100.         copyAndTerminateString(returnURL->port, posthostname, (posthost - posthostname));
  101.     } else {
  102.         returnURL->port = malloc(sizeof(char) * 2 + 1);
  103.         copyAndTerminateString(returnURL->port, "80", 2);
  104.     }
  105.     if (isPath) {
  106.         returnURL->path = malloc(sizeof(char) * strlen(posthost) + 1);
  107.         copyAndTerminateString(returnURL->path, posthost, strlen(posthost));
  108.     } else {
  109.         returnURL->path = calloc(1, 1);
  110.     }
  111.     return returnURL;
  112. }
  113.  
  114. void freeURLdata(URLdata *freeURL) {
  115.     free(freeURL->protocol);
  116.     free(freeURL->username);
  117.     free(freeURL->password);
  118.     free(freeURL->host);
  119.     free(freeURL->port);
  120.     free(freeURL->path);
  121.     free(freeURL);
  122. }
  123.  
  124. HTTPresponse *requestHTTPresponse(URLdata *requestDestination) {
  125.     char ip[INET6_ADDRSTRLEN], *request, *response = NULL, *headerTerminator = NULL, *responseTerminator = NULL, *headerString, *contentString, *authstring = NULL, buffer[100];
  126.     int sockfd, bufferLength, requesttime, responseLength = 0;
  127.     struct addrinfo hints, *servinfo, *p;
  128.    
  129.     /* Initialize HTTP response structure */
  130.     HTTPresponse *returnresponse = malloc(sizeof(HTTPresponse));
  131.     returnresponse->status = 0;
  132.     returnresponse->headers = NULL;
  133.     returnresponse->content = NULL;
  134.    
  135.     /* Retrieve IP address of host */
  136.     memset(&hints, 0, sizeof hints);
  137.     hints.ai_family = AF_UNSPEC;
  138.     hints.ai_socktype = SOCK_STREAM;
  139.     if (getaddrinfo(requestDestination->host, requestDestination->port, &hints, &servinfo) != 0) {
  140.         return returnresponse;
  141.     }
  142.    
  143.     /* Loop through all possible connections */
  144.     for (p = servinfo; p != NULL; p = p->ai_next) {
  145.         if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
  146.             continue;
  147.         }
  148.         if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
  149.             close(sockfd);
  150.             continue;
  151.         }
  152.         break;
  153.     }
  154.    
  155.     if (p == NULL) {
  156.         return returnresponse;
  157.     }
  158.    
  159.     /* Print IP address & free server information */
  160.     inet_ntop(p->ai_family, get_in_addr((struct sockaddr*)p->ai_addr), ip, sizeof(ip));
  161.     printf("The IP address is: %s\n", ip);
  162.     freeaddrinfo(servinfo);
  163.    
  164.     /* Format HTTP request */
  165.     if (requestDestination->username && requestDestination->password) {
  166.         char *preencode, *encode;
  167.         preencode = malloc(2 + (int)strlen(requestDestination->username) + (int)strlen(requestDestination->password) * sizeof(char));
  168.         sprintf(preencode, "%s:%s", requestDestination->username, requestDestination->password);
  169.         encode = base64encode(preencode);
  170.         authstring = malloc(24 + (int)strlen(encode) * sizeof(char));
  171.         sprintf(authstring, "\r\nAuthorization: Basic %s", encode);
  172.         free(preencode);
  173.         free(encode);
  174.         printf("AUTH: %s\r\n", authstring + 2);
  175.     }
  176.     request = malloc((26 + (int)strlen((*(requestDestination->path) == 0)?"/":requestDestination->path) + (int)strlen(requestDestination->host) + ((authstring != NULL)?(int)strlen(authstring):0)) * sizeof(char));
  177.     if (request == NULL) {
  178.         printf("Failure to allocate memory at line %d.\n", __LINE__ - 2);
  179.         exit(1);
  180.     }
  181.     sprintf(request, "GET %s HTTP/1.1\r\nHost: %s%s\r\n\r\n", (*(requestDestination->path) == 0)?"/":requestDestination->path, requestDestination->host, ((authstring != NULL)?authstring:""));
  182.     if (authstring != NULL) free(authstring);
  183.    
  184.     /* Send HTTP request */
  185.     send(sockfd, request, (int)strlen(request), 0);
  186.     free(request);
  187.     requesttime = time(NULL);
  188.    
  189.     /* Receive HTTP response */
  190.     do {
  191.         bufferLength = recv(sockfd, buffer, 99, 0);
  192.         if (bufferLength == -1) {
  193.             break;
  194.         }
  195.         responseLength += bufferLength;
  196.         response = realloc(response, (responseLength + 1) * sizeof(char));
  197.         if (response == NULL) {
  198.             printf("Failure to allocate memory at line %d.\r\n", __LINE__ - 2);
  199.             exit(2);
  200.         }
  201.         copyAndTerminateString(response + responseLength - bufferLength, buffer, bufferLength);
  202.         if (headerTerminator) {
  203.             responseTerminator = strstr(headerTerminator+4, "\r\n\r\n");
  204.         } else {
  205.             headerTerminator = strstr(response, "\r\n\r\n");
  206.         }
  207.         if ((time(NULL) - requesttime) > 20) {
  208.             printf("Server timeout error.\r\n");
  209.             exit(1);
  210.         }
  211.     } while (responseTerminator == NULL);
  212.    
  213.     /* Store data in structs */
  214.     headerString = malloc((headerTerminator - response + 1) * sizeof(char));
  215.     if (headerString == NULL) {
  216.         printf("Failure to allocate memory at line %d.\r\n", __LINE__ - 2);
  217.         exit(1);
  218.     }
  219.     copyAndTerminateString(headerString, response, headerTerminator - response);
  220.     contentString = malloc((responseTerminator - headerTerminator + 1) * sizeof(char));
  221.     if (contentString == NULL) {
  222.         printf("Failure to allocate memory at line %d.\r\n", __LINE__ - 2);
  223.         exit(1);
  224.     }
  225.     copyAndTerminateString(contentString, headerTerminator+4, responseTerminator - headerTerminator - 4);
  226.     returnresponse->headers = generateHeaderList(headerString);
  227.     returnresponse->content = contentString;
  228.     free(headerString);
  229.     free(response);
  230.    
  231.     /* Extract status code */
  232.     if (strncmp(returnresponse->headers[0], "HTTP", 4) == 0) {
  233.         response = malloc(4 * sizeof(char));
  234.         copyAndTerminateString(response, returnresponse->headers[0] + 9, 3);
  235.         returnresponse->status = atoi(response);
  236.         free(response);
  237.     } else {
  238.         returnresponse->status = -1;
  239.     }
  240.    
  241.     /* Close connection & return HTTP response */
  242.     close(sockfd);
  243.     return returnresponse;
  244. }
  245.  
  246. void *get_in_addr(struct sockaddr *sa) {
  247.     if (sa->sa_family == AF_INET) {
  248.         return &(((struct sockaddr_in*)sa)->sin_addr);
  249.     } else if (sa->sa_family == AF_INET6) {
  250.         return &(((struct sockaddr_in6*)sa)->sin6_addr);
  251.     }
  252.     return 0;
  253. }
  254.  
  255. char **generateHeaderList(char *headers) {
  256.     char **returnHeaders = NULL, *nextLine;
  257.     int len, n;
  258.     for (n = 0; (nextLine = strstr(headers, "\r\n")) != NULL; n++) {
  259.         len = nextLine - headers;
  260.         if (len == 0) break;
  261.         returnHeaders = realloc(returnHeaders, (n + 1) * sizeof(char *));
  262.         if (returnHeaders == NULL) {
  263.             printf("Failure to allocate memory at line %d.\r\n", __LINE__ - 2);
  264.             exit(1);
  265.         }
  266.         returnHeaders[n] = malloc((len + 1) * sizeof(char));
  267.         copyAndTerminateString(returnHeaders[n], headers, len);
  268.         headers = nextLine + 2;
  269.         printf("finished %d at %p\r\n", n, (void *)*(returnHeaders + n));
  270.     }
  271.     printf("with %d, remaining %s\r\n", n, headers);
  272.     len = strlen(headers);
  273.     if (len == 0) return returnHeaders;
  274.     returnHeaders = realloc(returnHeaders, (n + 1) * sizeof(char *));
  275.     if (returnHeaders == NULL) {
  276.         printf("Failure to allocate memory at line %d.\r\n", __LINE__ - 2);
  277.         exit(1);
  278.     }
  279.     returnHeaders[n] = malloc((len + 1) * sizeof(char));
  280.     copyAndTerminateString(returnHeaders[n], headers, len);
  281.     returnHeaders[n+1] = NULL;
  282.     return returnHeaders;
  283. }
  284.  
  285. void freeHTTPresponse(HTTPresponse *freeResponse) {
  286.     int n;
  287.     for (n = 0; freeResponse->headers[n] != NULL; n++) {
  288.         printf("freeing %d at %p: %s\r\n", n, (void *)*(freeResponse->headers + n), freeResponse->headers[n]);
  289.         free(freeResponse->headers[n]);
  290.     }
  291.     free(freeResponse->headers);
  292.     free(freeResponse->content);
  293.     free(freeResponse);
  294. }
  295.  
  296. void copyAndTerminateString(char *dest, char *src, int len) {
  297.     strncpy(dest, src, len);
  298.     dest[len] = '\0';
  299. }
  300.  
  301. char *base64encode(char *input) {
  302.     int len = strlen(input), leftover = len % 3, n = 0, outlen = 0;
  303.     char *ret = malloc(((len / 3) * 4) + ((leftover)?4:0) + 1);
  304.     uint8_t *inp = (uint8_t *)input, i = 0;
  305.     const char *index = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  306.    
  307.     if (ret == NULL) {
  308.         return NULL;
  309.     }
  310.    
  311.     len -= leftover;
  312.     for (n = 0; n < len; n+=3) {
  313.         i = inp[n] >> 2;
  314.         ret[outlen++] = index[i];
  315.  
  316.         i  = (inp[n]   & 0x03) << 4;
  317.         i |= (inp[n+1] & 0xf0) >> 4;
  318.         ret[outlen++] = index[i];
  319.  
  320.         i  = ((inp[n+1] & 0x0f) << 2);
  321.         i |= ((inp[n+2] & 0xc0) >> 6);
  322.         ret[outlen++] = index[i];
  323.  
  324.         i  = (inp[n+2] & 0x3f);
  325.         ret[outlen++] = index[i];
  326.     }
  327.  
  328.     if (leftover) {
  329.         i = (inp[n] >> 2);
  330.         ret[outlen++] = index[i];
  331.  
  332.         i = (inp[n]   & 0x03) << 4;
  333.         if (leftover == 2) {
  334.             i |= (inp[n+1] & 0xf0) >> 4;
  335.             ret[outlen++] = index[i];
  336.  
  337.             i  = ((inp[n+1] & 0x0f) << 2);
  338.         }
  339.         ret[outlen++] = index[i];
  340.         ret[outlen++] = '=';
  341.         if (leftover == 1) {
  342.             ret[outlen++] = '=';
  343.         }
  344.     }
  345.     ret[outlen] = '\0';
  346.     return ret;
  347. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement