]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/contrib/strutl.cc
Fixed espy's bug with experimental
[apt.git] / apt-pkg / contrib / strutl.cc
index 04a3c7bb7c3deab5414c5642af75cbe744c6deb9..2411623c573bc9fe87e7702528f09c69e8c4c35d 100644 (file)
@@ -1,25 +1,32 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: strutl.cc,v 1.6 1998/10/22 04:56:48 jgg Exp $
+// $Id: strutl.cc,v 1.24 1999/04/04 08:07:39 jgg Exp $
 /* ######################################################################
 
    String Util - Some usefull string functions.
 
-   strstrip - Remove whitespace from the front and end of a line.
+   These have been collected from here and there to do all sorts of usefull
+   things to strings. They are usefull in file parsers, URI handlers and
+   especially in APT methods.   
    
    This source is placed in the Public Domain, do with it what you will
-   It was originally written by Jason Gunthorpe <jgg@gpu.srv.ualberta.ca>   
+   It was originally written by Jason Gunthorpe <jgg@gpu.srv.ualberta.ca>
    
    ##################################################################### */
                                                                        /*}}}*/
 // Includes                                                            /*{{{*/
-#include <strutl.h>
+#ifdef __GNUG__
+#pragma implementation "apt-pkg/strutl.h"
+#endif
+
+#include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
 
 #include <ctype.h>
 #include <string.h>
 #include <stdio.h>
-#include <time.h>
+#include <unistd.h>
+#include <errno.h>
                                                                        /*}}}*/
 
 // strstrip - Remove white space from the front and back of a string   /*{{{*/
@@ -90,7 +97,7 @@ bool ParseQuoteWord(const char *&String,string &Res)
       return false;
    
    // Jump to the next word
