1 /***************************************************************************
2 *            mgurlparser.cpp
3 *
4 *  Tue Sep 26 16:17:23 2006
5 *  Copyright  2006  liubin,China
6 *  Email multiget@gmail.com
7 ****************************************************************************/
8 
9 /*
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23  */
24 
25 
26 #include "mgurlparser.h"
27 #include "common.h"
28 #include <iostream>
29 extern std::string gDefFtpPass;
30 
31 using namespace std;
32 ///%CF%D6%B9%DB%D7%AF%D1%CF%C2%DBCD/1-2a.mp3
33 
34 #define XDIGIT_TO_XCHAR(x) (((x) < 10) ? ((x) + '0') : ((x) - 10 + 'A'))
35 #define ISXDIGIT(x) ( ((x) >= '0' && (x) <= '9')||\
36 					  ((x) >= 'a' && (x) <= 'z')||\
37 					  ((x) >= 'A' && (x) <= 'Z') )
38 
39 
40 #define XCHAR_TO_XDIGIT(x) 	(((x) >= '0' && (x) <= '9') ? \
41 							((x) - '0') : (toupper(x) - 'A' + 10))
42 
43 enum {
44     urlchr_reserved = 1,   // rfc1738 reserved chars
45     urlchr_unsafe = 2  // rfc1738 unsafe chars
46 };
47 
48 /* Shorthands for the table: */
49 #define R  1 // reserved char
50 #define U  2 // unsafe char
51 #define RU 3 // R|U
52 
53 const static unsigned char urlchr_table[ 256 ] =
54     {
55         U, U, U, U, U, U, U, U,     /* NUL SOH STX ETX  EOT ENQ ACK BEL */
56         U, U, U, U, U, U, U, U,     /* BS  HT  LF  VT   FF  CR  SO  SI  */
57         U, U, U, U, U, U, U, U,     /* DLE DC1 DC2 DC3  DC4 NAK SYN ETB */
58         U, U, U, U, U, U, U, U,     /* CAN EM  SUB ESC  FS  GS  RS  US  */
59         U, 0, U, RU, R, U, R, 0,     /* SP  !   "   #    $   %   &   '   */
60         0, 0, 0, R, R, 0, 0, R,     /* (   )   *   +    ,   -   .   /   */
61         0, 0, 0, 0, 0, 0, 0, 0,     /* 0   1   2   3    4   5   6   7   */
62         0, 0, RU, R, U, R, U, R,     /* 8   9   :   ;    <   =   >   ?   */
63         RU, 0, 0, 0, 0, 0, 0, 0,     /* @   A   B   C    D   E   F   G   */
64         0, 0, 0, 0, 0, 0, 0, 0,     /* H   I   J   K    L   M   N   O   */
65         0, 0, 0, 0, 0, 0, 0, 0,     /* P   Q   R   S    T   U   V   W   */
66         0, 0, 0, RU, U, RU, U, 0,     /* X   Y   Z   [    \   ]   ^   _   */
67         U, 0, 0, 0, 0, 0, 0, 0,     /* `   a   b   c    d   e   f   g   */
68         0, 0, 0, 0, 0, 0, 0, 0,     /* h   i   j   k    l   m   n   o   */
69         0, 0, 0, 0, 0, 0, 0, 0,     /* p   q   r   s    t   u   v   w   */
70         0, 0, 0, U, U, U, RU, U,     /* x   y   z   {    |   }   ~   DEL */
71 
72         U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
73         U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
74         U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
75         U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
76 
77         U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
78         U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
79         U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
80         U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
81     };
82 
83 #define urlchr_test(c, mask) (urlchr_table[(unsigned char)(c)] & (mask))
84 #define URL_RESERVED_CHAR(c) urlchr_test(c, urlchr_reserved)
85 #define URL_UNSAFE_CHAR(c) urlchr_test(c, urlchr_unsafe)
86 
87 
CUrlParser()88 CUrlParser::CUrlParser()
89 {
90     m_bValidMirrorUrl = false;
91 }
92 
93 //返回false是不支持的协议或错误的地址格式
SetUrl(std::string url)94 bool CUrlParser::SetUrl( std::string url )
95 {
96 
97     Trim( url );
98 
99     m_bValidMirrorUrl = false;
100     //协议检查
101     m_protocol = UrlType( url );
102 
103     if ( m_protocol == UNKNOW_PROTOCOL )
104     {
105         return false;
106     }
107 
108     if ( m_protocol == FTP_PROTOCOL )
109     { //ftp
110 
111         //提取用户和密码
112 
113         if ( !GetUserAndPass( url, m_user, m_pass ) )
114         {
115             return false;
116         }
117 
118         //服务器和端口
119         if ( !GetServerAndPort( url, m_server, m_port ) )
120         {
121             return false;
122         }
123 
124         if ( !GetRawUrl( url, m_raw ) )
125         {
126             return false;
127         }
128 
129         //文件汉路径
130         if ( !GetPathFile( url, m_file ) )
131         {
132             return false;
133         }
134 
135         if ( m_file[ m_file.length() - 1 ] == '/' )
136         { //ftp dir not a valid file url
137             m_bValidMirrorUrl = true;
138             return false;
139         }
140 
141         //编码文件
142 
143         //Precode(m_file,m_escfile);
144         m_escfile = m_file;
145 
146         //DBGOUT("m_file="<<m_file);
147         UnEscape( m_escfile ); //m_escfile反而存放非转换串
148 
149         //DBGOUT("m_escfile="<<m_escfile);
150     }
151     else if ( m_protocol == HTTP_PROTOCOL )
152     { //http
153 
154         //提取用户和密码
155 
156         if ( !GetUserAndPass( url, m_user, m_pass ) )
157         {
158             return false;
159         }
160 
161         //服务器和端口
162         if ( !GetServerAndPort( url, m_server, m_port ) )
163         {
164             return false;
165         }
166 
167         if ( !GetRawUrl( url, m_raw ) )
168         {
169             return false;
170         }
171 
172         //文件汉路径
173         if ( !GetPathFile( url, m_file ) )
174         {
175             return false;
176         }
177 
178 
179         //编码文件
180         Precode( m_file, m_escfile );
181 
182         if ( !GetRefer( m_raw, m_refer ) )
183         {
184             return false;
185         }
186 
187     }
188     else
189     {
190         return false;
191     }
192 
193     return true;
194 }
195 
GetUser()196 string CUrlParser::GetUser()
197 {
198     return m_user;
199 }
200 
GetPass()201 string CUrlParser::GetPass()
202 {
203     return m_pass;
204 }
205 
GetServer()206 string CUrlParser::GetServer()
207 {
208     return m_server;
209 }
210 
GetFilePathName()211 string CUrlParser::GetFilePathName()
212 {
213     return m_file;
214 }
215 
GetFileName()216 std::string CUrlParser::GetFileName()
217 {
218     //only file name without path
219 
220     string::size_type pos;
221 
222     pos = m_file.find_last_of( '/' ); //for linux only
223 
224     if ( pos == std::string::npos )
225     {
226 		std::string uns=m_file;
227 		UnEscape(uns);
228 		return uns;
229 	}
230     else
231     {
232         std::string uns= m_file.substr( pos + 1, m_file.length() - pos - 1 );
233 		UnEscape(uns);
234 		return uns;
235     }
236 
237     /*
238        char fn[ 512 ];
239        strcpy( fn, m_file.c_str() );
240        int i = strlen( fn );
241 
242        while ( fn[ i ] != '/' && i > 0 )
243            i--;
244 
245        return string( fn + i + 1 );
246     */
247 
248 }
249 
250 //only http/https need refer
GetRefer()251 std::string CUrlParser::GetRefer()
252 {
253     return m_refer;
254 }
255 
GetPort()256 int CUrlParser::GetPort()
257 {
258     return m_port;
259 }
260 
261 //目前就支持两种协议,HTTP,FTP
UrlType(std::string url)262 _PROTYPE CUrlParser::UrlType( std::string url )
263 {
264     if ( url.length() < 7 )
265         return UNKNOW_PROTOCOL;  //太短了!
266 
267 #ifdef WIN32
268 
269     if ( strnicmp( url.c_str(), "ftp://", 6 ) == 0 )
270         return FTP_PROTOCOL;
271 
272     if ( strnicmp( url.c_str(), "http://", 7 ) == 0 )
273         return HTTP_PROTOCOL;
274 
275 #else
276 
277     if ( strncasecmp( url.c_str(), "ftp://", 6 ) == 0 )
278         return FTP_PROTOCOL;
279 
280     if ( strncasecmp( url.c_str(), "http://", 7 ) == 0 )
281         return HTTP_PROTOCOL;
282 
283 #endif
284 
285     return UNKNOW_PROTOCOL;
286 
287 }
288 
GetUrlType()289 _PROTYPE CUrlParser::GetUrlType()
290 {
291     return m_protocol;
292 }
293 
294 
GetEscFilePathName()295 std::string CUrlParser::GetEscFilePathName()
296 {
297     return m_escfile;
298 }
299 
300 
301 //新的提取用户和密码的函数
GetUserAndPass(const std::string & fullurl,std::string & user,std::string & pass)302 bool CUrlParser::GetUserAndPass( const std::string& fullurl, std::string& user, std::string& pass )
303 {
304     //从后向前寻找@,如果有则服务器从@后开始,到/结束
305     //如果没有,则从ftp://开始
306 
307     //是否太长而无法处理?
308 
309     if ( fullurl.length() > 510 )
310         return false;
311 
312     //考到url
313     char url[ 512 ];
314 
315     strcpy( url, fullurl.c_str() );
316 
317     //p是移动的指针
318     char * p = url;
319 
320     p += strlen( url );
321 
322     //look for @
323     //while ( *p != '@' && *p != 0 )
324     //    p++;
325 
326 findat:
327     while ( *p != '@' && p != url )
328         p--;
329 
330 	//根据提交的BUG,有时后面会有这个@字符,添加检查过滤无效的@
331 	if ( *p == '@' )
332 	{
333 		//检查是否前方的'/'位置是否是第2个'/'
334 		char *q=p;
335 		while ( *q != '/' && q > url )
336             q--;
337 
338 		if( q == url ) return false; //其实不会出现这个情况
339 		char *m = url; //从前向后找第二个'/',应该等于q
340 		while ( *m != '/' ) m++;
341 		if( q != m + 1 ) { p--; goto findat; }
342 	}
343 
344     if ( *p == '@' )
345     { //get @
346         char *e = p - 1;
347         char *p = e;
348 
349         while ( *p != '/' && p > url )
350             p--;
351 
352         if ( p == url )
353         {
354             return false; //没找到前面的斜杠,一个不合法的URL
355         }
356         else
357         {
358             char *s = p + 1;
359             //assert( e > s );
360             //int len=e-s+1;
361             //search ':'
362 
363             while ( *p != ':' && p < e )
364                 p++;
365 
366             if ( p == e )
367             {
368                 return false; //无冒号分割用户名和密码,一个不合法的URL
369             }
370 
371             if ( 30 < p - s + 1 )  //用户名超过30,有点长了
372             {
373                 return false;
374             }
375 
376             char temp[ 31 ];
377             memcpy( temp, s, p - s );
378             temp[ p - s ] = 0;
379             user = std::string( temp );
380 
381             if ( 30 < e - p + 1 )  //密码超过30,有点长了
382             {
383                 return false;
384             }
385 
386             memcpy( temp, p + 1, e - p );
387             temp[ e - p ] = 0;
388             pass = std::string( temp );
389             return true;
390         }
391     }
392     else
393     {
394         user = std::string( "anonymous" );
395         pass = gDefFtpPass;
396         return true;
397     }
398 
399     return false;
400 }
401 
GetServerAndPort(const std::string & fullurl,std::string & server,int & port)402 bool CUrlParser::GetServerAndPort( const std::string& fullurl, std::string& server, int& port )
403 {
404     //从后向前寻找@,如果有则服务器从@后开始,到/结束
405     //如果没有,则从ftp://开始
406 
407     //是否太长而无法处理?
408 
409     if ( fullurl.length() > 510 )
410         return false;
411 
412     //考到url
413     char url[ 512 ];
414 
415     strcpy( url, fullurl.c_str() );
416 
417     //p是移动的指针
418     char * p = url;
419 
420     p += strlen( url );
421 
422     //look for @
423     //while ( *p != '@' && *p != 0 )
424     //    p++;
425 
426 findat:
427     while ( *p != '@' && p != url )
428         p--;
429 
430 	//根据提交的BUG,有时后面会有这个@字符,添加检查过滤无效的@
431 	if ( *p == '@' )
432 	{
433 		//检查是否前方的'/'位置是否是第2个'/'
434 		char *q=p;
435 		while ( *q != '/' && q > url )
436             q--;
437 
438 		if( q == url ) return false; //其实不会出现这个情况
439 		char *m = url; //从前向后找第二个'/',应该等于q
440 		while ( *m != '/' ) m++;
441 		if( q != m + 1 ) { p--; goto findat; }
442 	}
443 
444     if ( *p == '@' )
445     {
446         char * s = p + 1;
447 
448         while ( *p != '/' && *p != 0 )
449             p++;
450 
451         if ( *p == '/' )
452         {
453             int len = p - s;	//包含端口在内的长度
454             //检查是否包含了端口在内
455             char *ck = p - 1;
456 
457             while ( *ck != ':' && ck > s )
458                 ck--;
459 
460             if ( ck == s )
461             { //无端口
462 
463                 if ( 256 < len + 1 )
464                     return false;  //server string too long
465 
466                 char temp[ 256 ];
467 
468                 memcpy( temp, s, len );
469 
470                 temp[ len ] = 0;
471 
472                 server = std::string( temp );
473 
474                 //按协议类型给出缺省的端口,以后可括从
475                 port = GetDefaultPort( m_protocol );
476 
477                 return true;
478 
479             }
480             else
481             {
482                 //有端口
483                 int slen = ck - s;
484                 int plen = len - slen - 1;
485 
486                 if ( 256 < slen )
487                     return false; //server too long
488 
489                 char temp[ 256 ];
490 
491                 memcpy( temp, s, slen );
492 
493                 temp[ slen ] = 0;
494 
495                 server = std::string( temp );
496 
497                 if ( plen > 5 )
498                     return false; //max port is 65535
499 
500                 char prt[ 6 ];
501 
502                 memcpy( prt, ck + 1, plen );
503 
504                 prt[ plen ] = 0;
505 
506                 //检查是否都为数字?
507                 for ( int i = 0;i < plen;i++ )
508                 {
509                     if ( prt[ i ] < '0' || prt[ i ] > '9' )
510                         return false; //wrong port
511                 }
512 
513                 port = atoi( prt );
514 
515                 return true;
516             }
517 
518         }
519         else
520         { //url wrong format
521             return false;
522         }
523     }
524     else //到了结尾没有@
525     {
526         p = url;
527 
528         while ( *p != '/' && *p != 0 )
529             p++;
530 
531         p++;
532 
533         while ( *p != '/' && *p != 0 )
534             p++;
535 
536         p++;
537 
538         char *s = p;
539 
540         while ( *p != '/' && *p != 0 )
541             p++;
542 
543         if ( *p == '/' )
544         {
545             int len = p - s;	//包含端口在内的长度
546             //检查是否包含了端口在内
547             char *ck = p - 1;
548 
549             while ( *ck != ':' && ck > s )
550                 ck--;
551 
552             if ( ck == s )
553             { //无端口
554 
555                 if ( 256 < len + 1 )
556                     return false; //server too long
557 
558                 char temp[ 256 ];
559 
560                 memcpy( temp, s, len );
561 
562                 temp[ len ] = 0;
563 
564                 server = std::string( temp );
565 
566                 //按协议类型给出缺省的端口,以后可括从
567                 port = GetDefaultPort( m_protocol );
568 
569                 return true;
570 
571             }
572             else
573             {
574                 //有端口
575                 int slen = ck - s;
576                 int plen = len - slen - 1;
577 
578                 if ( 256 < slen )
579                     return false;
580 
581                 char temp[ 256 ];
582 
583                 memcpy( temp, s, slen );
584 
585                 temp[ slen ] = 0;
586 
587                 server = std::string( temp );
588 
589                 if ( plen > 5 )
590                     return false; //max port is 65535
591 
592                 char prt[ 6 ];
593 
594                 memcpy( prt, ck + 1, plen );
595 
596                 prt[ plen ] = 0;
597 
598                 //检查是否都为数字?
599                 for ( int i = 0;i < plen;i++ )
600                 {
601                     if ( prt[ i ] < '0' || prt[ i ] > '9' )
602                         return false; //wrong port
603                 }
604 
605                 port = atoi( prt );
606 
607                 return true;
608             }
609         }
610         else
611         {
612             return false;
613         }
614     }
615 }
616 
617 
GetDefaultPort(_PROTYPE protocol)618 int CUrlParser::GetDefaultPort( _PROTYPE protocol )
619 {
620     //按协议类型给出缺省的端口,以后可括从
621 
622     switch ( protocol )
623     {
624 
625         case FTP_PROTOCOL:
626         return 21;
627 
628         case HTTP_PROTOCOL:
629         return 80;
630 
631         default:
632         return 0;
633     }
634 
635 }
636 
637 //去掉用户和密码的url
GetRawUrl(std::string & fullurl,std::string & rawurl)638 bool CUrlParser::GetRawUrl( std::string& fullurl, std::string& rawurl )
639 {
640     //ftp://user:pa@ss@www.abc.com/fdfas.txt,去掉//到@之间的内容。
641 
642     char url[ 512 ];
643     strcpy( url, fullurl.c_str() );
644 
645     char* p = url;
646 
647     while ( *p != '/' && *p != 0 )
648         p++;
649 
650     if ( *p == 0 )
651         return false;
652 
653     p++;
654 
655     while ( *p != '/' && *p != 0 )
656         p++;
657 
658     if ( *p == 0 )
659         return false;
660 
661     p++;
662 
663     //这里p指向'u'
664     char* h = p;
665 
666     p = url + strlen( url );
667 
668 findat:
669     while ( *p != '@' && p != url )
670         p--;
671 
672 	//根据提交的BUG,有时后面会有这个@字符,添加检查过滤无效的@
673 	if ( *p == '@' )
674 	{
675 		//检查是否前方的'/'位置是否是第2个'/'
676 		char *q=p;
677 		while ( *q != '/' && q > url )
678             q--;
679 
680 		if( q == url ) return false; //其实不会出现这个情况
681 		char *m = url; //从前向后找第二个'/',应该等于q
682 		while ( *m != '/' ) m++;
683 		if( q != m + 1 ) { p--; goto findat; }
684 	}
685 
686     if ( p == url )
687     {
688         rawurl = fullurl;
689 
690     }
691     else
692     {
693         p++;
694         char temp[ 512 ];
695         memcpy( temp, url, h - url );
696         strcpy( &temp[ h - url ], p );
697         rawurl = std::string( temp );
698     }
699 
700     return true;
701 }
702 
703 //从url中获得路径和文件的数据
704 //不检查是否为目录,也不进行编码
GetPathFile(std::string & fullurl,std::string & pathfile)705 bool CUrlParser::GetPathFile( std::string& fullurl, std::string& pathfile )
706 {
707     //ftp://dfasdfas.com/dfad/dfs =》/dfad/dfs
708     //找第三个'/'
709 
710     char url[ 512 ];
711     strcpy( url, fullurl.c_str() );
712 
713     char *p = url;
714 
715     while ( *p != '/' && *p != 0 )
716         p++;
717 
718     if ( *p == 0 )
719         return false;
720 
721     p++;
722 
723     while ( *p != '/' && *p != 0 )
724         p++;
725 
726     if ( *p == 0 )
727         return false;
728 
729     p++;
730 
731     while ( *p != '/' && *p != 0 )
732         p++;
733 
734     if ( *p == 0 )
735         return false;
736 
737     if ( 510 < int( strlen( url ) - ( p - url ) ) )
738     {
739         return false; //too long
740     }
741 
742     char temp[ 512 ];
743     memcpy( temp, p, strlen( url ) - ( p - url ) );
744     temp[ strlen( url ) - ( p - url ) ] = 0;
745     pathfile = std::string( temp );
746     return true;
747 }
748 
749 //提取refer
GetRefer(std::string rawurl,std::string & refer)750 bool CUrlParser::GetRefer( std::string rawurl, std::string& refer )
751 {
752 
753     if ( !m_refer.empty() )
754         return true; //already have set refer
755 
756     //找最后一个'/',之前的就算refer
757 
758     char url[ 512 ];
759 
760     strcpy( url, rawurl.c_str() );
761 
762     char* p = url + strlen( url );
763 
764     while ( p != url && *p != '/' )
765         p--;
766 
767     if ( p == url )
768     {
769         refer.clear();
770     }
771     else
772     {
773         if ( 512 < p - url )
774             return false;
775 
776         char temp[ 512 ];
777 
778         memcpy( temp, url, p - url );
779 
780         temp[ p - url ] = 0;
781 
782         refer = std::string( temp );
783 
784     }
785 
786     return true;
787 }
788 
Precode(const std::string & pathfile,std::string & escfile)789 void CUrlParser::Precode( const std::string& pathfile, std::string& escfile )
790 {
791     char * str_new;
792     int str_new_len;
793     char *ptr, *pptr;
794 
795     // get the length of the new string
796     ptr = ( char* ) pathfile.c_str();
797     str_new_len = 0;
798 
799     while ( *ptr != '\0' )
800     {
801         if ( *ptr == '%' )
802         {
803             if ( isxdigit( ptr[ 1 ] ) && isxdigit( ptr[ 2 ] ) )
804             {
805                 str_new_len += 3;
806                 ptr += 3;
807             }
808             else
809             {
810                 str_new_len += 3;
811                 ptr += 1;
812             }
813         }
814         else if ( URL_UNSAFE_CHAR( *ptr ) && !URL_RESERVED_CHAR( *ptr ) )
815         {
816             str_new_len += 3;
817             ptr += 1;
818         }
819         else
820         {
821             str_new_len += 1;
822             ptr += 1;
823         }
824     } // end of while
825 
826     /* encode the url */
827     str_new = new char[ str_new_len + 1 ];
828 
829     ptr = ( char* ) pathfile.c_str();
830 
831     pptr = str_new;
832 
833     while ( *ptr != '\0' )
834     {
835         if ( *ptr == '%' )
836         {
837             if ( isxdigit( ptr[ 1 ] ) && isxdigit( ptr[ 2 ] ) )
838             {
839                 strncpy( pptr, ptr, 3 );
840                 ptr += 3;
841                 pptr += 3;
842             }
843             else
844             {
845                 strncpy( pptr, "%25", 3 );
846                 ptr += 1;
847                 pptr += 3;
848             }
849         }
850         else if ( URL_UNSAFE_CHAR( *ptr ) && !URL_RESERVED_CHAR( *ptr ) )
851         {
852             pptr[ 0 ] = '%';
853             pptr[ 1 ] = XDIGIT_TO_XCHAR( ( ( unsigned char ) * ptr ) >> 4 );
854             pptr[ 2 ] = XDIGIT_TO_XCHAR( ( ( unsigned char ) * ptr ) & 0x0f );
855             ptr += 1;
856             pptr += 3;
857         }
858         else
859         {
860             *pptr = *ptr;
861             ptr += 1;
862             pptr += 1;
863         }
864     } // end of while
865 
866     *pptr = '\0';
867 
868     escfile = std::string( str_new );
869 
870     delete[] str_new;
871 
872 }
873 
GetRawUrl()874 std::string CUrlParser::GetRawUrl()
875 {
876     return m_raw;
877 }
878 
879 //把user,pass添加到url中
RebuildUrl(std::string & fullurl,std::string user,std::string pass,std::string & rebuild)880 bool CUrlParser::RebuildUrl(
881     std::string& fullurl, std::string user, std::string pass, std::string& rebuild )
882 {
883     std::string raw;
884 
885     if ( user.empty() || pass.empty() )
886         return false;
887 
888     if ( !GetRawUrl( fullurl, raw ) )
889         return false;
890 
891     string::size_type pos = raw.find( "//", 0 );
892 
893     if ( pos == string::npos )
894         return false;
895 
896     raw.insert( pos + 2, user + ":" + pass + "@" );
897 
898     rebuild = raw;
899 
900     return true;
901 }
902 
SetRefer(std::string & refer)903 void CUrlParser::SetRefer( std::string& refer )
904 {
905     m_refer = refer;
906 }
907 
IsValidMirror()908 bool CUrlParser::IsValidMirror()
909 {
910     return m_bValidMirrorUrl;
911 }
912 
UnEscape(std::string & str)913 void CUrlParser::UnEscape( std::string& str )
914 {
915     char buf[ 512 ];
916     strcpy( buf, str.c_str() );
917     UnEscape( buf );
918     str = std::string( buf );
919 }
920 
UnEscape(char * s)921 void CUrlParser::UnEscape ( char *s )
922 {
923     char * t = s;
924     char *h = s;
925 
926     for ( ; *h; h++, t++ )
927     {
928         if ( *h != '%' )
929         {
930             *t = *h;
931         }
932         else
933         {
934             unsigned char c;
935 
936             if ( !h[ 1 ] || !h[ 2 ] || !( ISXDIGIT ( h[ 1 ] ) && ISXDIGIT ( h[ 2 ] ) ) )
937             {
938                 *t = *h;
939                 continue;
940             }
941 
942             //c = X2DIGITS_TO_NUM (h[1], h[2]);
943             //			printf("h[1]=%c,h[2]=%c\n",h[1],h[2]);
944 
945             unsigned char k, m;
946 
947             k = XCHAR_TO_XDIGIT( h[ 1 ] );
948 
949             m = XCHAR_TO_XDIGIT( h[ 2 ] );
950 
951             c = k * 16 + m;
952 
953             //	  		if (c == 0)
954             //	    	{
955             //DBGOUT("c==0");
956             //				*t=*h;
957             //				continue;
958             //			}
959 
960             *t = c;
961 
962             h += 2;
963         }
964     }
965 
966     *t = '\0';
967 }
968