Description: paste.c
Submitted by Admin on October 20, 2012

Section 1 (Text)

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#include "paste.h"

#define HTTP_PREFIX "http:/"

#define HTTP_HOST "paste.ee"
#define HTTP_PORT "80"

#define BUF_SIZE 512

int main(int argc, char* argv[]) {
	
	char buffer[BUF_SIZE];
	size_t contentSize = 0;
	char *content = malloc(sizeof(char) * BUF_SIZE);
	if(content == NULL) {
		perror("Failed to allocate content");
		exit(1);
	}
	
	while(fgets(buffer, BUF_SIZE, stdin))
	{
		char *old = content;
		contentSize += strlen(buffer);
		content = realloc(content, contentSize);
		if(content == NULL) {
			perror("Failed to reallocate content");
			free(old);
			exit(2);
		}
		strcat(content, buffer);
		printf("%s", buffer);
	}
	
	char *key = getenv("PASTEE_KEY");
	
	char *url = paste(content, key, "Paste.ee CLI Tool", NULL);
	
	printf("\nPaste URL: %s\n", url);
	
}

char *paste( char *contents, char *key, char *description, char *language ) {

	if(contents == NULL || contents[0] == '\0') {
		perror("Contents empty!");
		return NULL;
	}

	struct addrinfo *result;
	
	int s = getaddrinfo(HTTP_HOST, HTTP_PORT, NULL, &result);
	
	if(s != 0) {
		perror("Unable to get address info");
		return NULL;
	}
	
	int sockfd = 0, conn = 0;
	struct addrinfo *rp = result;
	
	do {
		sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
		if (sockfd <0)
			continue;
		if ((conn = connect(sockfd, rp->ai_addr, rp->ai_addrlen)) == 0) {
			// Success!
			break;
		} else {
			perror("connecting stream socket");
		}
		close(sockfd);
	} while ((rp = rp->ai_next)!= NULL);
	
	if (rp == NULL)
		return NULL;
	
	freeaddrinfo(result);
	
	char buf[BUF_SIZE];
	
	if(key == NULL || key[0] == '\0') {
		key = "public";
	}
	
	if(description == NULL) {
		description = "";
	} else {
		description = url_encode(description);
	}
	
	if(language == NULL) {
		language = "plain";
	}
	
	size_t reqSize = sizeof(char) * (49 + strlen(description) + strlen(language) + strlen(key));
	
	char *req = malloc(reqSize);
	
	snprintf(req, reqSize, "key=%s&format=simple&description=%s&language=%s&paste=", key, description, language);
	
	char *encoded = url_encode(contents);
	
	snprintf(buf, sizeof(buf), "POST /api HTTP/1.1\r\nHost: paste.ee\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %i\r\n\r\n", strlen(req) + strlen(encoded));
	
	send(sockfd, buf, strlen(buf), 0);
	
	send(sockfd, req, strlen(req), 0);
	
	send(sockfd, encoded, strlen(encoded), 0);
	
	snprintf(buf, sizeof(buf), "\r\n");
	
	send(sockfd, buf, strlen(buf), 0);
	
	free(description);
	free(encoded);
	
	char resp[512];
	
	memset(resp, 0, sizeof(resp));
	
	recv(sockfd, resp, sizeof(resp), 0);
	
	close(sockfd);
	
	char delim[] = "\r\n";
	char *ret = NULL;
	char *res = strtok(resp, delim);
	while(res != NULL) {
		if(strncmp(res, HTTP_PREFIX, strlen(HTTP_PREFIX)) == 0) {
			ret = malloc(sizeof(char) * (strlen(res) + 1));
			memcpy(ret, res, strlen(res) + 1);
			break;
		}
		res = strtok( NULL, delim );
	}
	
	return ret;
	
}

/* Converts an integer value to its hex character*/
char to_hex(char code) {
  static char hex[] = "0123456789abcdef";
  return hex[code & 15];
}

/* Returns a url-encoded version of str */
/* IMPORTANT: be sure to free() the returned string after use */
char *url_encode(char *str) {
  char *pstr = str, *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf;
  while (*pstr) {
	if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') 
	  *pbuf++ = *pstr;
	else if (*pstr == ' ') 
	  *pbuf++ = '+';
	else 
	  *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
	pstr++;
  }
  *pbuf = '\0';
  return buf;
}