-   for (;*C != 0 && *C != ' '; C++)
+   for (;*C != 0 && isspace(*C) == 0; C++)
    {
       if (*C == '"')
       {
@@ -111,7 +118,7 @@ bool ParseQuoteWord(const char *&String,string &Res)
       {
         Tmp[0] = Start[1];
         Tmp[1] = Start[2];
-        Tmp[3] = 0;
+        Tmp[2] = 0;
         *I = (char)strtol(Tmp,0,16);
         Start += 3;
         continue;
@@ -126,7 +133,7 @@ bool ParseQuoteWord(const char *&String,string &Res)
    Res = Buffer;
    
    // Skip ending white space
-   for (;*C != 0 && *C == ' '; C++);
+   for (;*C != 0 && isspace(*C) != 0; C++);
    String = C;
    return true;
 }
@@ -193,10 +200,35 @@ string QuoteString(string Str,const char *Bad)
    return Res;
 }
                                                                        /*}}}*/
+// DeQuoteString - Convert a string from quoted from                    /*{{{*/
+// ---------------------------------------------------------------------
+/* This undoes QuoteString */
+string DeQuoteString(string Str)
+{
+   string Res;
+   for (string::iterator I = Str.begin(); I != Str.end(); I++)
+   {
+      if (*I == '%' && I + 2 < Str.end())
+      {
+        char Tmp[3];
+        Tmp[0] = I[1];
+        Tmp[1] = I[2];
+        Tmp[2] = 0;
+        Res += (char)strtol(Tmp,0,16);
+        I += 2;
+        continue;
+      }
+      else
+        Res += *I;
+   }
+   return Res;   
+}
+
+                                                                        /*}}}*/
 // SizeToStr - Convert a long into a human readable size               /*{{{*/
 // ---------------------------------------------------------------------
-/* A max of 4 digits are shown before conversion to the next highest unit. The
-   max length of the string will be 5 chars unless the size is > 10 
+/* A max of 4 digits are shown before conversion to the next highest unit. 
+   The max length of the string will be 5 chars unless the size is > 10
    YottaBytes (E24) */
 string SizeToStr(double Size)
 {
@@ -209,7 +241,7 @@ string SizeToStr(double Size)
    
    /* bytes, KiloBytes, MegaBytes, GigaBytes, TeraBytes, PetaBytes, 
       ExaBytes, ZettaBytes, YottaBytes */
-   char Ext[] = {'b','k','M','G','T','P','E','Z','Y'};
+   char Ext[] = {'\0','k','M','G','T','P','E','Z','Y'};
    int I = 0;
    while (I <= 8)
    {
@@ -306,17 +338,6 @@ string URItoFileName(string URI)
    return URI;
 }
                                                                        /*}}}*/
-// URIAccess - Return the access method for the URI                    /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string URIAccess(string URI)
-{
-   string::size_type Pos = URI.find(':');
-   if (Pos == string::npos)
-      return URI;
-   return string(URI,0,Pos);
-}
-                                                                       /*}}}*/
 // Base64Encode - Base64 Encoding routine for short strings            /*{{{*/
 // ---------------------------------------------------------------------
 /* This routine performs a base64 transformation on a string. It was ripped
@@ -462,6 +483,7 @@ int StringToBool(string Text,int Default = -1)
    if (strcasecmp(Text.c_str(),"no") == 0 ||
        strcasecmp(Text.c_str(),"false") == 0 ||
        strcasecmp(Text.c_str(),"without") == 0 ||
+       strcasecmp(Text.c_str(),"off") == 0 ||
        strcasecmp(Text.c_str(),"disable") == 0)
       return 0;
    
@@ -469,6 +491,7 @@ int StringToBool(string Text,int Default = -1)
    if (strcasecmp(Text.c_str(),"yes") == 0 ||
        strcasecmp(Text.c_str(),"true") == 0 ||
        strcasecmp(Text.c_str(),"with") == 0 ||
+       strcasecmp(Text.c_str(),"on") == 0 ||
        strcasecmp(Text.c_str(),"enable") == 0)
       return 1;
    
@@ -507,6 +530,8 @@ bool ReadMessages(int Fd, vector<string> &List)
    while (1)
    {
       int Res = read(Fd,End,sizeof(Buffer) - (End-Buffer));
+      if (Res < 0 && errno == EINTR)
+        continue;
       
       // Process is dead, this is kind of bad..
       if (Res == 0)
@@ -519,7 +544,7 @@ bool ReadMessages(int Fd, vector<string> &List)
       End += Res;
       
       // Look for the end of the message
-      for (char *I = Buffer; I < End; I++)
+      for (char *I = Buffer; I + 1 < End; I++)
       {
         if (I[0] != '\n' || I[1] != '\n')
            continue;
@@ -543,3 +568,210 @@ 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'
+   Made it a bit more robust with a few touppers though. */
+static int MonthConv(char *Month)
+{
+   switch (toupper(*Month)) 
+   {
+      case 'A':
+      return toupper(Month[1]) == 'P'?3:7;
+      case 'D':
+      return 11;
+      case 'F':
+      return 1;
+      case 'J':
+      if (toupper(Month[1]) == 'A')
+        return 0;
+      return toupper(Month[2]) == 'N'?5:6;
+      case 'M':
+      return toupper(Month[2]) == 'R'?2:4;
+      case 'N':
+      return 10;
+      case 'O':
+      return 9;
+      case 'S':
+      return 8;
+
+      // Pretend it is January..
+      default:
+      return 0;
+   }   
+}
+                                                                       /*}}}*/
+// timegm - Internal timegm function if gnu 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
+   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. */
+#ifndef __USE_MISC        // glib sets this
+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)));
+}
+#endif
+                                                                       /*}}}*/
+// StrToTime - Converts a string into a time_t                         /*{{{*/
+// ---------------------------------------------------------------------
+/* This handles all 3 populare time formats including RFC 1123, RFC 1036
+   and the C library asctime format. It requires the GNU library function
+   'timegm' to convert a struct tm in UTC to a time_t. For some bizzar
+   reason the C library does not provide any such function :<*/
+bool StrToTime(string Val,time_t &Result)
+{
+   struct tm Tm;
+   char Month[10];
+   const char *I = Val.c_str();
+   
+   // Skip the day of the week
+   for (;*I != 0  && *I != ' '; I++);
+   
+   // Handle RFC 1123 time
+   if (sscanf(I," %d %3s %d %d:%d:%d GMT",&Tm.tm_mday,Month,&Tm.tm_year,
+             &Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec) != 6)
+   {
+      // Handle RFC 1036 time
+      if (sscanf(I," %d-%3s-%d %d:%d:%d GMT",&Tm.tm_mday,Month,
+                &Tm.tm_year,&Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec) == 6)
+        Tm.tm_year += 1900;
+      else
+      {
+        // asctime format
+        if (sscanf(I," %3s %d %d:%d:%d %d",Month,&Tm.tm_mday,
+                   &Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec,&Tm.tm_year) != 6)
+           return false;
+      }
+   }
+   
+   Tm.tm_isdst = 0;
+   Tm.tm_mon = MonthConv(Month);
+   Tm.tm_year -= 1900;
+   
+   // Convert to local time and then to GMT
+   Result = timegm(&Tm);
+   return true;
+}
+                                                                       /*}}}*/
+
+// URI::CopyFrom - Copy from an object                                 /*{{{*/
+// ---------------------------------------------------------------------
+/* This parses the URI into all of its components */
+void URI::CopyFrom(string U)
+{
+   string::const_iterator I = U.begin();
+
+   // Locate the first colon, this seperates the scheme
+   for (; I < U.end() && *I != ':' ; I++);
+   string::const_iterator FirstColon = I;
+
+   /* Determine if this is a host type URI with a leading double //
+      and then search for the first single / */
+   string::const_iterator SingleSlash = I;
+   if (I + 3 < U.end() && I[1] == '/' && I[2] == '/')
+      SingleSlash += 3;
+   for (; SingleSlash < U.end() && *SingleSlash != '/'; SingleSlash++);
+   if (SingleSlash > U.end())
+      SingleSlash = U.end();
+
+   // We can now write the access and path specifiers
+   Access = string(U,0,FirstColon - U.begin());
+   if (SingleSlash != U.end())
+      Path = string(U,SingleSlash - U.begin());
+   if (Path.empty() == true)
+      Path = "/";
+
+   // Now we attempt to locate a user:pass@host fragment
+   if (FirstColon[1] == '/' && FirstColon[2] == '/')
+      FirstColon += 3;
+   else
+      FirstColon += 1;
+   if (FirstColon >= U.end())
+      return;
+   
+   if (FirstColon > SingleSlash)
+      FirstColon = SingleSlash;
+   
+   // Search for the @
+   I = FirstColon;
+   for (; I < SingleSlash && *I != '@'; I++);
+   string::const_iterator At = I;
+   
+   // Colon in the @ section
+   I = FirstColon + 1;
+   for (; I < At && *I != ':'; I++);
+   string::const_iterator SecondColon = I;
+      
+   // Now write the host and user/pass
+   if (At == SingleSlash)
+   {
+      if (FirstColon < SingleSlash)
+        Host = string(U,FirstColon - U.begin(),SingleSlash - FirstColon);
+   }
+   else
+   {
+      Host = string(U,At - U.begin() + 1,SingleSlash - At - 1);
+      User = string(U,FirstColon - U.begin(),SecondColon - FirstColon);
+      if (SecondColon < At)
+        Password = string(U,SecondColon - U.begin() + 1,At - SecondColon - 1);
+   }   
+   
+   // Now we parse off a pot number from the hostname
+   Port = 0;
+   string::size_type Pos = Host.rfind(':');
+   if (Pos == string::npos)
+      return;
+   
+   Port = atoi(string(Host,Pos+1).c_str());
+   Host = string(Host,0,Pos);
+}
+                                                                       /*}}}*/
+// URI::operator string - Convert the URI to a string                  /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+URI::operator string()
+{
+   string Res = Access + ':';
+   if (Host.empty() == false)
+   {
+      Res += "//";
+      if (User.empty() == false)
+      {
+        Res += "//" + User;
+        if (Password.empty() == false)
+           Res += ":" + Password;
+        Res += "@";
+      }
+      Res += Host;
+      if (Port != 0)
+      {
+        char S[30];
+        sprintf(S,":%u",Port);
+        Res += S;
+      }         
+   }
+   
+   if (Path.empty() == false)
+   {
+      if (Path[0] != '/')
+        Res += "/" + Path;
+      else
+        Res += Path;
+   }
+   
+   return Res;
+}
+                                                                       /*}}}*/