~ubuntu-branches/ubuntu/trusty/aria2/trusty-proposed

« back to all changes in this revision

Viewing changes to src/util.cc

  • Committer: Package Import Robot
  • Author(s): Kartik Mistry
  • Date: 2013-12-16 18:41:03 UTC
  • mfrom: (2.5.21 sid)
  • Revision ID: package-import@ubuntu.com-20131216184103-xzah3019zwut429g
Tags: 1.18.1-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
83
83
#include "DownloadContext.h"
84
84
#include "BufferedFile.h"
85
85
#include "SocketCore.h"
86
 
#include "prefs.h"
87
86
#include "Lock.h"
88
87
 
89
88
#ifdef ENABLE_MESSAGE_DIGEST
279
278
 
280
279
bool isHexDigit(const std::string& s)
281
280
{
282
 
  for(std::string::const_iterator i = s.begin(), eoi = s.end(); i != eoi; ++i) {
283
 
    if(!isHexDigit(*i)) {
 
281
  for (const auto& c : s) {
 
282
    if(!isHexDigit(c)) {
284
283
      return false;
285
284
    }
286
285
  }
348
347
 
349
348
namespace {
350
349
 
351
 
inline static
352
350
bool isUtf8Tail(unsigned char ch)
353
351
{
354
352
  return in(ch, 0x80u, 0xbfu);
355
353
}
356
354
 
357
 
inline static
358
355
bool inPercentEncodeMini(const unsigned char c)
359
356
{
360
357
  return c > 0x20 && c < 0x7fu &&
459
456
    return src;
460
457
  }
461
458
  std::string result;
462
 
  for (const auto& c: src) {
 
459
  for (auto c: src) {
463
460
    if(!inPercentEncodeMini(c)) {
464
 
      result += fmt("%%%02X", c);
 
461
      result += fmt("%%%02X", static_cast<unsigned char>(c));
465
462
    } else {
466
463
      result += c;
467
464
    }
676
673
  if(head == 0) {
677
674
    return;
678
675
  }
679
 
  for(auto fi = fileEntries.begin(), eoi = fileEntries.end(); fi != eoi; ++fi) {
680
 
    if((*fi)->getLength() == 0) {
 
676
  for (const auto& fi: fileEntries) {
 
677
    if(fi->getLength() == 0) {
681
678
      continue;
682
679
    }
683
 
    size_t lastIndex =
684
 
      ((*fi)->getOffset()+std::min(head, (*fi)->getLength())-1)/pieceLength;
685
 
    for(size_t index = (*fi)->getOffset()/pieceLength;
686
 
        index <= lastIndex; ++index) {
687
 
      indexes.push_back(index);
 
680
    const size_t lastIndex = (fi->getOffset() +
 
681
        std::min(head, fi->getLength()) - 1
 
682
        ) / pieceLength;
 
683
    for(size_t idx = fi->getOffset() / pieceLength; idx <= lastIndex; ++idx) {
 
684
      indexes.push_back(idx);
688
685
    }
689
686
  }
690
687
}
700
697
  if(tail == 0) {
701
698
    return;
702
699
  }
703
 
  for(auto fi = fileEntries.begin(), eoi = fileEntries.end(); fi != eoi; ++fi) {
704
 
    if((*fi)->getLength() == 0) {
 
700
  for (const auto& fi: fileEntries) {
 
701
    if(fi->getLength() == 0) {
705
702
      continue;
706
703
    }
707
 
    int64_t endOffset = (*fi)->getLastOffset();
708
 
    size_t fromIndex =
709
 
      (endOffset-1-(std::min(tail, (*fi)->getLength())-1))/pieceLength;
710
 
    for(size_t index = fromIndex; index <= (endOffset-1)/pieceLength;
711
 
        ++index) {
712
 
      indexes.push_back(index);
 
704
    int64_t endOffset = fi->getLastOffset();
 
705
    size_t fromIndex = (endOffset - 1 - (std::min(tail, fi->getLength()) - 1)) /
 
706
      pieceLength;
 
707
    const size_t toIndex = (endOffset - 1) / pieceLength;
 
708
    while (fromIndex <= toIndex) {
 
709
      indexes.push_back(fromIndex++);
713
710
    }
714
711
  }
715
712
}
724
721
  std::vector<size_t> indexes;
725
722
  std::vector<Scip> parts;
726
723
  splitIter(src.begin(), src.end(), std::back_inserter(parts), ',', true);
727
 
  for(std::vector<Scip>::const_iterator i = parts.begin(),
728
 
        eoi = parts.end(); i != eoi; ++i) {
729
 
    if(util::streq((*i).first, (*i).second, "head")) {
 
724
  for (const auto& i: parts) {
 
725
    if(util::streq(i.first, i.second, "head")) {
730
726
      computeHeadPieces(indexes, fileEntries, pieceLength, defaultSize);
731
 
    } else if(util::startsWith((*i).first, (*i).second, "head=")) {
732
 
      std::string sizestr((*i).first+5, (*i).second);
 
727
    }
 
728
    else if(util::startsWith(i.first, i.second, "head=")) {
 
729
      std::string sizestr(i.first + 5, i.second);
733
730
      computeHeadPieces(indexes, fileEntries, pieceLength,
734
731
                        std::max((int64_t)0, getRealSize(sizestr)));
735
 
    } else if(util::streq((*i).first, (*i).second, "tail")) {
 
732
    }
 
733
    else if(util::streq(i.first, i.second, "tail")) {
736
734
      computeTailPieces(indexes, fileEntries, pieceLength, defaultSize);
737
 
    } else if(util::startsWith((*i).first, (*i).second, "tail=")) {
738
 
      std::string sizestr((*i).first+5, (*i).second);
 
735
    }
 
736
    else if(util::startsWith(i.first, i.second, "tail=")) {
 
737
      std::string sizestr(i.first + 5, i.second);
739
738
      computeTailPieces(indexes, fileEntries, pieceLength,
740
739
                        std::max((int64_t)0, getRealSize(sizestr)));
741
 
    } else {
 
740
    }
 
741
    else {
742
742
      throw DL_ABORT_EX(fmt("Unrecognized token %s",
743
 
                            std::string((*i).first, (*i).second).c_str()));
 
743
                            std::string(i.first, i.second).c_str()));
744
744
    }
745
745
  }
746
746
  std::sort(indexes.begin(), indexes.end());
1177
1177
                                         header.c_str(), header.size());
1178
1178
  if(rv == -1) {
1179
1179
    return "";
 
1180
  }
 
1181
 
 
1182
  std::string res;
 
1183
  if(!charset || strieq(charset, charset+charsetlen, "iso-8859-1")) {
 
1184
    res = iso8859p1ToUtf8(cdval, rv);
1180
1185
  } else {
1181
 
    std::string res;
1182
 
    if(!charset || strieq(charset, charset+charsetlen, "iso-8859-1")) {
1183
 
      res = iso8859p1ToUtf8(cdval, rv);
1184
 
    } else {
1185
 
      res.assign(cdval, rv);
1186
 
    }
1187
 
    if(!detectDirTraversal(res) &&
1188
 
       res.find_first_of("/\\") == std::string::npos) {
1189
 
      return res;
1190
 
    } else {
1191
 
      return "";
1192
 
    }
1193
 
  }
 
1186
    res.assign(cdval, rv);
 
1187
  }
 
1188
  if(!detectDirTraversal(res) &&
 
1189
      res.find_first_of("/\\") == std::string::npos) {
 
1190
    return res;
 
1191
  }
 
1192
  return "";
1194
1193
}
1195
1194
 
1196
1195
std::string toUpper(std::string src)
1335
1334
std::string getHomeDir()
1336
1335
{
1337
1336
  const char* p = getenv("HOME");
1338
 
  if(p) {
 
1337
  if (p) {
1339
1338
    return p;
1340
 
  } else {
 
1339
  }
1341
1340
#ifdef __MINGW32__
1342
 
    p = getenv("USERPROFILE");
1343
 
    if(p) {
1344
 
      return p;
1345
 
    } else {
1346
 
      p = getenv("HOMEDRIVE");
1347
 
      if(p) {
1348
 
        std::string homeDir = p;
1349
 
        p = getenv("HOMEPATH");
1350
 
        if(p) {
1351
 
          homeDir += p;
1352
 
          return homeDir;
1353
 
        }
1354
 
      }
 
1341
  p = getenv("USERPROFILE");
 
1342
  if (p) {
 
1343
    return p;
 
1344
  }
 
1345
  p = getenv("HOMEDRIVE");
 
1346
  if (p) {
 
1347
    std::string homeDir = p;
 
1348
    p = getenv("HOMEPATH");
 
1349
    if (p) {
 
1350
      homeDir += p;
 
1351
      return homeDir;
1355
1352
    }
 
1353
  }
1356
1354
#elif HAVE_PWD_H
1357
 
    passwd* pw = getpwuid(geteuid());
1358
 
    if(pw && pw->pw_dir) {
1359
 
      return pw->pw_dir;
1360
 
    }
 
1355
  passwd* pw = getpwuid(geteuid());
 
1356
  if(pw && pw->pw_dir) {
 
1357
    return pw->pw_dir;
 
1358
  }
1361
1359
#endif // HAVE_PWD_H
1362
 
    return A2STR::NIL;
1363
 
  }
 
1360
  return A2STR::NIL;
1364
1361
}
1365
1362
 
1366
1363
int64_t getRealSize(const std::string& sizeWithUnit)
1387
1384
  if(!parseLLIntNoThrow(v, size) || v < 0) {
1388
1385
    throw DL_ABORT_EX(fmt("Bad or negative value detected: %s",
1389
1386
                          sizeWithUnit.c_str()));
1390
 
  } else if(INT64_MAX/mult < v) {
 
1387
  }
 
1388
  if(INT64_MAX/mult < v) {
1391
1389
    throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE,
1392
1390
                          "overflow/underflow"));
1393
1391
  }
1474
1472
  if(!dir.mkdirs()) {
1475
1473
    int errNum = errno;
1476
1474
    if(!dir.isDir()) {
1477
 
      throw DL_ABORT_EX3
1478
 
        (errNum,
1479
 
         fmt(EX_MAKE_DIR, dir.getPath().c_str(),
1480
 
             safeStrerror(errNum).c_str()),
1481
 
         error_code::DIR_CREATE_ERROR);
 
1475
      throw DL_ABORT_EX3(errNum, fmt(EX_MAKE_DIR, dir.getPath().c_str(),
 
1476
                                     safeStrerror(errNum).c_str()),
 
1477
                         error_code::DIR_CREATE_ERROR);
1482
1478
    }
1483
1479
  }
1484
1480
}
1518
1514
  void* buffer;
1519
1515
  int res;
1520
1516
  if((res = posix_memalign(&buffer, alignment, size)) != 0) {
1521
 
    throw FATAL_EXCEPTION
1522
 
      (fmt("Error in posix_memalign: %s",
1523
 
           util::safeStrerror(res).c_str()));
 
1517
    throw FATAL_EXCEPTION(fmt("Error in posix_memalign: %s",
 
1518
                              util::safeStrerror(res).c_str()));
1524
1519
  }
1525
1520
  return buffer;
1526
1521
}
1597
1592
void generateRandomDataRandom(unsigned char* data, size_t length)
1598
1593
{
1599
1594
  const auto& rd = SimpleRandomizer::getInstance();
1600
 
  for(size_t i = 0; i < length; ++i) {
1601
 
    data[i] = static_cast<unsigned long>(rd->getRandomNumber(256));
1602
 
  }
 
1595
  rd->getRandomBytes(data, length);
1603
1596
}
1604
1597
} // namespace
1605
1598
 
1663
1656
  if(dir.empty()) {
1664
1657
    s = "./";
1665
1658
    s += relPath;
1666
 
  } else {
 
1659
  }
 
1660
  else {
1667
1661
    s = dir;
1668
1662
    if(dir == "/") {
1669
1663
      s += relPath;
1670
 
    } else {
 
1664
    }
 
1665
    else {
1671
1666
      s += "/";
1672
1667
      s += relPath;
1673
1668
    }
1728
1723
  if(s.empty()) {
1729
1724
    return false;
1730
1725
  }
1731
 
  for(std::string::const_iterator i = s.begin(), eoi = s.end(); i != eoi; ++i) {
1732
 
    unsigned char c = *i;
1733
 
    if(in(c, 0x00u, 0x1fu) || c == 0x7fu) {
 
1726
  for (auto c : s) {
 
1727
    unsigned char ch = c;
 
1728
    if (in(ch, 0x00u, 0x1fu) || ch == 0x7fu) {
1734
1729
      return true;
1735
1730
    }
1736
1731
  }
1737
1732
  return s == "." || s == ".." || s[0] == '/' ||
1738
 
    util::startsWith(s, "./") || util::startsWith(s, "../") ||
 
1733
    util::startsWith(s, "./") ||
 
1734
    util::startsWith(s, "../") ||
1739
1735
    s.find("/../") != std::string::npos ||
1740
1736
    s.find("/./") != std::string::npos ||
1741
1737
    s[s.size()-1] == '/' ||
1742
 
    util::endsWith(s, "/.") || util::endsWith(s, "/..");
 
1738
    util::endsWith(s, "/.") ||
 
1739
    util::endsWith(s, "/..");
1743
1740
}
1744
1741
 
1745
1742
std::string escapePath(const std::string& s)
1750
1747
    { '"', '*', ':', '<', '>', '?', '\\', '|' };
1751
1748
#endif // __MINGW32__
1752
1749
  std::string d;
1753
 
  for(std::string::const_iterator i = s.begin(), eoi = s.end(); i != eoi; ++i) {
1754
 
    unsigned char c = *i;
 
1750
  for(auto cc: s) {
 
1751
    unsigned char c = cc;
1755
1752
    if(in(c, 0x00u, 0x1fu) || c == 0x7fu
1756
1753
#ifdef __MINGW32__
1757
1754
       || std::find(std::begin(WIN_INVALID_PATH_CHARS),
1761
1758
       ){
1762
1759
      d += fmt("%%%02X", c);
1763
1760
    } else {
1764
 
      d += *i;
 
1761
      d += c;
1765
1762
    }
1766
1763
  }
1767
1764
  return d;
1810
1807
                  numFilesStr.c_str(),
1811
1808
                  firstFilename.c_str()));
1812
1809
  pid_t cpid = fork();
1813
 
  if(cpid == -1) {
1814
 
    A2_LOG_ERROR("fork() failed. Cannot execute user command.");
1815
 
  } else if(cpid == 0) {
 
1810
  if (cpid > 0) {
 
1811
    // child!
1816
1812
    execlp(command.c_str(),
1817
1813
           command.c_str(),
1818
1814
           gidStr.c_str(),
1821
1817
           reinterpret_cast<char*>(0));
1822
1818
    perror(("Could not execute user command: "+command).c_str());
1823
1819
    _exit(EXIT_FAILURE);
1824
 
  }
1825
 
#else
 
1820
    return;
 
1821
  }
 
1822
 
 
1823
  if(cpid == -1) {
 
1824
    A2_LOG_ERROR("fork() failed. Cannot execute user command.");
 
1825
  }
 
1826
  return;
 
1827
 
 
1828
#else // __MINGW32__
1826
1829
  PROCESS_INFORMATION pi;
1827
1830
  STARTUPINFOW si;
1828
1831
 
1832
1835
  bool batch = util::iendsWith(command, ".bat");
1833
1836
  std::string cmdline;
1834
1837
  std::string cmdexe;
 
1838
 
 
1839
  // XXX batch handling, in particular quoting, correct?
1835
1840
  if(batch) {
1836
1841
    const char* p = getenv("windir");
1837
1842
    if(p) {
1878
1883
  if(!rc) {
1879
1884
    A2_LOG_ERROR("CreateProcess() failed. Cannot execute user command.");
1880
1885
  }
 
1886
  return;
 
1887
 
1881
1888
#endif
1882
1889
}
1883
1890
 
1885
1892
 
1886
1893
void executeHookByOptName
1887
1894
(const std::shared_ptr<RequestGroup>& group, const Option* option,
1888
 
 const Pref* pref)
 
1895
 PrefPtr pref)
1889
1896
{
1890
1897
  executeHookByOptName(group.get(), option, pref);
1891
1898
}
1892
1899
 
1893
1900
void executeHookByOptName
1894
 
(const RequestGroup* group, const Option* option, const Pref* pref)
 
1901
(const RequestGroup* group, const Option* option, PrefPtr pref)
1895
1902
{
1896
1903
  const std::string& cmd = option->get(pref);
1897
1904
  if(!cmd.empty()) {
1912
1919
std::string createSafePath
1913
1920
(const std::string& dir, const std::string& filename)
1914
1921
{
1915
 
  return util::applyDir
1916
 
    (dir,
1917
 
     util::isUtf8(filename)?
1918
 
     util::fixTaintedBasename(filename):
1919
 
     util::escapePath(util::percentEncode(filename)));
 
1922
  return util::applyDir(dir, util::isUtf8(filename) ?
 
1923
                             util::fixTaintedBasename(filename) :
 
1924
                             util::escapePath(util::percentEncode(filename))
 
1925
                        );
1920
1926
}
1921
1927
 
1922
1928
std::string encodeNonUtf8(const std::string& s)
1926
1932
 
1927
1933
std::string makeString(const char* str)
1928
1934
{
1929
 
  if(str) {
1930
 
    return str;
1931
 
  } else {
 
1935
  if(!str) {
1932
1936
    return A2STR::NIL;
1933
1937
  }
 
1938
  return str;
1934
1939
}
1935
1940
 
1936
1941
std::string safeStrerror(int errNum)
1944
1949
{
1945
1950
  if(!domain.empty() && domain[0] == '.' && !util::isNumericHost(hostname)) {
1946
1951
    return util::endsWith(hostname, domain);
1947
 
  } else {
1948
 
    return hostname == domain;
1949
1952
  }
 
1953
  return hostname == domain;
1950
1954
}
1951
1955
 
1952
1956
bool tlsHostnameMatch(const std::string& pattern, const std::string& hostname)
1987
1991
  if(hnLeftLabelEnd - hostname.begin() < ptLeftLabelEnd - pattern.begin()) {
1988
1992
    return false;
1989
1993
  }
1990
 
  return
1991
 
    istartsWith(hostname.begin(), hnLeftLabelEnd,
1992
 
                pattern.begin(), ptWildcard) &&
1993
 
    iendsWith(hostname.begin(), hnLeftLabelEnd,
1994
 
              ptWildcard+1, ptLeftLabelEnd);
 
1994
  return istartsWith(hostname.begin(), hnLeftLabelEnd, pattern.begin(),
 
1995
                     ptWildcard) &&
 
1996
         iendsWith(hostname.begin(), hnLeftLabelEnd, ptWildcard + 1,
 
1997
                   ptLeftLabelEnd);
1995
1998
}
1996
1999
 
1997
2000
bool strieq(const std::string& a, const char* b)