X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/0a8a80e58374771acc225fe1e08ed8e0fe0016cc..1fcbfcb8ba78224fd0e4d532d4fa976f0ea00fef:/apt-pkg/contrib/strutl.cc diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 04a3c7bb7..2411623c5 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -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 + It was originally written by Jason Gunthorpe ##################################################################### */ /*}}}*/ // Includes /*{{{*/ -#include +#ifdef __GNUG__ +#pragma implementation "apt-pkg/strutl.h" +#endif + +#include #include #include #include #include -#include +#include +#include /*}}}*/ // 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 &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 &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 &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 , with the help of + Mark Baushke 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; +} + /*}}}*/