]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/contrib/strutl.cc
* apt-pkg/contrib/cdromutl.cc:
[apt.git] / apt-pkg / contrib / strutl.cc
index b54758632ebec8bc807ea4c9a47f88797a77bb5d..072dda3ac3b1f74b76f403c4d79bbaffdc5fbbae 100644 (file)
@@ -340,13 +340,13 @@ string SizeToStr(double Size)
    {
       if (ASize < 100 && I != 0)
       {
    {
       if (ASize < 100 && I != 0)
       {
-         sprintf(S,"%'.1f%c",ASize,Ext[I]);
+         sprintf(S,"%'.1f %c",ASize,Ext[I]);
         break;
       }
       
       if (ASize < 10000)
       {
         break;
       }
       
       if (ASize < 10000)
       {
-         sprintf(S,"%'.0f%c",ASize,Ext[I]);
+         sprintf(S,"%'.0f %c",ASize,Ext[I]);
         break;
       }
       ASize /= 1000.0;
         break;
       }
       ASize /= 1000.0;
@@ -574,7 +574,7 @@ int stringcmp(string::const_iterator A,string::const_iterator AEnd,
 int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
 {
    for (; A != AEnd && B != BEnd; A++, B++)
 int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
 {
    for (; A != AEnd && B != BEnd; A++, B++)
-      if (toupper(*A) != toupper(*B))
+      if (tolower_ascii(*A) != tolower_ascii(*B))
         break;
 
    if (A == AEnd && B == BEnd)
         break;
 
    if (A == AEnd && B == BEnd)
@@ -583,7 +583,7 @@ int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
       return 1;
    if (B == BEnd)
       return -1;
       return 1;
    if (B == BEnd)
       return -1;
-   if (toupper(*A) < toupper(*B))
+   if (tolower_ascii(*A) < tolower_ascii(*B))
       return -1;
    return 1;
 }
       return -1;
    return 1;
 }
@@ -592,7 +592,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd,
                  const char *B,const char *BEnd)
 {
    for (; A != AEnd && B != BEnd; A++, B++)
                  const char *B,const char *BEnd)
 {
    for (; A != AEnd && B != BEnd; A++, B++)
-      if (toupper(*A) != toupper(*B))
+      if (tolower_ascii(*A) != tolower_ascii(*B))
         break;
 
    if (A == AEnd && B == BEnd)
         break;
 
    if (A == AEnd && B == BEnd)
@@ -601,7 +601,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd,
       return 1;
    if (B == BEnd)
       return -1;
       return 1;
    if (B == BEnd)
       return -1;
-   if (toupper(*A) < toupper(*B))
+   if (tolower_ascii(*A) < tolower_ascii(*B))
       return -1;
    return 1;
 }
       return -1;
    return 1;
 }
@@ -609,7 +609,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd,
                  string::const_iterator B,string::const_iterator BEnd)
 {
    for (; A != AEnd && B != BEnd; A++, B++)
                  string::const_iterator B,string::const_iterator BEnd)
 {
    for (; A != AEnd && B != BEnd; A++, B++)
-      if (toupper(*A) != toupper(*B))
+      if (tolower_ascii(*A) != tolower_ascii(*B))
         break;
 
    if (A == AEnd && B == BEnd)
         break;
 
    if (A == AEnd && B == BEnd)
@@ -618,7 +618,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd,
       return 1;
    if (B == BEnd)
       return -1;
       return 1;
    if (B == BEnd)
       return -1;
-   if (toupper(*A) < toupper(*B))
+   if (tolower_ascii(*A) < tolower_ascii(*B))
       return -1;
    return 1;
 }
       return -1;
    return 1;
 }
