判断URL是否合法

原帖: http://www.cppblog.com/smagle/archive/2010/01/08/105184.html


首先声明四点:

  • 本代码是我在MFC中写的,用到了很多MFC种的类,如果要移植到其他开发环境,请自行修改。
  • 因为实际具体要求,所有很多地方可能与大家使用的不同,原理代码贴出来,修改就简单了^_^。
  • 本代码仅仅是一个弱检查,如果有大牛写出了C/C++的正则式判断代码,请一定要给我邮一份,感激涕零。
  • 转载请注明出处,也就是本随笔地址啦。

原理:

URL是否合法的依据是RFC2369,可以 点击这里查看RFC2369

本段代码的原理很简单,举一个URL为例: http://xxx.xxx.xx/ffd?=dd22 ,如何判断是否合法?
如果你用过MFC中AfxParseUrl这个函数,我相信你马上就能明白90%,剩下的10%我后面再讲,首先看下这个函数原型。

BOOL AFXAPI AfxParseURL(
   LPCTSTR pstrURL, // 待解析的URL, http://xxx.xxx.xx/ffd?=dd22
   DWORD& dwServiceType, // 解析出来的服务类型,例如http,ftp之类的,上面例子出来为1(AFX_INET_SERVICE_HTTP)
   CString& strServer, // 上面例子中的xxx.xxx.xx
   CString& strObject, // 上面例子中的/ffd?=dd22
   INTERNET_PORT& nPort // 端口
);

这个函数解析成功返回true,否则false。当然,即便它返回true也不代表这个URL就是合法的,为什么呢?看这个例子:http://xxx/dd.html。所以重点变成了判断 strServer 这个参数是否合法,也就是我上面所说的10%了。

服务器域名有很多子域名,例如asd.page1.cppblog.com、ddd.sina.com.cn。弃繁从简,倒过来,如果找到多个.分开的字段,并且最后一个域名是正确的,就是正确的URL格式。有个例外,那就是纯IP,例如http://192.168.3.124/index.html。
OK,原理完了,上代码。

代码:

// 校验URL是否合法文件路径,依据为rfc2396
// 这个函数只做粗略的校验,不完全符合RFC2369
// 仅支持IPV4
BOOL CAddDlg::CheckURL( const CString &szUrl, CString &szMsg)
{
    DWORD dwService = 0;
    DWORD dwValid = AFX_INET_SERVICE_FTP|AFX_INET_SERVICE_HTTP|AFX_INET_SERVICE_HTTPS|AFX_INET_SERVICE_FILE;
    CString strServer;  
    CString strObject;  
    INTERNET_PORT port; 

    BOOL bValid = AfxParseURL(szUrl, dwService, strServer, strObject, port);  
     if ( !bValid || strObject.IsEmpty() || strObject == "/" || strServer == "localhost"
        )
    { 
        szMsg = szUrl + " \n不是一个合法的下载地址URL";
         return FALSE;  
    }
     else // 开始检验解析出来的部分
    {
         if ( (dwService & dwValid) == 0 )
        {
            szMsg =  szUrl + "\n不支持的服务类型,目前仅支持http,https,ftp,file";
             return FALSE;
        }
         if ( (dwService & AFX_INET_SERVICE_FILE) != 0 ) // file协议直接返回TRUE
        {
             return TRUE;
        }

        CStringArray arr;
        CString dom;
         int i, size = 0;
    
        ExtractString(arr, strServer, ".");
        size = arr.GetCount();
         if ( size == 0 )
             return TRUE;
        dom = arr.GetAt( size-1 );

         for ( i = 0; i < size; i++)
        {
             if ( IsGb2312(arr.GetAt(i)) )
            {
                szMsg = szUrl + " \n不支持包含中文的域名";
                 return FALSE;
            }
        }

         // 先看下是不是192.168.3.2这种IP形式的地址
         if ( IsNumber(dom) )
        {
             bool bt =  true;
             if ( size == 4 )
            {
                 for ( i = 0; i < size; i++ )
                {
                    UINT32 num = CString2UINT32(dom);
                     if (num < 0 && num > 255)
                    {
                        bt =  false;
                         continue;
                    }
                }
                 if ( bt )
                     return TRUE;
            }
        }
         else  if (size > 1) // 查一下域名表
        {
             for (i = 0; i < DOMAIN_NUM; i++)
            {
                 if (dom == szDomainTable[i])
                     return TRUE;
            }
        }
        szMsg = szUrl + " \n不是一个合法的下载地址URL";
         return FALSE;
    }
     return TRUE;
}

上面代码中用到的几个函数如 ExtractString、IsGb2312都很简单,为不增加代码长度影响阅读,故不再贴出。
szDomainTable是我定义的一个域名数组,可以 点击这里下载domain.h

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值