Saturday, September 29, 2012

URL Encoding / Decoding in C

Encode the url: http://foo bar/
 
Code 1: 
 
/* Converts a hex character to its integer value */
char from_hex(char ch) {
  return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}

/* 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;
}

/* Returns a url-decoded version of str */
/* IMPORTANT: be sure to free() the returned string after use */
char *url_decode(char *str) {
  char *pstr = str, *buf = malloc(strlen(str) + 1), *pbuf = buf;
  while (*pstr) {
    if (*pstr == '%') {
      if (pstr[1] && pstr[2]) {
        *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
        pstr += 2;
      }
    } else if (*pstr == '+') { 
      *pbuf++ = ' ';
    } else {
      *pbuf++ = *pstr;
    }
    pstr++;
  }
  *pbuf = '\0';
  return buf;
}
 
Code 2:
 
#include <stdio.h>
#include <ctype.h>
 
char rfc3986[256] = {0};
char html5[256] = {0};
 
/* caller responsible for memory */
void encode(unsigned char *s, char *enc, char *tb)
{
 for (; *s; s++) {
  if (tb[*s]) sprintf(enc, "%c", tb[*s]);
  else        sprintf(enc, "%%%02X", *s);
  while (*++enc);
 }
}
 
int main()
{
 unsigned char url[] = "http://foo bar/";
 char enc[sizeof(url) * 3];
 
 int i;
 for (i = 0; i < 256; i++) {
  rfc3986[i] = isalnum(i)||i == '~'||i == '-'||i == '.'||i == '_'
   ? i : 0;
  html5[i] = isalnum(i)||i == '*'||i == '-'||i == '.'||i == '_'
   ? i : (i == ' ') ? '+' : 0;
 }
 
 encode(url, enc, rfc3986);
 puts(enc);
 
 return 0;
} 

No comments:

Post a Comment