URL分解之InternetCrackUrl函数——就是python的urlparse

URL分解之InternetCrackUrl函数

 

背景

近期使用WININET库写的一个数据上传、下载的客户端小程序,上传数据到网站服务器和从网站服务器下载数据到本地。由于,对WININET库部分用的比较少,所以,对这部分知识比较陌生。也遇到一些波折,其中一个就是URL的分解问题。

起初,使用WININET库连接服务器并发送访问请求的时候,调用这两个API函数:InternetConnect 和 HttpOpenRequest,需要填写网站的信息。我知道URL是什么,但是需要从URL中手动提取信息,比较麻烦。

后来了解到,原来WININET库专门提供了 InternetCrackUrl 函数来对URL进行分解,提取URL中的信息。现在,总结一下 InternetCrackUrl 的用法。

 

函数介绍

下面是 MSDN 2001 解释:

Cracks a URL into its component parts.

Syntax

BOOL InternetCrackUrl(
    LPCTSTR lpszUrl,
    DWORD dwUrlLength,
    DWORD dwFlags,
    LPURL_COMPONENTS lpUrlComponents
);

Parameters

  • lpszUrl

    [in] Pointer to a string that contains the canonical URL to crack.

  • dwUrlLength

    [in] Unsigned long integer value that contains the length of the lpszUrl string in TCHAR, or zero if lpszUrl is an ASCIIZ string.

  • dwFlags

    [in] Unsigned long integer value that contains the flags controlling the operation. This can be one of the following values:ICU_DECODEConverts encoded characters back to their normal form. This can be used only if the user provides buffers in the URL_COMPONENTS structure to copy the components into.ICU_ESCAPEConverts all escape sequences (%xx) to their corresponding characters. This can be used only if the user provides buffers in the URL_COMPONENTS structure to copy the components into.

  • lpUrlComponents

    [in, out] Pointer to a URL_COMPONENTS structure that receives the URL components.

Return Value

Returns TRUE if the function succeeds, or FALSE otherwise. To get extended error information, call GetLastError.

其中,URL_COMPONENTS 结构体的内容是:

typedef struct {
    DWORD dwStructSize;
    LPTSTR lpszScheme;
    DWORD dwSchemeLength;
    INTERNET_SCHEME nScheme;
    LPTSTR lpszHostName;
    DWORD dwHostNameLength;
    INTERNET_PORT nPort;
    LPTSTR lpszUserName;
    DWORD dwUserNameLength;
    LPTSTR lpszPassword;
    DWORD dwPasswordLength;
    LPTSTR lpszUrlPath;
    DWORD dwUrlPathLength;
    LPTSTR lpszExtraInfo;
    DWORD dwExtraInfoLength;
} URL_COMPONENTS, *LPURL_COMPONENTS;

dwStructSize用于表明该结构体大小,一般我们都是传递sizeof(URL_COMPONENTS)。

lpszSheme指向一段用于保存协议类型的内存空间。 dwSchemeLength用于描述传入空间的大小(以TCHARS为单位的大小,下面其他空间大小描述字段都是以TCHARS单位)。

lpHostName指向一段用于保存域名信息的内存空间。 dwHostNameLength用于描述传入空间的大小。 nPort用于接收端口号。 lpszUserName和lpszPassword分别用于保存URL中携带的用户名和密码。 lpszUrlPath指向保存URL的路径——不包含域名的一段内存空间。 lpszExtraInfo指向保存URL中参数信息的一段内容空间。

 

使用例子

 

1. 导入WININET库

# include <WinInet.h>
# pragma comment(lib, "Wininet.lib")

 

2. 调用 InternetCrackUrl 函数

传入要分解的URL链接字符串,调用 InternetCrackUrl 函数分解,并输出分解结果。

void CrackURL(char *pszURL)
{
	URL_COMPONENTS uc = { 0 };
	char szScheme[MAX_PATH] = { 0 };
	char szHostName[MAX_PATH] = { 0 };
	char szUserName[MAX_PATH] = { 0 };
	char szPassword[MAX_PATH] = { 0 };
	char szUrlPath[MAX_PATH] = { 0 };
	char szExtraInfo[MAX_PATH] = { 0 };
	// 初始化缓冲区
	::RtlZeroMemory(&uc, sizeof(uc));
	::RtlZeroMemory(szScheme, MAX_PATH);
	::RtlZeroMemory(szHostName, MAX_PATH);
	::RtlZeroMemory(szUserName, MAX_PATH);
	::RtlZeroMemory(szPassword, MAX_PATH);
	::RtlZeroMemory(szUrlPath, MAX_PATH);
	::RtlZeroMemory(szExtraInfo, MAX_PATH);
	// 设置 URL_COMPONENTS 结构体数据
	uc.dwStructSize = sizeof(uc);
	uc.lpszScheme = szScheme;
	uc.lpszHostName = szHostName;
	uc.lpszUserName = szUserName;
	uc.lpszPassword = szPassword;
	uc.lpszUrlPath = szUrlPath;
	uc.lpszExtraInfo = szExtraInfo;

	uc.dwSchemeLength = MAX_PATH;
	uc.dwHostNameLength = MAX_PATH;
	uc.dwUserNameLength = MAX_PATH;
	uc.dwPasswordLength = MAX_PATH;
	uc.dwUrlPathLength = MAX_PATH;
	uc.dwExtraInfoLength = MAX_PATH;
	// 调用函数
	if (FALSE == ::InternetCrackUrl(pszURL, 0, 0, &uc))
	{
		printf("Error[%d]\n", ::GetLastError());
	}
	// 显示分解结果
	printf("szScheme = %s\n", szScheme);
	printf("szHostName = %s\n", szHostName);
	printf("szUserName = %s\n", szUserName);
	printf("szPassword = %s\n", szPassword);
	printf("szUrlPath = %s\n", szUrlPath);
	printf("szExtraInfo = %s\n", szExtraInfo);
	printf("uc.nPort = %d\n", uc.nPort);
}

我们传入的URL为:http://www.demongan.com/upload.asp?file=520.zip 。主函数部分的代码为:

int _tmain(int argc, _TCHAR* argv[])
{
	char szURL[] = "http://www.demongan.com/upload.asp?file=520.zip";
	printf("URL: %s\n", szURL);
	CrackURL(szURL);
	printf("\n");

	system("pause");
	return 0;
}

 

3. 运行结果

大家可以看到分解的结果显示,其中:

协议类型szScheme为http;

传输端口号uc.nPort为80;

域名szHostName为 www.demongan.com ;

用户名szUserName为空;

用户密码szPassword为空;

URL路径szUrlPath为/upload.asp;

URL中的参数信息szExtraInfo为?file=520.zip。

 

总结

单单这个理解不是很难,主要是之前没有接触过这方面的知识,所以才会感到陌生,希望方便大家的参考吧。

 

参考

参考自《Windows黑客编程技术详解》一书

posted @ 2022-12-27 15:03  bonelee  阅读(259)  评论(0编辑  收藏  举报