/* * myturl.com URL Shortener (C Client) * by Mike Crute (mcrute@gmail.com) * on December 1, 2009 * * compile with: gcc -lcurl -o myturl myturl_client.c */ #include #include #include #include #define TRUE 1 #define FALSE 0 static const char *URL_BASE = "http://myturl.com/add-url?url="; static int it_worked = FALSE; inline void blow_up(const char *message) { perror(message); exit(EXIT_FAILURE); } inline void * safe_malloc(size_t size) { char *location = calloc(1, size); if (location == NULL) { blow_up("You ran out of memory!"); } return location; } inline void safe_free(void *stuff) { free(stuff); stuff = NULL; } char * chomp_end(const char *instr) { size_t len = strlen(instr); char *output = safe_malloc(len); strlcpy(output, instr, len - 1); return output; } inline int starts_with(const char *instr, const char* value) { return !(strncmp(instr, value, strlen(value))); } inline int char_in(const char *instr, char testval) { return !(strchr(instr, (int)testval) == NULL); } char to_hex(char code) { static char hex[] = "0123456789abcdef"; return hex[code & 15]; } char * url_quote(char *string) { static char *acceptable = "-_.~"; char *buffer = safe_malloc(strlen(string) * 3 + 1); char *strpos = string; char *bufpos = buffer; while (*strpos) { if (isalnum(*strpos) || char_in(acceptable, *strpos)) { *bufpos++ = *strpos; } else if (*strpos == ' ') { *bufpos++ = '+'; } else { *bufpos++ = '%'; *bufpos++ = to_hex(*strpos >> 4); *bufpos++ = to_hex(*strpos & 15); } *strpos++; } return buffer; } char * get_value_part(const char *instr) { size_t len = strlen(instr); char *offset = strpbrk(instr, ":") + 2; size_t slice_size = len - (instr - offset); char *output = safe_malloc(len); strlcpy(output, offset, slice_size); return output; } size_t handle_headers(char *instr, size_t size, size_t slen, void *outstream) { char *header = chomp_end(instr); if (starts_with(header, "X-MyTurl:")) { char *value = get_value_part(header); printf("%s\n", value); safe_free(value); it_worked = TRUE; } safe_free(header); return size * slen; } void silence_curl(CURL *curl) { FILE *devnull = fopen("/dev/null", "w"); if (devnull == NULL) { blow_up("Could not open /dev/null."); } curl_easy_setopt(curl, CURLOPT_WRITEDATA, devnull); } inline char * string_join(const char *lhs, const char *rhs) { char *output = safe_malloc(strlen(lhs) + strlen(rhs)); sprintf(output, "%s%s", lhs, rhs); return output; } int main(int argc, char **argv) { if (argc < 2) { blow_up("This program takes only one argument, the URL."); } CURL *curl = curl_easy_init(); if (!curl) { blow_up("Failed to initialize curl!"); } silence_curl(curl); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, handle_headers); char *encoded = url_quote(argv[1]); char *url = string_join(URL_BASE, encoded); curl_easy_setopt(curl, CURLOPT_URL, url); CURLcode result = curl_easy_perform(curl); if (result != 0) { blow_up("Couldn't contact the service!"); } if (it_worked == FALSE) { perror("No turl was generated. Check your URL."); } curl_easy_cleanup(curl); safe_free(url); safe_free(encoded); return EXIT_SUCCESS; }