Haggard的文章

  • 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黑客编程技术详解》一书
    1  留言 2018-11-06 22:06:48

发送私信

所有的道别里,我还是最喜欢明天见

13
文章数
12
评论数
eject