@@ -692,14 +692,16 @@ int StringToBool(const string &Text,int Default)
    year 2000 complient and timezone neutral */
 string TimeRFC1123(time_t Date)
 {
    year 2000 complient and timezone neutral */
 string TimeRFC1123(time_t Date)
 {
-   struct tm Conv = *gmtime(&Date);
-   char Buf[300];
+   struct tm Conv;
+   if (gmtime_r(&Date, &Conv) == NULL)
+      return "";
 
 
+   char Buf[300];
    const char *Day[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
    const char *Month[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul",
                           "Aug","Sep","Oct","Nov","Dec"};
 
    const char *Day[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
    const char *Month[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul",
                           "Aug","Sep","Oct","Nov","Dec"};
 
-   sprintf(Buf,"%s, %02i %s %i %02i:%02i:%02i GMT",Day[Conv.tm_wday],
+   snprintf(Buf, sizeof(Buf), "%s, %02i %s %i %02i:%02i:%02i GMT",Day[Conv.tm_wday],
           Conv.tm_mday,Month[Conv.tm_mon],Conv.tm_year+1900,Conv.tm_hour,
           Conv.tm_min,Conv.tm_sec);
    return Buf;
           Conv.tm_mday,Month[Conv.tm_mon],Conv.tm_year+1900,Conv.tm_hour,
           Conv.tm_min,Conv.tm_sec);
    return Buf;
@@ -797,28 +799,28 @@ bool ReadMessages(int Fd, vector<string> &List)
 // MonthConv - Converts a month string into a number                   /*{{{*/
 // ---------------------------------------------------------------------
 /* This was lifted from the boa webserver which lifted it from 'wn-v1.07'
 // MonthConv - Converts a month string into a number                   /*{{{*/
 // ---------------------------------------------------------------------
 /* This was lifted from the boa webserver which lifted it from 'wn-v1.07'
-   Made it a bit more robust with a few touppers though. */
+   Made it a bit more robust with a few tolower_ascii though. */
 static int MonthConv(char *Month)
 {
 static int MonthConv(char *Month)
 {
-   switch (toupper(*Month)) 
+   switch (tolower_ascii(*Month)) 
    {
    {
-      case 'A':
-      return toupper(Month[1]) == 'P'?3:7;
-      case 'D':
+      case 'a':
+      return tolower_ascii(Month[1]) == 'p'?3:7;
+      case 'd':
       return 11;
       return 11;
-      case 'F':
+      case 'f':
       return 1;
       return 1;
-      case 'J':
-      if (toupper(Month[1]) == 'A')
+      case 'j':
+      if (tolower_ascii(Month[1]) == 'a')
         return 0;
         return 0;
-      return toupper(Month[2]) == 'N'?5:6;
-      case 'M':
-      return toupper(Month[2]) == 'R'?2:4;
-      case 'N':
+      return tolower_ascii(Month[2]) == 'n'?5:6;
+      case 'm':
+      return tolower_ascii(Month[2]) == 'r'?2:4;
+      case 'n':
       return 10;
       return 10;
-      case 'O':
+      case 'o':
       return 9;
       return 9;
-      case 'S':
+      case 's':
       return 8;
 
       // Pretend it is January..
       return 8;
 
       // Pretend it is January..
@@ -827,34 +829,70 @@ static int MonthConv(char *Month)
    }   
 }
                                                                        /*}}}*/
    }   
 }
                                                                        /*}}}*/
-// timegm - Internal timegm function if gnu is not available           /*{{{*/
+// timegm - Internal timegm if the gnu version is not available                /*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* Ripped this evil little function from wget - I prefer the use of 
-   GNU timegm if possible as this technique will have interesting problems
-   with leap seconds, timezones and other.
-   
-   Converts struct tm to time_t, assuming the data in tm is UTC rather
+/* Converts struct tm to time_t, assuming the data in tm is UTC rather
    than local timezone (mktime assumes the latter).
    than local timezone (mktime assumes the latter).
-   
-   Contributed by Roger Beeman <beeman@cisco.com>, with the help of
-   Mark Baushke <mdb@cisco.com> and the rest of the Gurus at CISCO. */
-
-/* Turned it into an autoconf check, because GNU is not the only thing which
-   can provide timegm. -- 2002-09-22, Joel Baker */
 
 
-#ifndef HAVE_TIMEGM // Now with autoconf!
+   This function is a nonstandard GNU extension that is also present on
+   the BSDs and maybe other systems. For others we follow the advice of
+   the manpage of timegm and use his portable replacement. */
+#ifndef HAVE_TIMEGM
 static time_t timegm(struct tm *t)
 {
 static time_t timegm(struct tm *t)
 {
-   time_t tl, tb;
-   
-   tl = mktime (t);
-   if (tl == -1)
-      return -1;
-   tb = mktime (gmtime (&tl));
-   return (tl <= tb ? (tl + (tl - tb)) : (tl - (tb - tl)));
+   char *tz = getenv("TZ");
+   setenv("TZ", "", 1);
+   tzset();
+   time_t ret = mktime(t);
+   if (tz)
+      setenv("TZ", tz, 1);
+   else
+      unsetenv("TZ");
+   tzset();
+   return ret;
 }
 #endif
                                                                        /*}}}*/
 }
 #endif
                                                                        /*}}}*/
+// FullDateToTime - Converts a HTTP1.1 full date strings into a time_t /*{{{*/
+// ---------------------------------------------------------------------
+/* tries to parses a full date as specified in RFC2616 Section 3.3.1
+   with one exception: All timezones (%Z) are accepted but the protocol
+   says that it MUST be GMT, but this one is equal to UTC which we will
+   encounter from time to time (e.g. in Release files) so we accept all
+   here and just assume it is GMT (or UTC) later on */
+bool RFC1123StrToTime(const char* const str,time_t &time)
+{
+   struct tm Tm;
+   setlocale (LC_ALL,"C");
+   bool const invalid =
+   // Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
+      (strptime(str, "%a, %d %b %Y %H:%M:%S %Z", &Tm) == NULL &&
+   // Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+       strptime(str, "%A, %d-%b-%y %H:%M:%S %Z", &Tm) == NULL &&
+   // Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format
+       strptime(str, "%a %b %d %H:%M:%S %Y", &Tm) == NULL);
+   setlocale (LC_ALL,"");
+   if (invalid == true)
+      return false;
+
+   time = timegm(&Tm);
+   return true;
+}
+                                                                       /*}}}*/
+// FTPMDTMStrToTime - Converts a ftp modification date into a time_t   /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool FTPMDTMStrToTime(const char* const str,time_t &time)
+{
+   struct tm Tm;
+   // MDTM includes no whitespaces but recommend and ignored by strptime
+   if (strptime(str, "%Y %m %d %H %M %S", &Tm) == NULL)
+      return false;
+
+   time = timegm(&Tm);
+   return true;
+}
+                                                                       /*}}}*/
 // StrToTime - Converts a string into a time_t                         /*{{{*/
 // ---------------------------------------------------------------------
 /* This handles all 3 populare time formats including RFC 1123, RFC 1036
 // StrToTime - Converts a string into a time_t                         /*{{{*/
 // ---------------------------------------------------------------------
 /* This handles all 3 populare time formats including RFC 1123, RFC 1036
@@ -932,6 +970,23 @@ bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base)
    return true;
 }
                                                                        /*}}}*/
    return true;
 }
                                                                        /*}}}*/
+// Base256ToNum - Convert a fixed length binary to a number             /*{{{*/
+// ---------------------------------------------------------------------
+/* This is used in decoding the 256bit encoded fixed length fields in
+   tar files */
+bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len)
+{
+   if ((Str[0] & 0x80) == 0)
+      return false;
+   else
+   {
+      Res = Str[0] & 0x7F;
+      for(unsigned int i = 1; i < Len; ++i)
+         Res = (Res<<8) + Str[i];
+      return true;
+   }
+}
+                                                                       /*}}}*/
 // HexDigit - Convert a hex character into an integer                  /*{{{*/
 // ---------------------------------------------------------------------
 /* Helper for Hex2Num */
 // HexDigit - Convert a hex character into an integer                  /*{{{*/
 // ---------------------------------------------------------------------
 /* Helper for Hex2Num */
@@ -1008,6 +1063,24 @@ bool TokSplitString(char Tok,char *Input,char **List,
    return true;
 }
                                                                        /*}}}*/
    return true;
 }
                                                                        /*}}}*/
+// VectorizeString - Split a string up into a vector of strings                /*{{{*/
+// ---------------------------------------------------------------------
+/* This can be used to split a given string up into a vector, so the
+   propose is the same as in the method above and this one is a bit slower
+   also, but the advantage is that we have an iteratable vector */
+vector<string> VectorizeString(string const &haystack, char const &split)
+{
+   string::const_iterator start = haystack.begin();
+   string::const_iterator end = start;
+   vector<string> exploded;
+   do {
+      for (; end != haystack.end() && *end != split; ++end);
+      exploded.push_back(string(start, end));
+      start = end + 1;
+   } while (end != haystack.end() && (++end) != haystack.end());
+   return exploded;
+}
+                                                                       /*}}}*/
 // RegexChoice - Simple regex list/list matcher                                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 // RegexChoice - Simple regex list/list matcher                                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1107,7 +1180,7 @@ void strprintf(string &out,const char *format,...)
 char *safe_snprintf(char *Buffer,char *End,const char *Format,...)
 {
    va_list args;
 char *safe_snprintf(char *Buffer,char *End,const char *Format,...)
 {
    va_list args;
-   unsigned long Did;
+   int Did;
 
    va_start(args,Format);
 
 
    va_start(args,Format);
 
@@ -1120,13 +1193,25 @@ char *safe_snprintf(char *Buffer,char *End,const char *Format,...)
    return Buffer + Did;
 }
                                                                        /*}}}*/
    return Buffer + Did;
 }
                                                                        /*}}}*/
+// StripEpoch - Remove the version "epoch" from a version string       /*{{{*/
+// ---------------------------------------------------------------------
+string StripEpoch(const string &VerStr)
+{
+   size_t i = VerStr.find(":");
+   if (i == string::npos)
+      return VerStr;
+   return VerStr.substr(i+1);
+}
 
 // tolower_ascii - tolower() function that ignores the locale          /*{{{*/
 // ---------------------------------------------------------------------
 
 // tolower_ascii - tolower() function that ignores the locale          /*{{{*/
 // ---------------------------------------------------------------------
-/* */
-int tolower_ascii(int c)
+/* This little function is the most called method we have and tries
+   therefore to do the absolut minimum - and is noteable faster than
+   standard tolower/toupper and as a bonus avoids problems with different
+   locales - we only operate on ascii chars anyway. */
+int tolower_ascii(int const c)
 {
 {
-   if (c >= 'A' and c <= 'Z')
+   if (c >= 'A' && c <= 'Z')
       return c + 32;
    return c;
 }
       return c + 32;
    return c;
 }