From b8eba208daebe3e3f235983e44da9c398d6f7a57 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 10 Mar 2015 14:11:54 +0100 Subject: [PATCH] reimplement the last uses of sprintf Working with strings c-style is complicated and error-prune, so by converting to c++ style we gain some simplicity and avoid buffer overflows by later extensions. Git-Dch: Ignore --- apt-pkg/contrib/cdromutl.cc | 31 +++---- apt-pkg/contrib/strutl.cc | 126 ++++++++++++-------------- apt-private/acqprogress.cc | 173 ++++++++++++++++++------------------ apt-private/acqprogress.h | 4 +- ftparchive/writer.cc | 8 +- methods/ftp.cc | 16 ++-- test/libapt/strutil_test.cc | 22 +++++ test/libapt/uri_test.cc | 12 +++ 8 files changed, 206 insertions(+), 186 deletions(-) diff --git a/apt-pkg/contrib/cdromutl.cc b/apt-pkg/contrib/cdromutl.cc index 936e377fb..6eb917457 100644 --- a/apt-pkg/contrib/cdromutl.cc +++ b/apt-pkg/contrib/cdromutl.cc @@ -207,7 +207,6 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version) /* Run over the directory, we assume that the reader order will never change as the media is read-only. In theory if the kernel did some sort of wacked caching this might not be true.. */ - char S[300]; for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D)) { // Skip some files.. @@ -215,30 +214,32 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version) strcmp(Dir->d_name,"..") == 0) continue; + std::string S; if (Version <= 1) { - sprintf(S,"%lu",(unsigned long)Dir->d_ino); + strprintf(S, "%lu", (unsigned long)Dir->d_ino); } else { struct stat Buf; if (stat(Dir->d_name,&Buf) != 0) continue; - sprintf(S,"%lu",(unsigned long)Buf.st_mtime); + strprintf(S, "%lu", (unsigned long)Buf.st_mtime); } - - Hash.Add(S); + + Hash.Add(S.c_str()); Hash.Add(Dir->d_name); }; - + if (chdir(StartDir.c_str()) != 0) { _error->Errno("chdir",_("Unable to change to %s"),StartDir.c_str()); closedir(D); return false; } closedir(D); - + // Some stats from the fsys + std::string S; if (_config->FindB("Debug::identcdrom",false) == false) { struct statvfs Buf; @@ -248,19 +249,19 @@ bool IdentCdrom(string CD,string &Res,unsigned int Version) // We use a kilobyte block size to advoid overflow if (writable_media) { - sprintf(S,"%lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024))); + strprintf(S, "%lu", (unsigned long)(Buf.f_blocks*(Buf.f_bsize/1024))); } else { - sprintf(S,"%lu %lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024)), - (long)(Buf.f_bfree*(Buf.f_bsize/1024))); + strprintf(S, "%lu %lu", (unsigned long)(Buf.f_blocks*(Buf.f_bsize/1024)), + (unsigned long)(Buf.f_bfree*(Buf.f_bsize/1024))); } - Hash.Add(S); - sprintf(S,"-%u",Version); + Hash.Add(S.c_str()); + strprintf(S, "-%u", Version); } else - sprintf(S,"-%u.debug",Version); - + strprintf(S, "-%u.debug", Version); + Res = Hash.Result().Value() + S; - return true; + return true; } /*}}}*/ // FindMountPointForDevice - Find mountpoint for the given device /*{{{*/ diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 0ac587a9e..0db4c57b2 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -324,21 +324,19 @@ bool ParseCWord(const char *&String,string &Res) /* */ string QuoteString(const string &Str, const char *Bad) { - string Res; + std::stringstream Res; for (string::const_iterator I = Str.begin(); I != Str.end(); ++I) { - if (strchr(Bad,*I) != 0 || isprint(*I) == 0 || + if (strchr(Bad,*I) != 0 || isprint(*I) == 0 || *I == 0x25 || // percent '%' char *I <= 0x20 || *I >= 0x7F) // control chars { - char Buf[10]; - sprintf(Buf,"%%%02x",(int)*I); - Res += Buf; + ioprintf(Res,"%%%02x",(int)*I); } else - Res += *I; + Res << *I; } - return Res; + return Res.str(); } /*}}}*/ // DeQuoteString - Convert a string from quoted from /*{{{*/ @@ -379,13 +377,12 @@ string DeQuoteString(string::const_iterator const &begin, YottaBytes (E24) */ string SizeToStr(double Size) { - char S[300]; double ASize; if (Size >= 0) ASize = Size; else ASize = -1*Size; - + /* bytes, KiloBytes, MegaBytes, GigaBytes, TeraBytes, PetaBytes, ExaBytes, ZettaBytes, YottaBytes */ char Ext[] = {'\0','k','M','G','T','P','E','Z','Y'}; @@ -394,20 +391,21 @@ string SizeToStr(double Size) { if (ASize < 100 && I != 0) { - sprintf(S,"%'.1f %c",ASize,Ext[I]); - break; + std::string S; + strprintf(S, "%'.1f %c", ASize, Ext[I]); + return S; } - + if (ASize < 10000) { - sprintf(S,"%'.0f %c",ASize,Ext[I]); - break; + std::string S; + strprintf(S, "%'.0f %c", ASize, Ext[I]); + return S; } ASize /= 1000.0; I++; } - - return S; + return ""; } /*}}}*/ // TimeToStr - Convert the time into a string /*{{{*/ @@ -415,36 +413,27 @@ string SizeToStr(double Size) /* Converts a number of seconds to a hms format */ string TimeToStr(unsigned long Sec) { - char S[300]; - - while (1) + std::string S; + if (Sec > 60*60*24) { - if (Sec > 60*60*24) - { - //d means days, h means hours, min means minutes, s means seconds - sprintf(S,_("%lid %lih %limin %lis"),Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60); - break; - } - - if (Sec > 60*60) - { - //h means hours, min means minutes, s means seconds - sprintf(S,_("%lih %limin %lis"),Sec/60/60,(Sec/60) % 60,Sec % 60); - break; - } - - if (Sec > 60) - { - //min means minutes, s means seconds - sprintf(S,_("%limin %lis"),Sec/60,Sec % 60); - break; - } - - //s means seconds - sprintf(S,_("%lis"),Sec); - break; + //TRANSLATOR: d means days, h means hours, min means minutes, s means seconds + strprintf(S,_("%lid %lih %limin %lis"),Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60); + } + else if (Sec > 60*60) + { + //TRANSLATOR: h means hours, min means minutes, s means seconds + strprintf(S,_("%lih %limin %lis"),Sec/60/60,(Sec/60) % 60,Sec % 60); + } + else if (Sec > 60) + { + //TRANSLATOR: min means minutes, s means seconds + strprintf(S,_("%limin %lis"),Sec/60,Sec % 60); + } + else + { + //TRANSLATOR: s means seconds + strprintf(S,_("%lis"),Sec); } - return S; } /*}}}*/ @@ -1423,7 +1412,7 @@ size_t strv_length(const char **str_array) ; return i; } - + /*}}}*/ // DeEscapeString - unescape (\0XX and \xXX) from a string /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -1605,51 +1594,46 @@ void URI::CopyFrom(const string &U) /* */ URI::operator string() { - string Res; - + std::stringstream Res; + if (Access.empty() == false) - Res = Access + ':'; - + Res << Access << ':'; + if (Host.empty() == false) - { + { if (Access.empty() == false) - Res += "//"; - + Res << "//"; + if (User.empty() == false) { // FIXME: Technically userinfo is permitted even less // characters than these, but this is not conveniently // expressed with a blacklist. - Res += QuoteString(User, ":/?#[]@"); + Res << QuoteString(User, ":/?#[]@"); if (Password.empty() == false) - Res += ":" + QuoteString(Password, ":/?#[]@"); - Res += "@"; + Res << ":" << QuoteString(Password, ":/?#[]@"); + Res << "@"; } - + // Add RFC 2732 escaping characters - if (Access.empty() == false && - (Host.find('/') != string::npos || Host.find(':') != string::npos)) - Res += '[' + Host + ']'; + if (Access.empty() == false && Host.find_first_of("/:") != string::npos) + Res << '[' << Host << ']'; else - Res += Host; - + Res << Host; + if (Port != 0) - { - char S[30]; - sprintf(S,":%u",Port); - Res += S; - } + Res << ':' << Port; } - + if (Path.empty() == false) { if (Path[0] != '/') - Res += "/" + Path; + Res << "/" << Path; else - Res += Path; + Res << Path; } - - return Res; + + return Res.str(); } /*}}}*/ // URI::SiteOnly - Return the schema and site for the URI /*{{{*/ diff --git a/apt-private/acqprogress.cc b/apt-private/acqprogress.cc index 14a53eacb..e834d7d6a 100644 --- a/apt-private/acqprogress.cc +++ b/apt-private/acqprogress.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -34,9 +35,8 @@ using namespace std; // --------------------------------------------------------------------- /* */ AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int const Quiet) : - pkgAcquireStatus(), ScreenWidth(ScreenWidth), ID(0), Quiet(Quiet) + pkgAcquireStatus(), ScreenWidth(ScreenWidth), LastLineLength(0), ID(0), Quiet(Quiet) { - BlankLine[0] = 0; // testcases use it to disable pulses without disabling other user messages if (Quiet == 0 && _config->FindB("quiet::NoUpdate", false) == true) this->Quiet = 1; @@ -48,7 +48,7 @@ AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int const Quiet) void AcqTextStatus::Start() { pkgAcquireStatus::Start(); - BlankLine[0] = 0; + LastLineLength = 0; ID = 1; } /*}}}*/ @@ -60,8 +60,7 @@ void AcqTextStatus::IMSHit(pkgAcquire::ItemDesc &Itm) if (Quiet > 1) return; - if (Quiet <= 0) - cout << '\r' << BlankLine << '\r'; + clearLastLine(); cout << _("Hit ") << Itm.Description; cout << endl; @@ -82,8 +81,7 @@ void AcqTextStatus::Fetch(pkgAcquire::ItemDesc &Itm) if (Quiet > 1) return; - if (Quiet <= 0) - cout << '\r' << BlankLine << '\r'; + clearLastLine(); cout << _("Get:") << Itm.Owner->ID << ' ' << Itm.Description; if (Itm.Owner->FileSize != 0) @@ -111,8 +109,7 @@ void AcqTextStatus::Fail(pkgAcquire::ItemDesc &Itm) if (Itm.Owner->Status == pkgAcquire::Item::StatIdle) return; - if (Quiet <= 0) - cout << '\r' << BlankLine << '\r'; + clearLastLine(); if (Itm.Owner->Status == pkgAcquire::Item::StatDone) { @@ -140,8 +137,7 @@ void AcqTextStatus::Stop() if (Quiet > 1) return; - if (Quiet <= 0) - cout << '\r' << BlankLine << '\r' << flush; + clearLastLine(); if (_config->FindB("quiet::NoStatistic", false) == true) return; @@ -167,77 +163,66 @@ bool AcqTextStatus::Pulse(pkgAcquire *Owner) enum {Long = 0,Medium,Short} Mode = Medium; - char Buffer[sizeof(BlankLine)]; - char *End = Buffer + sizeof(Buffer); - char *S = Buffer; - if (ScreenWidth >= sizeof(Buffer)) - ScreenWidth = sizeof(Buffer)-1; - - // Put in the percent done - sprintf(S,"%.0f%%", Percent); - - bool Shown = false; - for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0; - I = Owner->WorkerStep(I)) + std::string Line; { - S += strlen(S); - - // There is no item running - if (I->CurrentItem == 0) + std::stringstream S; + for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0; + I = Owner->WorkerStep(I)) { - if (I->Status.empty() == false) + // There is no item running + if (I->CurrentItem == 0) { - snprintf(S,End-S," [%s]",I->Status.c_str()); - Shown = true; - } - - continue; - } - - Shown = true; + if (I->Status.empty() == false) + S << " [" << I->Status << "]"; - // Add in the short description - if (I->CurrentItem->Owner->ID != 0) - snprintf(S,End-S," [%lu %s",I->CurrentItem->Owner->ID, - I->CurrentItem->ShortDesc.c_str()); - else - snprintf(S,End-S," [%s",I->CurrentItem->ShortDesc.c_str()); - S += strlen(S); + continue; + } - // Show the short mode string - if (I->CurrentItem->Owner->ActiveSubprocess.empty() == false) - { - snprintf(S,End-S, " %s", I->CurrentItem->Owner->ActiveSubprocess.c_str()); - S += strlen(S); - } + // Add in the short description + S << " ["; + if (I->CurrentItem->Owner->ID != 0) + S << I->CurrentItem->Owner->ID << " "; + S << I->CurrentItem->ShortDesc; - // Add the current progress - if (Mode == Long) - snprintf(S,End-S," %llu",I->CurrentSize); - else - { - if (Mode == Medium || I->TotalSize == 0) - snprintf(S,End-S," %sB",SizeToStr(I->CurrentSize).c_str()); - } - S += strlen(S); + // Show the short mode string + if (I->CurrentItem->Owner->ActiveSubprocess.empty() == false) + S << " " << I->CurrentItem->Owner->ActiveSubprocess; - // Add the total size and percent - if (I->TotalSize > 0 && I->CurrentItem->Owner->Complete == false) - { - if (Mode == Short) - snprintf(S,End-S," %.0f%%", - (I->CurrentSize*100.0)/I->TotalSize); + // Add the current progress + if (Mode == Long) + S << " " << I->CurrentSize; else - snprintf(S,End-S,"/%sB %.0f%%",SizeToStr(I->TotalSize).c_str(), + { + if (Mode == Medium || I->TotalSize == 0) + S << " " << SizeToStr(I->CurrentSize) << "B"; + } + + // Add the total size and percent + if (I->TotalSize > 0 && I->CurrentItem->Owner->Complete == false) + { + if (Mode == Short) + ioprintf(S, " %.0f%%", (I->CurrentSize*100.0)/I->TotalSize); + else + ioprintf(S, "/%sB %.0f%%", SizeToStr(I->TotalSize).c_str(), (I->CurrentSize*100.0)/I->TotalSize); + } + S << "]"; } - S += strlen(S); - snprintf(S,End-S,"]"); - } - // Show something.. - if (Shown == false) - snprintf(S,End-S,_(" [Working]")); + // Show at least something + Line = S.str(); + S.clear(); + if (Line.empty() == true) + Line = _(" [Working]"); + } + // Put in the percent done + { + std::stringstream S; + ioprintf(S, "%.0f%%", Percent); + S << Line; + Line = S.str(); + S.clear(); + } /* Put in the ETA and cps meter, block off signals to prevent strangeness during resizing */ @@ -248,34 +233,33 @@ bool AcqTextStatus::Pulse(pkgAcquire *Owner) if (CurrentCPS != 0) { - char Tmp[300]; unsigned long long ETA = (TotalBytes - CurrentBytes)/CurrentCPS; - sprintf(Tmp," %sB/s %s",SizeToStr(CurrentCPS).c_str(),TimeToStr(ETA).c_str()); - unsigned int Len = strlen(Buffer); - unsigned int LenT = strlen(Tmp); - if (Len + LenT < ScreenWidth) + std::string Tmp = " " + SizeToStr(CurrentCPS) + "B/s " + TimeToStr(ETA); + size_t alignment = Line.length() + Tmp.length(); + if (alignment < ScreenWidth) { - memset(Buffer + Len,' ',ScreenWidth - Len); - strcpy(Buffer + ScreenWidth - LenT,Tmp); + alignment = ScreenWidth - alignment; + for (size_t i = 0; i < alignment; ++i) + Line.append(" "); + Line.append(Tmp); } } - Buffer[ScreenWidth] = 0; - BlankLine[ScreenWidth] = 0; + if (Line.length() > ScreenWidth) + Line.erase(ScreenWidth); sigprocmask(SIG_SETMASK,&OldSigs,0); // Draw the current status if (_config->FindB("Apt::Color", false) == true) cout << _config->Find("APT::Color::Yellow"); - if (strlen(Buffer) == strlen(BlankLine)) - cout << '\r' << Buffer << flush; + if (LastLineLength > Line.length()) + clearLastLine(); else - cout << '\r' << BlankLine << '\r' << Buffer << flush; + cout << '\r'; + cout << Line << flush; if (_config->FindB("Apt::Color", false) == true) cout << _config->Find("APT::Color::Neutral") << flush; - memset(BlankLine,' ',strlen(Buffer)); - BlankLine[strlen(Buffer)] = 0; - + LastLineLength = Line.length(); Update = false; return true; @@ -296,8 +280,7 @@ bool AcqTextStatus::MediaChange(string Media,string Drive) return false; - if (Quiet <= 0) - cout << '\r' << BlankLine << '\r'; + clearLastLine(); ioprintf(cout,_("Media change: please insert the disc labeled\n" " '%s'\n" "in the drive '%s' and press enter\n"), @@ -317,3 +300,17 @@ bool AcqTextStatus::MediaChange(string Media,string Drive) return bStatus; } /*}}}*/ +void AcqTextStatus::clearLastLine() { /*{{{*/ + if (Quiet > 0) + return; + + // do not try to clear more than the (now smaller) screen + if (LastLineLength > ScreenWidth) + LastLineLength = ScreenWidth; + + std::cout << '\r'; + for (size_t i = 0; i < LastLineLength; ++i) + std::cout << ' '; + std::cout << '\r' << std::flush; +} + /*}}}*/ diff --git a/apt-private/acqprogress.h b/apt-private/acqprogress.h index 71a10d78a..ab8170126 100644 --- a/apt-private/acqprogress.h +++ b/apt-private/acqprogress.h @@ -17,10 +17,12 @@ class APT_PUBLIC AcqTextStatus : public pkgAcquireStatus { unsigned int &ScreenWidth; - char BlankLine[1024]; + size_t LastLineLength; unsigned long ID; unsigned long Quiet; + void clearLastLine(); + public: virtual bool MediaChange(std::string Media,std::string Drive); diff --git a/ftparchive/writer.cc b/ftparchive/writer.cc index a63d8846b..db68c21f0 100644 --- a/ftparchive/writer.cc +++ b/ftparchive/writer.cc @@ -440,9 +440,6 @@ bool PackagesWriter::DoPackage(string FileName) OverItem->Priority = Tags.FindS("Priority"); } - char Size[40]; - sprintf(Size,"%llu", (unsigned long long) FileSize); - // Strip the DirStrip prefix from the FileName and add the PathPrefix string NewFileName; if (DirStrip.empty() == false && @@ -466,7 +463,10 @@ bool PackagesWriter::DoPackage(string FileName) // This lists all the changes to the fields we are going to make. std::vector Changes; - Changes.push_back(SetTFRewriteData("Size", Size)); + std::string Size; + strprintf(Size, "%llu", (unsigned long long) FileSize); + Changes.push_back(SetTFRewriteData("Size", Size.c_str())); + for (HashStringList::const_iterator hs = Db.HashesList.begin(); hs != Db.HashesList.end(); ++hs) { if (hs->HashType() == "MD5Sum") diff --git a/methods/ftp.cc b/methods/ftp.cc index 0504e5872..7764acf6a 100644 --- a/methods/ftp.cc +++ b/methods/ftp.cc @@ -259,19 +259,21 @@ bool FTPConn::Login() { if (Opts->Value.empty() == true) continue; - + // Substitute the variables into the command - char SitePort[20]; - if (ServerName.Port != 0) - sprintf(SitePort,"%u",ServerName.Port); - else - strcpy(SitePort,"21"); string Tmp = Opts->Value; Tmp = SubstVar(Tmp,"$(PROXY_USER)",Proxy.User); Tmp = SubstVar(Tmp,"$(PROXY_PASS)",Proxy.Password); Tmp = SubstVar(Tmp,"$(SITE_USER)",User); Tmp = SubstVar(Tmp,"$(SITE_PASS)",Pass); - Tmp = SubstVar(Tmp,"$(SITE_PORT)",SitePort); + if (ServerName.Port != 0) + { + std::string SitePort; + strprintf(SitePort, "%u", ServerName.Port); + Tmp = SubstVar(Tmp,"$(SITE_PORT)", SitePort); + } + else + Tmp = SubstVar(Tmp,"$(SITE_PORT)", "21"); Tmp = SubstVar(Tmp,"$(SITE)",ServerName.Host); // Send the command diff --git a/test/libapt/strutil_test.cc b/test/libapt/strutil_test.cc index 9bc3c76fd..23dc08727 100644 --- a/test/libapt/strutil_test.cc +++ b/test/libapt/strutil_test.cc @@ -97,6 +97,28 @@ TEST(StrUtilTest,StartsWith) EXPECT_FALSE(Startswith("abcd", "x")); EXPECT_FALSE(Startswith("abcd", "abcndefg")); } +TEST(StrUtilTest,TimeToStr) +{ + EXPECT_EQ("0s", TimeToStr(0)); + EXPECT_EQ("42s", TimeToStr(42)); + EXPECT_EQ("9min 21s", TimeToStr((9*60) + 21)); + EXPECT_EQ("20min 42s", TimeToStr((20*60) + 42)); + EXPECT_EQ("10h 42min 21s", TimeToStr((10*3600) + (42*60) + 21)); + EXPECT_EQ("10h 42min 21s", TimeToStr((10*3600) + (42*60) + 21)); + EXPECT_EQ("1988d 3h 29min 7s", TimeToStr((1988*86400) + (3*3600) + (29*60) + 7)); + + EXPECT_EQ("59s", TimeToStr(59)); + EXPECT_EQ("60s", TimeToStr(60)); + EXPECT_EQ("1min 1s", TimeToStr(61)); + EXPECT_EQ("59min 59s", TimeToStr(3599)); + EXPECT_EQ("60min 0s", TimeToStr(3600)); + EXPECT_EQ("1h 0min 1s", TimeToStr(3601)); + EXPECT_EQ("1h 1min 0s", TimeToStr(3660)); + EXPECT_EQ("23h 59min 59s", TimeToStr(86399)); + EXPECT_EQ("24h 0min 0s", TimeToStr(86400)); + EXPECT_EQ("1d 0h 0min 1s", TimeToStr(86401)); + EXPECT_EQ("1d 0h 1min 0s", TimeToStr(86460)); +} TEST(StrUtilTest,SubstVar) { EXPECT_EQ("", SubstVar("", "fails", "passes")); diff --git a/test/libapt/uri_test.cc b/test/libapt/uri_test.cc index 1662f51f0..5d5ae9679 100644 --- a/test/libapt/uri_test.cc +++ b/test/libapt/uri_test.cc @@ -12,6 +12,7 @@ TEST(URITest, BasicHTTP) EXPECT_EQ(90, U.Port); EXPECT_EQ("www.debian.org", U.Host); EXPECT_EQ("/temp/test", U.Path); + EXPECT_EQ("http://www.debian.org:90/temp/test", (std::string)U); // Login data U = URI("http://jgg:foo@ualberta.ca/blah"); EXPECT_EQ("http", U.Access); @@ -20,6 +21,7 @@ TEST(URITest, BasicHTTP) EXPECT_EQ(0, U.Port); EXPECT_EQ("ualberta.ca", U.Host); EXPECT_EQ("/blah", U.Path); + EXPECT_EQ("http://jgg:foo@ualberta.ca/blah", (std::string)U); } TEST(URITest, SingeSlashFile) { @@ -30,6 +32,7 @@ TEST(URITest, SingeSlashFile) EXPECT_EQ(0, U.Port); EXPECT_EQ("", U.Host); EXPECT_EQ("/usr/bin/foo", U.Path); + EXPECT_EQ("file:/usr/bin/foo", (std::string)U); } TEST(URITest, BasicCDROM) { @@ -40,6 +43,7 @@ TEST(URITest, BasicCDROM) EXPECT_EQ(0, U.Port); EXPECT_EQ("Moo Cow Rom", U.Host); EXPECT_EQ("/debian", U.Path); + EXPECT_EQ("cdrom://Moo Cow Rom/debian", (std::string)U); } TEST(URITest, RelativeGzip) { @@ -50,6 +54,7 @@ TEST(URITest, RelativeGzip) EXPECT_EQ(0, U.Port); EXPECT_EQ(".", U.Host); EXPECT_EQ("/bar/cow", U.Path); + EXPECT_EQ("gzip://./bar/cow", (std::string)U); } TEST(URITest, NoSlashFTP) { @@ -60,6 +65,7 @@ TEST(URITest, NoSlashFTP) EXPECT_EQ(0, U.Port); EXPECT_EQ("ftp.fr.debian.org", U.Host); EXPECT_EQ("/debian/pool/main/x/xtel/xtel_3.2.1-15_i386.deb", U.Path); + EXPECT_EQ("ftp://ftp.fr.debian.org/debian/pool/main/x/xtel/xtel_3.2.1-15_i386.deb", (std::string)U); } TEST(URITest, RFC2732) { @@ -70,6 +76,7 @@ TEST(URITest, RFC2732) EXPECT_EQ(0, U.Port); EXPECT_EQ("1080::8:800:200C:417A", U.Host); EXPECT_EQ("/foo", U.Path); + EXPECT_EQ("http://[1080::8:800:200C:417A]/foo", (std::string)U); // with port U = URI("http://[::FFFF:129.144.52.38]:80/index.html"); EXPECT_EQ("http", U.Access); @@ -78,6 +85,7 @@ TEST(URITest, RFC2732) EXPECT_EQ(80, U.Port); EXPECT_EQ("::FFFF:129.144.52.38", U.Host); EXPECT_EQ("/index.html", U.Path); + EXPECT_EQ("http://[::FFFF:129.144.52.38]:80/index.html", (std::string)U); // extra colon U = URI("http://[::FFFF:129.144.52.38:]:80/index.html"); EXPECT_EQ("http", U.Access); @@ -86,6 +94,7 @@ TEST(URITest, RFC2732) EXPECT_EQ(80, U.Port); EXPECT_EQ("::FFFF:129.144.52.38:", U.Host); EXPECT_EQ("/index.html", U.Path); + EXPECT_EQ("http://[::FFFF:129.144.52.38:]:80/index.html", (std::string)U); // extra colon port U = URI("http://[::FFFF:129.144.52.38:]/index.html"); EXPECT_EQ("http", U.Access); @@ -94,6 +103,7 @@ TEST(URITest, RFC2732) EXPECT_EQ(0, U.Port); EXPECT_EQ("::FFFF:129.144.52.38:", U.Host); EXPECT_EQ("/index.html", U.Path); + EXPECT_EQ("http://[::FFFF:129.144.52.38:]/index.html", (std::string)U); // My Evil Corruption of RFC 2732 to handle CDROM names! // Fun for the whole family! */ U = URI("cdrom:[The Debian 1.2 disk, 1/2 R1:6]/debian/"); @@ -103,6 +113,7 @@ TEST(URITest, RFC2732) EXPECT_EQ(0, U.Port); EXPECT_EQ("The Debian 1.2 disk, 1/2 R1:6", U.Host); EXPECT_EQ("/debian/", U.Path); + EXPECT_EQ("cdrom://[The Debian 1.2 disk, 1/2 R1:6]/debian/", (std::string)U); // no brackets U = URI("cdrom:Foo Bar Cow/debian/"); EXPECT_EQ("cdrom", U.Access); @@ -111,6 +122,7 @@ TEST(URITest, RFC2732) EXPECT_EQ(0, U.Port); EXPECT_EQ("Foo Bar Cow", U.Host); EXPECT_EQ("/debian/", U.Path); + EXPECT_EQ("cdrom://Foo Bar Cow/debian/", (std::string)U); // percent encoded U = URI("ftp://foo:b%40r@example.org"); EXPECT_EQ("foo", U.User); -- 2.45.2