1. 程式人生 > >C語言的url轉碼,提交內容到網站

C語言的url轉碼,提交內容到網站

2011-09-07

url提交資訊為何要轉碼呢?因為url本身會有很多特殊字元。而提交的引數中如果再有特殊字元的話,url就不能區分哪些是引數內容,哪些是分隔符。尤其是unicode,gb18030,big5等多位元組的編碼,不知道里面會隱藏什麼位元組,因此必須全部轉碼。

好像C語言裡面沒有現成的轉碼函式。參考張老師專欄,從php的轉碼中引出兩個函式,進行轉碼。

字元”a”-“z”,”A”-“Z”,”0”-“9”,”.”,”-“,”*“,和”_” 都不被編碼,維持原值; 空格” “被轉換為加號”+”。 其他每個位元組都被表示成”%xy”格式的由3個字元組成的字串,編碼為UTF-8。

標頭檔案

int url_decode(char *str, int len);
char *url_encode(char const *s, int len, int *new_length);

c 檔案:

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>


/*
本文程式碼為從PHP程式碼中修改而來,只保留了2個函式。

int url_decode(char *str, int len);
char *url_encode(char const *s, int len, int *new_length);



URL編碼做了如下操作:


字元"a"-"z","A"-"Z","0"-"9",".","-","*",和"_" 都不被編碼,維持原值;

空格" "被轉換為加號"+"。

其他每個位元組都被表示成"%xy"格式的由3個字元組成的字串,編碼為UTF-8。
*/
static unsigned char hexchars[] = "0123456789ABCDEF";

static int htoi(char *s)
{
	int value;
	int c;

	c = ((unsigned char *)s)[0];
	if (isupper(c))
		c = tolower(c);
	value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;

	c = ((unsigned char *)s)[1];
	if (isupper(c))
		c = tolower(c);
	value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;

	return (value);
}


char *url_encode(char const *s, int len, int *new_length)
{
	register unsigned char c;
	unsigned char *to, *start;
	unsigned char const *from, *end;

	from = (unsigned char *)s;
	end  = (unsigned char *)s + len;
	start = to = (unsigned char *) calloc(1, 3*len+1);

	while (from < end)
	{
		c = *from++;

		if (c == ' ')
		{
			*to++ = '+';
		}
		else if ((c < '0' && c != '-' && c != '.') ||
			(c < 'A' && c > '9') ||
			(c > 'Z' && c < 'a' && c != '_') ||
			(c > 'z'))
		{
			to[0] = '%';
			to[1] = hexchars[c >> 4];
			to[2] = hexchars[c & 15];
			to += 3;
		}
		else
		{
			*to++ = c;
		}
	}
	*to = 0;
	if (new_length)
	{
		*new_length = to - start;
	}
	return (char *) start;
}


int url_decode(char *str, int len)
{
	char *dest = str;
	char *data = str;

	while (len--)
	{
		if (*data == '+')
		{
			*dest = ' ';
		}
		else if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) && isxdigit((int) *(data + 2)))
		{
			*dest = (char) htoi(data + 1);
			data += 2;
			len -= 2;
		}
		else
		{
			*dest = *data;
		}
		data++;
		dest++;
	}
	*dest = '/0';
	return dest - str;
}

使用方式:

#include <wininet.h>
//定義一個傳送函式
void PostHttpRequest(const char* url, const char* param)
{
	HINTERNET hSession = InternetOpen("MobileAgent", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
	if ( hSession != NULL )
	{
		HINTERNET hConnection = InternetConnect(hSession,
												url,
												INTERNET_DEFAULT_HTTP_PORT,
												NULL,
												NULL,
												INTERNET_SERVICE_HTTP,
												0,
												NULL);
		if ( hConnection != NULL )
		{
			HINTERNET hRequest = HttpOpenRequest(hConnection,
												"POST",
												param,
												NULL,
												NULL,
												(const char**)"*/*\0",
												0,
												NULL);
			if ( hRequest != NULL )
			{
				HttpSendRequest(hRequest, NULL, 0, NULL, 0);
				InternetCloseHandle(hRequest);
			}
			InternetCloseHandle(hConnection);
		}
		InternetCloseHandle(hSession);
	}
}





#define URL_ADDFEEDBACK ("http://abloz.com/")
void sendurl()
{
    char buf[MAX_PATH];
	char szUserName[MAX_PATH]={"周海漢 ablozhou abloz.com"};
	char szContent[MAX_PATH]={"這什麼網站啊?盡是些亂碼dja;a d;404 &^$ # %$()!~?'、%“”;"};
	int lenu = strlen(szUserName);
	int lenc = strlen(szContent);

	sprintf(buf, "test.php?username=%s&content;=%s", url_encode(szUserName,lenu,&lenu),url_encode(szContent,lenc,&lenc));

PostHttpRequest(URL_ADDFEEDBACK,buf);
}

本文在window7 下用vs 2010編譯測試通過。

如非註明轉載, 均為原創. 本站遵循知識共享CC協議,轉載請註明來源