]>
git.saurik.com Git - apt.git/blob - apt-pkg/contrib/strutl.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: strutl.cc,v 1.40 2001/05/27 05:36:04 jgg Exp $
4 /* ######################################################################
6 String Util - Some useful string functions.
8 These have been collected from here and there to do all sorts of useful
9 things to strings. They are useful in file parsers, URI handlers and
10 especially in APT methods.
12 This source is placed in the Public Domain, do with it what you will
13 It was originally written by Jason Gunthorpe <jgg@gpu.srv.ualberta.ca>
15 ##################################################################### */
19 #pragma implementation "apt-pkg/strutl.h"
22 #include <apt-pkg/strutl.h>
23 #include <apt-pkg/fileutl.h>
24 #include <apt-pkg/error.h>
39 // strstrip - Remove white space from the front and back of a string /*{{{*/
40 // ---------------------------------------------------------------------
41 /* This is handy to use when parsing a file. It also removes \n's left
42 over from fgets and company */
43 char *_strstrip(char *String
)
45 for (;*String
!= 0 && (*String
== ' ' || *String
== '\t'); String
++);
50 char *End
= String
+ strlen(String
) - 1;
51 for (;End
!= String
- 1 && (*End
== ' ' || *End
== '\t' || *End
== '\n' ||
52 *End
== '\r'); End
--);
58 // strtabexpand - Converts tabs into 8 spaces /*{{{*/
59 // ---------------------------------------------------------------------
61 char *_strtabexpand(char *String
,size_t Len
)
63 for (char *I
= String
; I
!= I
+ Len
&& *I
!= 0; I
++)
67 if (I
+ 8 > String
+ Len
)
73 /* Assume the start of the string is 0 and find the next 8 char
79 Len
= 8 - ((String
- I
) % 8);
87 memmove(I
+ Len
,I
+ 1,strlen(I
) + 1);
88 for (char *J
= I
; J
+ Len
!= I
; *I
= ' ', I
++);
93 // ParseQuoteWord - Parse a single word out of a string /*{{{*/
94 // ---------------------------------------------------------------------
95 /* This grabs a single word, converts any % escaped characters to their
96 proper values and advances the pointer. Double quotes are understood
97 and striped out as well. This is for URI/URL parsing. It also can
98 understand [] brackets.*/
99 bool ParseQuoteWord(const char *&String
,string
&Res
)
101 // Skip leading whitespace
102 const char *C
= String
;
103 for (;*C
!= 0 && *C
== ' '; C
++);
107 // Jump to the next word
108 for (;*C
!= 0 && isspace(*C
) == 0; C
++)
112 for (C
++; *C
!= 0 && *C
!= '"'; C
++);
118 for (C
++; *C
!= 0 && *C
!= ']'; C
++);
124 // Now de-quote characters
127 const char *Start
= String
;
129 for (I
= Buffer
; I
< Buffer
+ sizeof(Buffer
) && Start
!= C
; I
++)
131 if (*Start
== '%' && Start
+ 2 < C
)
136 *I
= (char)strtol(Tmp
,0,16);
149 // Skip ending white space
150 for (;*C
!= 0 && isspace(*C
) != 0; C
++);
155 // ParseCWord - Parses a string like a C "" expression /*{{{*/
156 // ---------------------------------------------------------------------
157 /* This expects a series of space separated strings enclosed in ""'s.
158 It concatenates the ""'s into a single string. */
159 bool ParseCWord(const char *&String
,string
&Res
)
161 // Skip leading whitespace
162 const char *C
= String
;
163 for (;*C
!= 0 && *C
== ' '; C
++);
169 if (strlen(String
) >= sizeof(Buffer
))
176 for (C
++; *C
!= 0 && *C
!= '"'; C
++)
185 if (C
!= String
&& isspace(*C
) != 0 && isspace(C
[-1]) != 0)
187 if (isspace(*C
) == 0)
197 // QuoteString - Convert a string into quoted from /*{{{*/
198 // ---------------------------------------------------------------------
200 string
QuoteString(string Str
,const char *Bad
)
203 for (const char *I
= Str
.c_str(); *I
!= 0; I
++)
205 if (strchr(Bad
,*I
) != 0 || isprint(*I
) == 0 ||
206 *I
<= 0x20 || *I
>= 0x7F)
209 sprintf(Buf
,"%%%02x",(int)*I
);
218 // DeQuoteString - Convert a string from quoted from /*{{{*/
219 // ---------------------------------------------------------------------
220 /* This undoes QuoteString */
221 string
DeQuoteString(string Str
)
224 for (const char *I
= Str
.c_str(); *I
!= 0; I
++)
226 if (*I
== '%' && I
+ 2 < Str
.c_str() + Str
.length())
232 Res
+= (char)strtol(Tmp
,0,16);
243 // SizeToStr - Convert a long into a human readable size /*{{{*/
244 // ---------------------------------------------------------------------
245 /* A max of 4 digits are shown before conversion to the next highest unit.
246 The max length of the string will be 5 chars unless the size is > 10
248 string
SizeToStr(double Size
)
257 /* bytes, KiloBytes, MegaBytes, GigaBytes, TeraBytes, PetaBytes,
258 ExaBytes, ZettaBytes, YottaBytes */
259 char Ext
[] = {'\0','k','M','G','T','P','E','Z','Y'};
263 if (ASize
< 100 && I
!= 0)
265 sprintf(S
,"%.1f%c",ASize
,Ext
[I
]);
271 sprintf(S
,"%.0f%c",ASize
,Ext
[I
]);
281 // TimeToStr - Convert the time into a string /*{{{*/
282 // ---------------------------------------------------------------------
283 /* Converts a number of seconds to a hms format */
284 string
TimeToStr(unsigned long Sec
)
292 sprintf(S
,"%lid %lih%lim%lis",Sec
/60/60/24,(Sec
/60/60) % 24,(Sec
/60) % 60,Sec
% 60);
298 sprintf(S
,"%lih%lim%lis",Sec
/60/60,(Sec
/60) % 60,Sec
% 60);
304 sprintf(S
,"%lim%lis",Sec
/60,Sec
% 60);
308 sprintf(S
,"%lis",Sec
);
315 // SubstVar - Substitute a string for another string /*{{{*/
316 // ---------------------------------------------------------------------
317 /* This replaces all occurances of Subst with Contents in Str. */
318 string
SubstVar(string Str
,string Subst
,string Contents
)
320 string::size_type Pos
= 0;
321 string::size_type OldPos
= 0;
324 while (OldPos
< Str
.length() &&
325 (Pos
= Str
.find(Subst
,OldPos
)) != string::npos
)
327 Temp
+= string(Str
,OldPos
,Pos
) + Contents
;
328 OldPos
= Pos
+ Subst
.length();
334 return Temp
+ string(Str
,OldPos
);
337 string
SubstVar(string Str
,const struct SubstVar
*Vars
)
339 for (; Vars
->Subst
!= 0; Vars
++)
340 Str
= SubstVar(Str
,Vars
->Subst
,*Vars
->Contents
);
344 // URItoFileName - Convert the uri into a unique file name /*{{{*/
345 // ---------------------------------------------------------------------
346 /* This converts a URI into a safe filename. It quotes all unsafe characters
347 and converts / to _ and removes the scheme identifier. The resulting
348 file name should be unique and never occur again for a different file */
349 string
URItoFileName(string URI
)
351 // Nuke 'sensitive' items
354 U
.Password
= string();
357 // "\x00-\x20{}|\\\\^\\[\\]<>\"\x7F-\xFF";
358 URI
= QuoteString(U
,"\\|{}[]<>\"^~_=!@#$%^&*");
359 char *J
= const_cast<char *>(URI
.c_str());
366 // Base64Encode - Base64 Encoding routine for short strings /*{{{*/
367 // ---------------------------------------------------------------------
368 /* This routine performs a base64 transformation on a string. It was ripped
369 from wget and then patched and bug fixed.
371 This spec can be found in rfc2045 */
372 string
Base64Encode(string S
)
375 static char tbl
[64] = {'A','B','C','D','E','F','G','H',
376 'I','J','K','L','M','N','O','P',
377 'Q','R','S','T','U','V','W','X',
378 'Y','Z','a','b','c','d','e','f',
379 'g','h','i','j','k','l','m','n',
380 'o','p','q','r','s','t','u','v',
381 'w','x','y','z','0','1','2','3',
382 '4','5','6','7','8','9','+','/'};
384 // Pre-allocate some space
386 Final
.reserve((4*S
.length() + 2)/3 + 2);
388 /* Transform the 3x8 bits to 4x6 bits, as required by
390 for (const char *I
= S
.c_str(); I
< (S
.c_str() + S
.length()); I
+= 3)
392 char Bits
[3] = {0,0,0};
394 if (I
+ 1 < S
.c_str() + S
.length())
396 if (I
+ 2 < S
.c_str() + S
.length())
399 Final
+= tbl
[Bits
[0] >> 2];
400 Final
+= tbl
[((Bits
[0] & 3) << 4) + (Bits
[1] >> 4)];
402 if (I
+ 1 >= S
.c_str() + S
.length())
405 Final
+= tbl
[((Bits
[1] & 0xf) << 2) + (Bits
[2] >> 6)];
407 if (I
+ 2 >= S
.c_str() + S
.length())
410 Final
+= tbl
[Bits
[2] & 0x3f];
413 /* Apply the padding elements, this tells how many bytes the remote
414 end should discard */
415 if (S
.length() % 3 == 2)
417 if (S
.length() % 3 == 1)
423 // stringcmp - Arbitary string compare /*{{{*/
424 // ---------------------------------------------------------------------
425 /* This safely compares two non-null terminated strings of arbitary
427 int stringcmp(const char *A
,const char *AEnd
,const char *B
,const char *BEnd
)
429 for (; A
!= AEnd
&& B
!= BEnd
; A
++, B
++)
433 if (A
== AEnd
&& B
== BEnd
)
444 // stringcasecmp - Arbitary case insensitive string compare /*{{{*/
445 // ---------------------------------------------------------------------
447 int stringcasecmp(const char *A
,const char *AEnd
,const char *B
,const char *BEnd
)
449 for (; A
!= AEnd
&& B
!= BEnd
; A
++, B
++)
450 if (toupper(*A
) != toupper(*B
))
453 if (A
== AEnd
&& B
== BEnd
)
459 if (toupper(*A
) < toupper(*B
))
464 // LookupTag - Lookup the value of a tag in a taged string /*{{{*/
465 // ---------------------------------------------------------------------
466 /* The format is like those used in package files and the method
467 communication system */
468 string
LookupTag(string Message
,const char *Tag
,const char *Default
)
470 // Look for a matching tag.
471 int Length
= strlen(Tag
);
472 for (const char *I
= Message
.c_str(); I
+ Length
< Message
.c_str() + Message
.length(); I
++)
475 if (I
[Length
] == ':' && stringcasecmp(I
,I
+Length
,Tag
) == 0)
477 // Find the end of line and strip the leading/trailing spaces
480 for (; isspace(*I
) != 0 && *I
!= 0; I
++);
481 for (J
= I
; *J
!= '\n' && *J
!= 0; J
++);
482 for (; J
> I
&& isspace(J
[-1]) != 0; J
--);
487 for (; *I
!= '\n' && *I
!= 0; I
++);
490 // Failed to find a match
496 // StringToBool - Converts a string into a boolean /*{{{*/
497 // ---------------------------------------------------------------------
498 /* This inspects the string to see if it is true or if it is false and
499 then returns the result. Several varients on true/false are checked. */
500 int StringToBool(string Text
,int Default
)
503 int Res
= strtol(Text
.c_str(),&End
,0);
504 if (End
!= Text
.c_str() && Res
>= 0 && Res
<= 1)
507 // Check for positives
508 if (strcasecmp(Text
.c_str(),"no") == 0 ||
509 strcasecmp(Text
.c_str(),"false") == 0 ||
510 strcasecmp(Text
.c_str(),"without") == 0 ||
511 strcasecmp(Text
.c_str(),"off") == 0 ||
512 strcasecmp(Text
.c_str(),"disable") == 0)
515 // Check for negatives
516 if (strcasecmp(Text
.c_str(),"yes") == 0 ||
517 strcasecmp(Text
.c_str(),"true") == 0 ||
518 strcasecmp(Text
.c_str(),"with") == 0 ||
519 strcasecmp(Text
.c_str(),"on") == 0 ||
520 strcasecmp(Text
.c_str(),"enable") == 0)
526 // TimeRFC1123 - Convert a time_t into RFC1123 format /*{{{*/
527 // ---------------------------------------------------------------------
528 /* This converts a time_t into a string time representation that is
529 year 2000 complient and timezone neutral */
530 string
TimeRFC1123(time_t Date
)
532 struct tm Conv
= *gmtime(&Date
);
535 const char *Day
[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
536 const char *Month
[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul",
537 "Aug","Sep","Oct","Nov","Dec"};
539 sprintf(Buf
,"%s, %02i %s %i %02i:%02i:%02i GMT",Day
[Conv
.tm_wday
],
540 Conv
.tm_mday
,Month
[Conv
.tm_mon
],Conv
.tm_year
+1900,Conv
.tm_hour
,
541 Conv
.tm_min
,Conv
.tm_sec
);
545 // ReadMessages - Read messages from the FD /*{{{*/
546 // ---------------------------------------------------------------------
547 /* This pulls full messages from the input FD into the message buffer.
548 It assumes that messages will not pause during transit so no
549 fancy buffering is used. */
550 bool ReadMessages(int Fd
, vector
<string
> &List
)
557 int Res
= read(Fd
,End
,sizeof(Buffer
) - (End
-Buffer
));
558 if (Res
< 0 && errno
== EINTR
)
561 // Process is dead, this is kind of bad..
566 if (Res
< 0 && errno
== EAGAIN
)
573 // Look for the end of the message
574 for (char *I
= Buffer
; I
+ 1 < End
; I
++)
576 if (I
[0] != '\n' || I
[1] != '\n')
579 // Pull the message out
580 string
Message(Buffer
,0,I
-Buffer
);
583 for (; I
< End
&& *I
== '\n'; I
++);
585 memmove(Buffer
,I
,End
-Buffer
);
588 List
.push_back(Message
);
593 if (WaitFd(Fd
) == false)
598 // MonthConv - Converts a month string into a number /*{{{*/
599 // ---------------------------------------------------------------------
600 /* This was lifted from the boa webserver which lifted it from 'wn-v1.07'
601 Made it a bit more robust with a few touppers though. */
602 static int MonthConv(char *Month
)
604 switch (toupper(*Month
))
607 return toupper(Month
[1]) == 'P'?3:7;
613 if (toupper(Month
[1]) == 'A')
615 return toupper(Month
[2]) == 'N'?5:6;
617 return toupper(Month
[2]) == 'R'?2:4;
625 // Pretend it is January..
631 // timegm - Internal timegm function if gnu is not available /*{{{*/
632 // ---------------------------------------------------------------------
633 /* Ripped this evil little function from wget - I prefer the use of
634 GNU timegm if possible as this technique will have interesting problems
635 with leap seconds, timezones and other.
637 Converts struct tm to time_t, assuming the data in tm is UTC rather
638 than local timezone (mktime assumes the latter).
640 Contributed by Roger Beeman <beeman@cisco.com>, with the help of
641 Mark Baushke <mdb@cisco.com> and the rest of the Gurus at CISCO. */
642 #ifndef __USE_MISC // glib sets this
643 static time_t timegm(struct tm
*t
)
650 tb
= mktime (gmtime (&tl
));
651 return (tl
<= tb
? (tl
+ (tl
- tb
)) : (tl
- (tb
- tl
)));
655 // StrToTime - Converts a string into a time_t /*{{{*/
656 // ---------------------------------------------------------------------
657 /* This handles all 3 populare time formats including RFC 1123, RFC 1036
658 and the C library asctime format. It requires the GNU library function
659 'timegm' to convert a struct tm in UTC to a time_t. For some bizzar
660 reason the C library does not provide any such function :< This also
661 handles the weird, but unambiguous FTP time format*/
662 bool StrToTime(string Val
,time_t &Result
)
666 const char *I
= Val
.c_str();
668 // Skip the day of the week
669 for (;*I
!= 0 && *I
!= ' '; I
++);
671 // Handle RFC 1123 time
673 if (sscanf(I
," %d %3s %d %d:%d:%d GMT",&Tm
.tm_mday
,Month
,&Tm
.tm_year
,
674 &Tm
.tm_hour
,&Tm
.tm_min
,&Tm
.tm_sec
) != 6)
676 // Handle RFC 1036 time
677 if (sscanf(I
," %d-%3s-%d %d:%d:%d GMT",&Tm
.tm_mday
,Month
,
678 &Tm
.tm_year
,&Tm
.tm_hour
,&Tm
.tm_min
,&Tm
.tm_sec
) == 6)
683 if (sscanf(I
," %3s %d %d:%d:%d %d",Month
,&Tm
.tm_mday
,
684 &Tm
.tm_hour
,&Tm
.tm_min
,&Tm
.tm_sec
,&Tm
.tm_year
) != 6)
687 if (sscanf(Val
.c_str(),"%4d%2d%2d%2d%2d%2d",&Tm
.tm_year
,&Tm
.tm_mon
,
688 &Tm
.tm_mday
,&Tm
.tm_hour
,&Tm
.tm_min
,&Tm
.tm_sec
) != 6)
697 Tm
.tm_mon
= MonthConv(Month
);
700 // Convert to local time and then to GMT
701 Result
= timegm(&Tm
);
705 // StrToNum - Convert a fixed length string to a number /*{{{*/
706 // ---------------------------------------------------------------------
707 /* This is used in decoding the crazy fixed length string headers in
709 bool StrToNum(const char *Str
,unsigned long &Res
,unsigned Len
,unsigned Base
)
712 if (Len
>= sizeof(S
))
717 // All spaces is a zero
720 for (I
= 0; S
[I
] == ' '; I
++);
725 Res
= strtoul(S
,&End
,Base
);
732 // HexDigit - Convert a hex character into an integer /*{{{*/
733 // ---------------------------------------------------------------------
734 /* Helper for Hex2Num */
735 static int HexDigit(int c
)
737 if (c
>= '0' && c
<= '9')
739 if (c
>= 'a' && c
<= 'f')
741 if (c
>= 'A' && c
<= 'F')
746 // Hex2Num - Convert a long hex number into a buffer /*{{{*/
747 // ---------------------------------------------------------------------
748 /* The length of the buffer must be exactly 1/2 the length of the string. */
749 bool Hex2Num(string Str
,unsigned char *Num
,unsigned int Length
)
751 if (Str
.length() != Length
*2)
754 // Convert each digit. We store it in the same order as the string
756 for (string::const_iterator I
= Str
.begin(); I
!= Str
.end();J
++, I
+= 2)
758 if (isxdigit(*I
) == 0 || isxdigit(I
[1]) == 0)
761 Num
[J
] = HexDigit(I
[0]) << 4;
762 Num
[J
] += HexDigit(I
[1]);
768 // TokSplitString - Split a string up by a given token /*{{{*/
769 // ---------------------------------------------------------------------
770 /* This is intended to be a faster splitter, it does not use dynamic
771 memories. Input is changed to insert nulls at each token location. */
772 bool TokSplitString(char Tok
,char *Input
,char **List
,
773 unsigned long ListMax
)
775 // Strip any leading spaces
777 char *Stop
= Start
+ strlen(Start
);
778 for (; *Start
!= 0 && isspace(*Start
) != 0; Start
++);
780 unsigned long Count
= 0;
784 // Skip to the next Token
785 for (; Pos
!= Stop
&& *Pos
!= Tok
; Pos
++);
787 // Back remove spaces
789 for (; End
> Start
&& (End
[-1] == Tok
|| isspace(End
[-1]) != 0); End
--);
792 List
[Count
++] = Start
;
793 if (Count
>= ListMax
)
800 for (; Pos
!= Stop
&& (*Pos
== Tok
|| isspace(*Pos
) != 0 || *Pos
== 0); Pos
++);
808 // RegexChoice - Simple regex list/list matcher /*{{{*/
809 // ---------------------------------------------------------------------
811 unsigned long RegexChoice(RxChoiceList
*Rxs
,const char **ListBegin
,
812 const char **ListEnd
)
814 for (RxChoiceList
*R
= Rxs
; R
->Str
!= 0; R
++)
817 unsigned long Hits
= 0;
818 for (; ListBegin
!= ListEnd
; ListBegin
++)
820 // Check if the name is a regex
823 for (I
= *ListBegin
; *I
!= 0; I
++)
824 if (*I
== '.' || *I
== '?' || *I
== '*' || *I
== '|')
829 // Compile the regex pattern
832 if (regcomp(&Pattern
,*ListBegin
,REG_EXTENDED
| REG_ICASE
|
838 for (RxChoiceList
*R
= Rxs
; R
->Str
!= 0; R
++)
843 if (strcasecmp(R
->Str
,*ListBegin
) != 0)
847 if (regexec(&Pattern
,R
->Str
,0,0,0) != 0)
862 _error
->Warning(_("Selection %s not found"),*ListBegin
);
868 // ioprintf - C format string outputter to C++ iostreams /*{{{*/
869 // ---------------------------------------------------------------------
870 /* This is used to make the internationalization strinc easier to translate
871 and to allow reordering of parameters */
872 void ioprintf(ostream
&out
,const char *format
,...)
875 va_start(args
,format
);
877 // sprintf the description
879 vsnprintf(S
,sizeof(S
),format
,args
);
884 // CheckDomainList - See if Host is in a , seperate list /*{{{*/
885 // ---------------------------------------------------------------------
886 /* The domain list is a comma seperate list of domains that are suffix
887 matched against the argument */
888 bool CheckDomainList(string Host
,string List
)
890 const char *Start
= List
.c_str();
891 for (const char *Cur
= List
.c_str(); *Cur
!= 0; Cur
++)
896 // Match the end of the string..
897 if ((Host
.size() >= (unsigned)(Cur
- List
.c_str())) &&
899 stringcasecmp(Host
.c_str() + Host
.length() - (Cur
- Start
),Host
.c_str()+Host
.length(),Start
,Cur
) == 0)
908 // URI::CopyFrom - Copy from an object /*{{{*/
909 // ---------------------------------------------------------------------
910 /* This parses the URI into all of its components */
911 void URI::CopyFrom(string U
)
913 const char *I
= U
.c_str();
915 // Locate the first colon, this separates the scheme
916 for (; *I
!= 0 && *I
!= ':' ; I
++);
917 const char *FirstColon
= I
;
919 /* Determine if this is a host type URI with a leading double //
920 and then search for the first single / */
921 const char *SingleSlash
= I
;
922 if (I
+ 3 < U
.c_str() + U
.length() && I
[1] == '/' && I
[2] == '/')
925 /* Find the / indicating the end of the hostname, ignoring /'s in the
927 bool InBracket
= false;
928 for (; SingleSlash
< U
.c_str() + U
.length() && (*SingleSlash
!= '/' || InBracket
== true); SingleSlash
++)
930 if (*SingleSlash
== '[')
932 if (InBracket
== true && *SingleSlash
== ']')
936 if (SingleSlash
> U
.c_str() + U
.length())
937 SingleSlash
= U
.c_str() + U
.length();
939 // We can now write the access and path specifiers
940 Access
= string(U
,0,FirstColon
- U
.c_str());
941 if (*SingleSlash
!= 0)
942 Path
= string(U
,SingleSlash
- U
.c_str());
943 if (Path
.empty() == true)
946 // Now we attempt to locate a user:pass@host fragment
947 if (FirstColon
[1] == '/' && FirstColon
[2] == '/')
951 if (FirstColon
>= U
.c_str() + U
.length())
954 if (FirstColon
> SingleSlash
)
955 FirstColon
= SingleSlash
;
961 for (; I
< SingleSlash
&& *I
!= ':'; I
++);
962 const char *SecondColon
= I
;
964 // Search for the @ after the colon
965 for (; I
< SingleSlash
&& *I
!= '@'; I
++);
968 // Now write the host and user/pass
969 if (At
== SingleSlash
)
971 if (FirstColon
< SingleSlash
)
972 Host
= string(U
,FirstColon
- U
.c_str(),SingleSlash
- FirstColon
);
976 Host
= string(U
,At
- U
.c_str() + 1,SingleSlash
- At
- 1);
977 User
= string(U
,FirstColon
- U
.c_str(),SecondColon
- FirstColon
);
978 if (SecondColon
< At
)
979 Password
= string(U
,SecondColon
- U
.c_str() + 1,At
- SecondColon
- 1);
982 // Now we parse the RFC 2732 [] hostnames.
983 unsigned long PortEnd
= 0;
985 for (unsigned I
= 0; I
!= Host
.length();)
994 if (InBracket
== true && Host
[I
] == ']')
1005 if (InBracket
== true)
1011 // Now we parse off a port number from the hostname
1013 string::size_type Pos
= Host
.rfind(':');
1014 if (Pos
== string::npos
|| Pos
< PortEnd
)
1017 Port
= atoi(string(Host
,Pos
+1).c_str());
1018 Host
= string(Host
,0,Pos
);
1021 // URI::operator string - Convert the URI to a string /*{{{*/
1022 // ---------------------------------------------------------------------
1024 URI::operator string()
1028 if (Access
.empty() == false)
1031 if (Host
.empty() == false)
1033 if (Access
.empty() == false)
1036 if (User
.empty() == false)
1039 if (Password
.empty() == false)
1040 Res
+= ":" + Password
;
1044 // Add RFC 2732 escaping characters
1045 if (Access
.empty() == false &&
1046 (Host
.find('/') != string::npos
|| Host
.find(':') != string::npos
))
1047 Res
+= '[' + Host
+ ']';
1054 sprintf(S
,":%u",Port
);
1059 if (Path
.empty() == false)
1070 // URI::SiteOnly - Return the schema and site for the URI /*{{{*/
1071 // ---------------------------------------------------------------------
1073 string
URI::SiteOnly(string URI
)
1077 U
.Password
= string();