<commit_before>/*
 * RToolsInfo.cpp
 *
 * Copyright (C) 2009-19 by RStudio, PBC
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <core/Version.hpp>
#include <core/r_util/RToolsInfo.hpp>

#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

#include <core/Log.hpp>
#include <core/http/URL.hpp>
#include <core/StringUtils.hpp>
#include <core/system/System.hpp>

#include <core/system/RegistryKey.hpp>

#ifndef KEY_WOW64_32KEY
#define KEY_WOW64_32KEY 0x0200
#endif

namespace rstudio {
namespace core {
namespace r_util {

namespace {

std::string asRBuildPath(const FilePath& filePath)
{
   std::string path = filePath.getAbsolutePath();
   boost::algorithm::replace_all(path, "\\", "/");
   if (!boost::algorithm::ends_with(path, "/"))
      path += "/";
   return path;
}

std::vector<std::string> gcc463ClangArgs(const FilePath& installPath)
{
   std::vector<std::string> clangArgs;
   clangArgs.push_back("-I" + installPath.completeChildPath(
      "gcc-4.6.3/i686-w64-mingw32/include").getAbsolutePath());

   clangArgs.push_back("-I" + installPath.completeChildPath(
      "gcc-4.6.3/include/c++/4.6.3").getAbsolutePath());

   std::string bits = "-I" + installPath.completeChildPath(
      "gcc-4.6.3/include/c++/4.6.3/i686-w64-mingw32").getAbsolutePath();
#ifdef _WIN64
   bits += "/64";
#endif
   clangArgs.push_back(bits);
   return clangArgs;
}

void gcc463Configuration(const FilePath& installPath,
                         std::vector<std::string>* pRelativePathEntries,
                         std::vector<std::string>* pClangArgs)
{
   pRelativePathEntries->push_back("bin");
   pRelativePathEntries->push_back("gcc-4.6.3/bin");
   *pClangArgs = gcc463ClangArgs(installPath);
}

} // anonymous namespace

RToolsInfo::RToolsInfo(const std::string& name,
                       const FilePath& installPath,
                       bool usingMingwGcc49)
   : name_(name), installPath_(installPath)
{
   std::string versionMin, versionMax;
   std::vector<std::string> relativePathEntries;
   std::vector<std::string> clangArgs;
   std::vector<core::system::Option> environmentVars;
   if (name == "2.11")
   {
      versionMin = "2.10.0";
      versionMax = "2.11.1";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("perl/bin");
      relativePathEntries.push_back("MinGW/bin");
   }
   else if (name == "2.12")
   {
      versionMin = "2.12.0";
      versionMax = "2.12.2";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("perl/bin");
      relativePathEntries.push_back("MinGW/bin");
      relativePathEntries.push_back("MinGW64/bin");
   }
   else if (name == "2.13")
   {
      versionMin = "2.13.0";
      versionMax = "2.13.2";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("MinGW/bin");
      relativePathEntries.push_back("MinGW64/bin");
   }
   else if (name == "2.14")
   {
      versionMin = "2.13.0";
      versionMax = "2.14.2";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("MinGW/bin");
      relativePathEntries.push_back("MinGW64/bin");
   }
   else if (name == "2.15")
   {
      versionMin = "2.14.2";
      versionMax = "2.15.1";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("gcc-4.6.3/bin");
      clangArgs = gcc463ClangArgs(installPath);
   }
   else if (name == "2.16" || name == "3.0")
   {
      versionMin = "2.15.2";
      versionMax = "3.0.99";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.1")
   {
      versionMin = "3.0.0";
      versionMax = "3.1.99";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.2")
   {
      versionMin = "3.1.0";
      versionMax = "3.2.0";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.3")
   {
      versionMin = "3.2.0";
      versionMax = "3.2.99";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.4" || name == "3.5")
   {
      versionMin = "3.3.0";
      if (name == "3.4")
         versionMax = "3.5.99";  // Rtools 3.4
      else
         versionMax = "3.6.99";  // Rtools 3.5

      relativePathEntries.push_back("bin");

      // set environment variables
      FilePath gccPath = installPath_.completeChildPath("mingw_$(WIN)/bin");
      environmentVars.push_back(
            std::make_pair("BINPREF", asRBuildPath(gccPath)));

      // set clang args
#ifdef _WIN64
      std::string baseDir = "mingw_64";
      std::string arch = "x86_64";
#else
      std::string baseDir = "mingw_32";
      std::string arch = "i686";
#endif

      boost::format mgwIncFmt("%1%/%2%-w64-mingw32/include");
      std::string mgwInc = boost::str(mgwIncFmt % baseDir % arch);
      clangArgs.push_back(
            "-I" + installPath.completeChildPath(mgwInc).getAbsolutePath());

      std::string cppInc = mgwInc + "/c++";
      clangArgs.push_back(
            "-I" + installPath.completeChildPath(cppInc).getAbsolutePath());

      boost::format bitsIncFmt("%1%/%2%-w64-mingw32");
      std::string bitsInc = boost::str(bitsIncFmt % cppInc % arch);
      clangArgs.push_back(
            "-I" + installPath.completeChildPath(bitsInc).getAbsolutePath());
   }
   else if (name == "4.0")
   {
      versionMin = "4.0.0";
      versionMax = "5.0.0";

      // PATH for utilities
      relativePathEntries.push_back("usr/bin");

      // set BINPREF
      environmentVars.push_back({"BINPREF", "/mingw$(WIN)/bin/"});

      // set clang args
#ifdef _WIN64
      std::string baseDir = "mingw64";
      std::string arch = "x86_64";
#else
      std::string baseDir = "mingw32";
      std::string arch = "i686";
#endif

      // path to mingw includes
      boost::format mgwIncFmt("%1%/%2%-w64-mingw32/include");
      std::string mingwIncludeSuffix = boost::str(mgwIncFmt % baseDir % arch);
      FilePath mingwIncludePath = installPath.completeChildPath(mingwIncludeSuffix);
      clangArgs.push_back("-I" + mingwIncludePath.getAbsolutePath());

      // path to C++ headers
      std::string cppSuffix = "c++/8.3.0";
      FilePath cppIncludePath = installPath.completeChildPath(cppSuffix);
      clangArgs.push_back("-I" + cppIncludePath.getAbsolutePath());
   }
   else
   {
      LOG_DEBUG_MESSAGE("Unrecognized Rtools installation at path '" + installPath.getAbsolutePath() + "'");
   }

   // build version predicate and path list if we can
   if (!versionMin.empty())
   {
      boost::format fmt("getRversion() >= \"%1%\" && getRversion() <= \"%2%\"");
      versionPredicate_ = boost::str(fmt % versionMin % versionMax);

      for (const std::string& relativePath : relativePathEntries)
      {
         pathEntries_.push_back(installPath_.completeChildPath(relativePath));
      }

      clangArgs_ = clangArgs;
      environmentVars_ = environmentVars;
   }
}

std::string RToolsInfo::url(const std::string& repos) const
{
   std::string url;

   if (name() == "4.0")
   {
      // TODO: Currently, Rtools 4.0 is only available from the 'testing'
      // sub-directory. Update this URL once it's been promoted.
      std::string arch = core::system::isWin64() ? "x86_64" : "i686";
      std::string suffix = "bin/windows/testing/rtools40-" + arch + ".exe";
      url = core::http::URL::complete(repos, suffix);
   }
   else
   {
      std::string version = boost::algorithm::replace_all_copy(name(), ".", "");
      std::string suffix = "bin/windows/Rtools/Rtools" + version + ".exe";
      url = core::http::URL::complete(repos, suffix);
   }

   return url;
}

std::ostream& operator<<(std::ostream& os, const RToolsInfo& info)
{
   os << "Rtools " << info.name() << std::endl;
   os << info.versionPredicate() << std::endl;
   for (const FilePath& pathEntry : info.pathEntries())
   {
     os << pathEntry << std::endl;
   }
   for (const core::system::Option& var : info.environmentVars())
   {
      os << var.first << "=" << var.second << std::endl;
   }

   return os;
}

namespace {

Error scanEnvironmentForRTools(bool usingMingwGcc49,
                               const std::string& envvar,
                               std::vector<RToolsInfo>* pRTools)
{
   // nothing to do if we have no envvar
   if (envvar.empty())
      return Success();

   // read value
   std::string envval = core::system::getenv(envvar);
   if (envval.empty())
      return Success();

   // build info
   FilePath installPath(envval);
   RToolsInfo toolsInfo("4.0", installPath, usingMingwGcc49);

   // check that recorded path is valid
   bool ok =
       toolsInfo.isStillInstalled() &&
       toolsInfo.isRecognized();

   // use it if all looks well
   if (ok)
      pRTools->push_back(toolsInfo);

   return Success();

}

Error scanRegistryForRTools(HKEY key,
                            bool usingMingwGcc49,
                            std::vector<RToolsInfo>* pRTools)
{
   core::system::RegistryKey regKey;
   Error error = regKey.open(key,
                             "Software\\R-core\\Rtools",
                             KEY_READ | KEY_WOW64_32KEY);
   if (error)
   {
      if (error != systemError(boost::system::errc::no_such_file_or_directory, ErrorLocation()))
         return error;
      else
         return Success();
   }

   std::vector<std::string> keys = regKey.keyNames();
   for (size_t i = 0; i < keys.size(); i++)
   {
      std::string name = keys.at(i);
      core::system::RegistryKey verKey;
      error = verKey.open(regKey.handle(),
                          name,
                          KEY_READ | KEY_WOW64_32KEY);
      if (error)
      {
         LOG_ERROR(error);
         continue;
      }

      std::string installPath = verKey.getStringValue("InstallPath", "");
      if (!installPath.empty())
      {
         std::string utf8InstallPath = string_utils::systemToUtf8(installPath);
         RToolsInfo toolsInfo(name, FilePath(utf8InstallPath), usingMingwGcc49);
         if (toolsInfo.isStillInstalled())
         {
            if (toolsInfo.isRecognized())
               pRTools->push_back(toolsInfo);
            else
               LOG_WARNING_MESSAGE("Unknown Rtools version: " + name);
         }
      }
   }

   return Success();
}

void scanRegistryForRTools(bool usingMingwGcc49,
                           std::vector<RToolsInfo>* pRTools)
{
   // try HKLM first (backwards compatible with previous code)
   Error error = scanRegistryForRTools(
            HKEY_LOCAL_MACHINE,
            usingMingwGcc49,
            pRTools);

   if (error)
      LOG_ERROR(error);

   // try HKCU as a fallback
   if (pRTools->empty())
   {
      Error error = scanRegistryForRTools(
               HKEY_CURRENT_USER,
               usingMingwGcc49,
               pRTools);
      if (error)
         LOG_ERROR(error);
   }
}

void scanFoldersForRTools(bool usingMingwGcc49, std::vector<RToolsInfo>* pRTools)
{
   // look for Rtools as installed by RStudio
   std::string systemDrive = core::system::getenv("SYSTEMDRIVE");
   FilePath buildDirRoot(systemDrive + "/RBuildTools");

   // ensure it exists (may not exist if the user has not installed
   // any copies of Rtools through RStudio yet)
   if (!buildDirRoot.exists())
      return;

   // find sub-directories
   std::vector<FilePath> buildDirs;
   Error error = buildDirRoot.getChildren(buildDirs);
   if (error)
      LOG_ERROR(error);

   // infer Rtools information from each directory
   for (const FilePath& buildDir : buildDirs)
   {
      RToolsInfo toolsInfo(buildDir.getFilename(), buildDir, usingMingwGcc49);
      if (toolsInfo.isRecognized())
         pRTools->push_back(toolsInfo);
      else
         LOG_WARNING_MESSAGE("Unknown Rtools version: " + buildDir.getFilename());
   }
}

} // end anonymous namespace

void scanForRTools(bool usingMingwGcc49,
                   const std::string& rtoolsHomeEnvVar,
                   std::vector<RToolsInfo>* pRTools)
{
   std::vector<RToolsInfo> rtoolsInfo;

   // scan for Rtools
   scanEnvironmentForRTools(usingMingwGcc49, rtoolsHomeEnvVar, &rtoolsInfo);
   scanRegistryForRTools(usingMingwGcc49, &rtoolsInfo);
   scanFoldersForRTools(usingMingwGcc49, &rtoolsInfo);

   // remove duplicates
   std::set<FilePath> knownPaths;
   for (const RToolsInfo& info : rtoolsInfo)
   {
      if (knownPaths.count(info.installPath()))
         continue;

      knownPaths.insert(info.installPath());
      pRTools->push_back(info);
   }

   // ensure sorted by version
   std::sort(
            pRTools->begin(),
            pRTools->end(),
            [](const RToolsInfo& lhs, const RToolsInfo& rhs)
   {
      return Version(lhs.name()) < Version(rhs.name());
   });
}

} // namespace r_util
} // namespace core
} // namespace rstudio

<commit_msg>update Rtools URL<commit_after>/*
 * RToolsInfo.cpp
 *
 * Copyright (C) 2009-19 by RStudio, PBC
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <core/Version.hpp>
#include <core/r_util/RToolsInfo.hpp>

#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

#include <core/Log.hpp>
#include <core/http/URL.hpp>
#include <core/StringUtils.hpp>
#include <core/system/System.hpp>

#include <core/system/RegistryKey.hpp>

#ifndef KEY_WOW64_32KEY
#define KEY_WOW64_32KEY 0x0200
#endif

namespace rstudio {
namespace core {
namespace r_util {

namespace {

std::string asRBuildPath(const FilePath& filePath)
{
   std::string path = filePath.getAbsolutePath();
   boost::algorithm::replace_all(path, "\\", "/");
   if (!boost::algorithm::ends_with(path, "/"))
      path += "/";
   return path;
}

std::vector<std::string> gcc463ClangArgs(const FilePath& installPath)
{
   std::vector<std::string> clangArgs;
   clangArgs.push_back("-I" + installPath.completeChildPath(
      "gcc-4.6.3/i686-w64-mingw32/include").getAbsolutePath());

   clangArgs.push_back("-I" + installPath.completeChildPath(
      "gcc-4.6.3/include/c++/4.6.3").getAbsolutePath());

   std::string bits = "-I" + installPath.completeChildPath(
      "gcc-4.6.3/include/c++/4.6.3/i686-w64-mingw32").getAbsolutePath();
#ifdef _WIN64
   bits += "/64";
#endif
   clangArgs.push_back(bits);
   return clangArgs;
}

void gcc463Configuration(const FilePath& installPath,
                         std::vector<std::string>* pRelativePathEntries,
                         std::vector<std::string>* pClangArgs)
{
   pRelativePathEntries->push_back("bin");
   pRelativePathEntries->push_back("gcc-4.6.3/bin");
   *pClangArgs = gcc463ClangArgs(installPath);
}

} // anonymous namespace

RToolsInfo::RToolsInfo(const std::string& name,
                       const FilePath& installPath,
                       bool usingMingwGcc49)
   : name_(name), installPath_(installPath)
{
   std::string versionMin, versionMax;
   std::vector<std::string> relativePathEntries;
   std::vector<std::string> clangArgs;
   std::vector<core::system::Option> environmentVars;
   if (name == "2.11")
   {
      versionMin = "2.10.0";
      versionMax = "2.11.1";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("perl/bin");
      relativePathEntries.push_back("MinGW/bin");
   }
   else if (name == "2.12")
   {
      versionMin = "2.12.0";
      versionMax = "2.12.2";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("perl/bin");
      relativePathEntries.push_back("MinGW/bin");
      relativePathEntries.push_back("MinGW64/bin");
   }
   else if (name == "2.13")
   {
      versionMin = "2.13.0";
      versionMax = "2.13.2";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("MinGW/bin");
      relativePathEntries.push_back("MinGW64/bin");
   }
   else if (name == "2.14")
   {
      versionMin = "2.13.0";
      versionMax = "2.14.2";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("MinGW/bin");
      relativePathEntries.push_back("MinGW64/bin");
   }
   else if (name == "2.15")
   {
      versionMin = "2.14.2";
      versionMax = "2.15.1";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("gcc-4.6.3/bin");
      clangArgs = gcc463ClangArgs(installPath);
   }
   else if (name == "2.16" || name == "3.0")
   {
      versionMin = "2.15.2";
      versionMax = "3.0.99";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.1")
   {
      versionMin = "3.0.0";
      versionMax = "3.1.99";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.2")
   {
      versionMin = "3.1.0";
      versionMax = "3.2.0";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.3")
   {
      versionMin = "3.2.0";
      versionMax = "3.2.99";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.4" || name == "3.5")
   {
      versionMin = "3.3.0";
      if (name == "3.4")
         versionMax = "3.5.99";  // Rtools 3.4
      else
         versionMax = "3.6.99";  // Rtools 3.5

      relativePathEntries.push_back("bin");

      // set environment variables
      FilePath gccPath = installPath_.completeChildPath("mingw_$(WIN)/bin");
      environmentVars.push_back(
            std::make_pair("BINPREF", asRBuildPath(gccPath)));

      // set clang args
#ifdef _WIN64
      std::string baseDir = "mingw_64";
      std::string arch = "x86_64";
#else
      std::string baseDir = "mingw_32";
      std::string arch = "i686";
#endif

      boost::format mgwIncFmt("%1%/%2%-w64-mingw32/include");
      std::string mgwInc = boost::str(mgwIncFmt % baseDir % arch);
      clangArgs.push_back(
            "-I" + installPath.completeChildPath(mgwInc).getAbsolutePath());

      std::string cppInc = mgwInc + "/c++";
      clangArgs.push_back(
            "-I" + installPath.completeChildPath(cppInc).getAbsolutePath());

      boost::format bitsIncFmt("%1%/%2%-w64-mingw32");
      std::string bitsInc = boost::str(bitsIncFmt % cppInc % arch);
      clangArgs.push_back(
            "-I" + installPath.completeChildPath(bitsInc).getAbsolutePath());
   }
   else if (name == "4.0")
   {
      versionMin = "4.0.0";
      versionMax = "5.0.0";

      // PATH for utilities
      relativePathEntries.push_back("usr/bin");

      // set BINPREF
      environmentVars.push_back({"BINPREF", "/mingw$(WIN)/bin/"});

      // set clang args
#ifdef _WIN64
      std::string baseDir = "mingw64";
      std::string arch = "x86_64";
#else
      std::string baseDir = "mingw32";
      std::string arch = "i686";
#endif

      // path to mingw includes
      boost::format mgwIncFmt("%1%/%2%-w64-mingw32/include");
      std::string mingwIncludeSuffix = boost::str(mgwIncFmt % baseDir % arch);
      FilePath mingwIncludePath = installPath.completeChildPath(mingwIncludeSuffix);
      clangArgs.push_back("-I" + mingwIncludePath.getAbsolutePath());

      // path to C++ headers
      std::string cppSuffix = "c++/8.3.0";
      FilePath cppIncludePath = installPath.completeChildPath(cppSuffix);
      clangArgs.push_back("-I" + cppIncludePath.getAbsolutePath());
   }
   else
   {
      LOG_DEBUG_MESSAGE("Unrecognized Rtools installation at path '" + installPath.getAbsolutePath() + "'");
   }

   // build version predicate and path list if we can
   if (!versionMin.empty())
   {
      boost::format fmt("getRversion() >= \"%1%\" && getRversion() <= \"%2%\"");
      versionPredicate_ = boost::str(fmt % versionMin % versionMax);

      for (const std::string& relativePath : relativePathEntries)
      {
         pathEntries_.push_back(installPath_.completeChildPath(relativePath));
      }

      clangArgs_ = clangArgs;
      environmentVars_ = environmentVars;
   }
}

std::string RToolsInfo::url(const std::string& repos) const
{
   std::string url;

   if (name() == "4.0")
   {
      std::string arch = core::system::isWin64() ? "x86_64" : "i686";
      std::string suffix = "bin/windows/Rtools/rtools40-" + arch + ".exe";
      url = core::http::URL::complete(repos, suffix);
   }
   else
   {
      std::string version = boost::algorithm::replace_all_copy(name(), ".", "");
      std::string suffix = "bin/windows/Rtools/Rtools" + version + ".exe";
      url = core::http::URL::complete(repos, suffix);
   }

   return url;
}

std::ostream& operator<<(std::ostream& os, const RToolsInfo& info)
{
   os << "Rtools " << info.name() << std::endl;
   os << info.versionPredicate() << std::endl;
   for (const FilePath& pathEntry : info.pathEntries())
   {
     os << pathEntry << std::endl;
   }
   for (const core::system::Option& var : info.environmentVars())
   {
      os << var.first << "=" << var.second << std::endl;
   }

   return os;
}

namespace {

Error scanEnvironmentForRTools(bool usingMingwGcc49,
                               const std::string& envvar,
                               std::vector<RToolsInfo>* pRTools)
{
   // nothing to do if we have no envvar
   if (envvar.empty())
      return Success();

   // read value
   std::string envval = core::system::getenv(envvar);
   if (envval.empty())
      return Success();

   // build info
   FilePath installPath(envval);
   RToolsInfo toolsInfo("4.0", installPath, usingMingwGcc49);

   // check that recorded path is valid
   bool ok =
       toolsInfo.isStillInstalled() &&
       toolsInfo.isRecognized();

   // use it if all looks well
   if (ok)
      pRTools->push_back(toolsInfo);

   return Success();

}

Error scanRegistryForRTools(HKEY key,
                            bool usingMingwGcc49,
                            std::vector<RToolsInfo>* pRTools)
{
   core::system::RegistryKey regKey;
   Error error = regKey.open(key,
                             "Software\\R-core\\Rtools",
                             KEY_READ | KEY_WOW64_32KEY);
   if (error)
   {
      if (error != systemError(boost::system::errc::no_such_file_or_directory, ErrorLocation()))
         return error;
      else
         return Success();
   }

   std::vector<std::string> keys = regKey.keyNames();
   for (size_t i = 0; i < keys.size(); i++)
   {
      std::string name = keys.at(i);
      core::system::RegistryKey verKey;
      error = verKey.open(regKey.handle(),
                          name,
                          KEY_READ | KEY_WOW64_32KEY);
      if (error)
      {
         LOG_ERROR(error);
         continue;
      }

      std::string installPath = verKey.getStringValue("InstallPath", "");
      if (!installPath.empty())
      {
         std::string utf8InstallPath = string_utils::systemToUtf8(installPath);
         RToolsInfo toolsInfo(name, FilePath(utf8InstallPath), usingMingwGcc49);
         if (toolsInfo.isStillInstalled())
         {
            if (toolsInfo.isRecognized())
               pRTools->push_back(toolsInfo);
            else
               LOG_WARNING_MESSAGE("Unknown Rtools version: " + name);
         }
      }
   }

   return Success();
}

void scanRegistryForRTools(bool usingMingwGcc49,
                           std::vector<RToolsInfo>* pRTools)
{
   // try HKLM first (backwards compatible with previous code)
   Error error = scanRegistryForRTools(
            HKEY_LOCAL_MACHINE,
            usingMingwGcc49,
            pRTools);

   if (error)
      LOG_ERROR(error);

   // try HKCU as a fallback
   if (pRTools->empty())
   {
      Error error = scanRegistryForRTools(
               HKEY_CURRENT_USER,
               usingMingwGcc49,
               pRTools);
      if (error)
         LOG_ERROR(error);
   }
}

void scanFoldersForRTools(bool usingMingwGcc49, std::vector<RToolsInfo>* pRTools)
{
   // look for Rtools as installed by RStudio
   std::string systemDrive = core::system::getenv("SYSTEMDRIVE");
   FilePath buildDirRoot(systemDrive + "/RBuildTools");

   // ensure it exists (may not exist if the user has not installed
   // any copies of Rtools through RStudio yet)
   if (!buildDirRoot.exists())
      return;

   // find sub-directories
   std::vector<FilePath> buildDirs;
   Error error = buildDirRoot.getChildren(buildDirs);
   if (error)
      LOG_ERROR(error);

   // infer Rtools information from each directory
   for (const FilePath& buildDir : buildDirs)
   {
      RToolsInfo toolsInfo(buildDir.getFilename(), buildDir, usingMingwGcc49);
      if (toolsInfo.isRecognized())
         pRTools->push_back(toolsInfo);
      else
         LOG_WARNING_MESSAGE("Unknown Rtools version: " + buildDir.getFilename());
   }
}

} // end anonymous namespace

void scanForRTools(bool usingMingwGcc49,
                   const std::string& rtoolsHomeEnvVar,
                   std::vector<RToolsInfo>* pRTools)
{
   std::vector<RToolsInfo> rtoolsInfo;

   // scan for Rtools
   scanEnvironmentForRTools(usingMingwGcc49, rtoolsHomeEnvVar, &rtoolsInfo);
   scanRegistryForRTools(usingMingwGcc49, &rtoolsInfo);
   scanFoldersForRTools(usingMingwGcc49, &rtoolsInfo);

   // remove duplicates
   std::set<FilePath> knownPaths;
   for (const RToolsInfo& info : rtoolsInfo)
   {
      if (knownPaths.count(info.installPath()))
         continue;

      knownPaths.insert(info.installPath());
      pRTools->push_back(info);
   }

   // ensure sorted by version
   std::sort(
            pRTools->begin(),
            pRTools->end(),
            [](const RToolsInfo& lhs, const RToolsInfo& rhs)
   {
      return Version(lhs.name()) < Version(rhs.name());
   });
}

} // namespace r_util
} // namespace core
} // namespace rstudio

<|endoftext|>


<commit_before>/*
 * RToolsInfo.cpp
 *
 * Copyright (C) 2009-18 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <core/r_util/RToolsInfo.hpp>

#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

#include <core/Log.hpp>
#include <core/http/URL.hpp>
#include <core/StringUtils.hpp>
#include <core/system/Types.hpp>

#include <core/system/RegistryKey.hpp>

#ifndef KEY_WOW64_32KEY
#define KEY_WOW64_32KEY 0x0200
#endif

namespace rstudio {
namespace core {
namespace r_util {

namespace {

std::string asRBuildPath(const FilePath& filePath)
{
   std::string path = filePath.absolutePath();
   boost::algorithm::replace_all(path, "\\", "/");
   if (!boost::algorithm::ends_with(path, "/"))
      path += "/";
   return path;
}

std::vector<std::string> gcc463ClangArgs(const FilePath& installPath)
{
   std::vector<std::string> clangArgs;
   clangArgs.push_back("-I" + installPath.childPath(
      "gcc-4.6.3/i686-w64-mingw32/include").absolutePath());

   clangArgs.push_back("-I" + installPath.childPath(
      "gcc-4.6.3/include/c++/4.6.3").absolutePath());

   std::string bits = "-I" + installPath.childPath(
      "gcc-4.6.3/include/c++/4.6.3/i686-w64-mingw32").absolutePath();
#ifdef _WIN64
   bits += "/64";
#endif
   clangArgs.push_back(bits);
   return clangArgs;
}

void gcc463Configuration(const FilePath& installPath,
                         std::vector<std::string>* pRelativePathEntries,
                         std::vector<std::string>* pClangArgs)
{
   pRelativePathEntries->push_back("bin");
   pRelativePathEntries->push_back("gcc-4.6.3/bin");
   *pClangArgs = gcc463ClangArgs(installPath);
}

} // anonymous namespace

RToolsInfo::RToolsInfo(const std::string& name,
                       const FilePath& installPath,
                       bool usingMingwGcc49)
   : name_(name), installPath_(installPath)
{
   std::string versionMin, versionMax;
   std::vector<std::string> relativePathEntries;
   std::vector<std::string> clangArgs;
   std::vector<core::system::Option> environmentVars;
   if (name == "2.11")
   {
      versionMin = "2.10.0";
      versionMax = "2.11.1";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("perl/bin");
      relativePathEntries.push_back("MinGW/bin");
   }
   else if (name == "2.12")
   {
      versionMin = "2.12.0";
      versionMax = "2.12.2";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("perl/bin");
      relativePathEntries.push_back("MinGW/bin");
      relativePathEntries.push_back("MinGW64/bin");
   }
   else if (name == "2.13")
   {
      versionMin = "2.13.0";
      versionMax = "2.13.2";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("MinGW/bin");
      relativePathEntries.push_back("MinGW64/bin");
   }
   else if (name == "2.14")
   {
      versionMin = "2.13.0";
      versionMax = "2.14.2";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("MinGW/bin");
      relativePathEntries.push_back("MinGW64/bin");
   }
   else if (name == "2.15")
   {
      versionMin = "2.14.2";
      versionMax = "2.15.1";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("gcc-4.6.3/bin");
      clangArgs = gcc463ClangArgs(installPath);
   }
   else if (name == "2.16" || name == "3.0")
   {
      versionMin = "2.15.2";
      versionMax = "3.0.99";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.1")
   {
      versionMin = "3.0.0";
      versionMax = "3.1.99";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.2")
   {
      versionMin = "3.1.0";
      versionMax = "3.2.0";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.3")
   {
      versionMin = "3.2.0";
      versionMax = "3.2.99";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.4" || name == "3.5")
   {
      versionMin = "3.3.0";
      versionMax = "3.5.99";

      relativePathEntries.push_back("bin");

      // set environment variables
      FilePath gccPath = installPath_.childPath("mingw_$(WIN)/bin");
      environmentVars.push_back(
            std::make_pair("BINPREF", asRBuildPath(gccPath)));

      // set clang args
#ifdef _WIN64
      std::string baseDir = "mingw_64";
      std::string arch = "x86_64";
#else
      std::string baseDir = "mingw_32";
      std::string arch = "i686";
#endif

      boost::format mgwIncFmt("%1%/%2%-w64-mingw32/include");
      std::string mgwInc = boost::str(mgwIncFmt % baseDir % arch);
      clangArgs.push_back(
            "-I" + installPath.childPath(mgwInc).absolutePath());

      std::string cppInc = mgwInc + "/c++";
      clangArgs.push_back(
            "-I" + installPath.childPath(cppInc).absolutePath());

      boost::format bitsIncFmt("%1%/%2%-w64-mingw32");
      std::string bitsInc = boost::str(bitsIncFmt % cppInc % arch);
      clangArgs.push_back(
            "-I" + installPath.childPath(bitsInc).absolutePath());
   }

   // build version predicate and path list if we can
   if (!versionMin.empty())
   {
      boost::format fmt("getRversion() >= \"%1%\" && getRversion() <= \"%2%\"");
      versionPredicate_ = boost::str(fmt % versionMin % versionMax);

      BOOST_FOREACH(const std::string& relativePath, relativePathEntries)
      {
         pathEntries_.push_back(installPath_.childPath(relativePath));
      }

      clangArgs_ = clangArgs;
      environmentVars_ = environmentVars;
   }
}

std::string RToolsInfo::url(const std::string& repos) const
{
   // strip period from name
   std::string ver = boost::algorithm::replace_all_copy(name(), ".", "");
   std::string url = core::http::URL::complete(
                        repos, "bin/windows/Rtools/Rtools" + ver + ".exe");
   return url;
}

std::ostream& operator<<(std::ostream& os, const RToolsInfo& info)
{
   os << "Rtools " << info.name() << std::endl;
   os << info.versionPredicate() << std::endl;
   BOOST_FOREACH(const FilePath& pathEntry, info.pathEntries())
   {
     os << pathEntry << std::endl;
   }
   BOOST_FOREACH(const core::system::Option& var, info.environmentVars())
   {
      os << var.first << "=" << var.second << std::endl;
   }

   return os;
}

Error scanRegistryForRTools(HKEY key,
                            bool usingMingwGcc49,
                            std::vector<RToolsInfo>* pRTools)
{
   core::system::RegistryKey regKey;
   Error error = regKey.open(key,
                             "Software\\R-core\\Rtools",
                             KEY_READ | KEY_WOW64_32KEY);
   if (error)
   {
      if (error.code() != boost::system::errc::no_such_file_or_directory)
         return error;
      else
         return Success();
   }

   std::vector<std::string> keys = regKey.keyNames();
   for (size_t i = 0; i < keys.size(); i++)
   {
      std::string name = keys.at(i);
      core::system::RegistryKey verKey;
      error = verKey.open(regKey.handle(),
                          name,
                          KEY_READ | KEY_WOW64_32KEY);
      if (error)
      {
         LOG_ERROR(error);
         continue;
      }

      std::string installPath = verKey.getStringValue("InstallPath", "");
      if (!installPath.empty())
      {
         std::string utf8InstallPath = string_utils::systemToUtf8(installPath);
         RToolsInfo toolsInfo(name, FilePath(utf8InstallPath), usingMingwGcc49);
         if (toolsInfo.isStillInstalled())
         {
            if (toolsInfo.isRecognized())
               pRTools->push_back(toolsInfo);
            else
               LOG_WARNING_MESSAGE("Unknown Rtools version: " + name);
         }
      }
   }

   return Success();
}

Error scanRegistryForRTools(bool usingMingwGcc49,
                            std::vector<RToolsInfo>* pRTools)
{
   // try HKLM first (backwards compatible with previous code)
   Error error = scanRegistryForRTools(HKEY_LOCAL_MACHINE,
                                       usingMingwGcc49,
                                       pRTools);
   if (error)
      return error;

   // try HKCU as a fallback
   if (pRTools->empty())
      return scanRegistryForRTools(HKEY_CURRENT_USER,
                                   usingMingwGcc49,
                                   pRTools);
   else
      return Success();
}

} // namespace r_util
} // namespace core
} // namespace rstudio

<commit_msg>allow use of Rtools 3.5 for R 3.6 (devel)<commit_after>/*
 * RToolsInfo.cpp
 *
 * Copyright (C) 2009-18 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <core/r_util/RToolsInfo.hpp>

#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

#include <core/Log.hpp>
#include <core/http/URL.hpp>
#include <core/StringUtils.hpp>
#include <core/system/Types.hpp>

#include <core/system/RegistryKey.hpp>

#ifndef KEY_WOW64_32KEY
#define KEY_WOW64_32KEY 0x0200
#endif

namespace rstudio {
namespace core {
namespace r_util {

namespace {

std::string asRBuildPath(const FilePath& filePath)
{
   std::string path = filePath.absolutePath();
   boost::algorithm::replace_all(path, "\\", "/");
   if (!boost::algorithm::ends_with(path, "/"))
      path += "/";
   return path;
}

std::vector<std::string> gcc463ClangArgs(const FilePath& installPath)
{
   std::vector<std::string> clangArgs;
   clangArgs.push_back("-I" + installPath.childPath(
      "gcc-4.6.3/i686-w64-mingw32/include").absolutePath());

   clangArgs.push_back("-I" + installPath.childPath(
      "gcc-4.6.3/include/c++/4.6.3").absolutePath());

   std::string bits = "-I" + installPath.childPath(
      "gcc-4.6.3/include/c++/4.6.3/i686-w64-mingw32").absolutePath();
#ifdef _WIN64
   bits += "/64";
#endif
   clangArgs.push_back(bits);
   return clangArgs;
}

void gcc463Configuration(const FilePath& installPath,
                         std::vector<std::string>* pRelativePathEntries,
                         std::vector<std::string>* pClangArgs)
{
   pRelativePathEntries->push_back("bin");
   pRelativePathEntries->push_back("gcc-4.6.3/bin");
   *pClangArgs = gcc463ClangArgs(installPath);
}

} // anonymous namespace

RToolsInfo::RToolsInfo(const std::string& name,
                       const FilePath& installPath,
                       bool usingMingwGcc49)
   : name_(name), installPath_(installPath)
{
   std::string versionMin, versionMax;
   std::vector<std::string> relativePathEntries;
   std::vector<std::string> clangArgs;
   std::vector<core::system::Option> environmentVars;
   if (name == "2.11")
   {
      versionMin = "2.10.0";
      versionMax = "2.11.1";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("perl/bin");
      relativePathEntries.push_back("MinGW/bin");
   }
   else if (name == "2.12")
   {
      versionMin = "2.12.0";
      versionMax = "2.12.2";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("perl/bin");
      relativePathEntries.push_back("MinGW/bin");
      relativePathEntries.push_back("MinGW64/bin");
   }
   else if (name == "2.13")
   {
      versionMin = "2.13.0";
      versionMax = "2.13.2";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("MinGW/bin");
      relativePathEntries.push_back("MinGW64/bin");
   }
   else if (name == "2.14")
   {
      versionMin = "2.13.0";
      versionMax = "2.14.2";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("MinGW/bin");
      relativePathEntries.push_back("MinGW64/bin");
   }
   else if (name == "2.15")
   {
      versionMin = "2.14.2";
      versionMax = "2.15.1";
      relativePathEntries.push_back("bin");
      relativePathEntries.push_back("gcc-4.6.3/bin");
      clangArgs = gcc463ClangArgs(installPath);
   }
   else if (name == "2.16" || name == "3.0")
   {
      versionMin = "2.15.2";
      versionMax = "3.0.99";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.1")
   {
      versionMin = "3.0.0";
      versionMax = "3.1.99";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.2")
   {
      versionMin = "3.1.0";
      versionMax = "3.2.0";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.3")
   {
      versionMin = "3.2.0";
      versionMax = "3.2.99";
      gcc463Configuration(installPath, &relativePathEntries, &clangArgs);
   }
   else if (name == "3.4" || name == "3.5")
   {
      versionMin = "3.3.0";
      if (name == "3.4")
         versionMax = "3.5.99";  // Rtools 3.4
      else
         versionMax = "3.6.99";  // Rtools 3.5

      relativePathEntries.push_back("bin");

      // set environment variables
      FilePath gccPath = installPath_.childPath("mingw_$(WIN)/bin");
      environmentVars.push_back(
            std::make_pair("BINPREF", asRBuildPath(gccPath)));

      // set clang args
#ifdef _WIN64
      std::string baseDir = "mingw_64";
      std::string arch = "x86_64";
#else
      std::string baseDir = "mingw_32";
      std::string arch = "i686";
#endif

      boost::format mgwIncFmt("%1%/%2%-w64-mingw32/include");
      std::string mgwInc = boost::str(mgwIncFmt % baseDir % arch);
      clangArgs.push_back(
            "-I" + installPath.childPath(mgwInc).absolutePath());

      std::string cppInc = mgwInc + "/c++";
      clangArgs.push_back(
            "-I" + installPath.childPath(cppInc).absolutePath());

      boost::format bitsIncFmt("%1%/%2%-w64-mingw32");
      std::string bitsInc = boost::str(bitsIncFmt % cppInc % arch);
      clangArgs.push_back(
            "-I" + installPath.childPath(bitsInc).absolutePath());
   }

   // build version predicate and path list if we can
   if (!versionMin.empty())
   {
      boost::format fmt("getRversion() >= \"%1%\" && getRversion() <= \"%2%\"");
      versionPredicate_ = boost::str(fmt % versionMin % versionMax);

      BOOST_FOREACH(const std::string& relativePath, relativePathEntries)
      {
         pathEntries_.push_back(installPath_.childPath(relativePath));
      }

      clangArgs_ = clangArgs;
      environmentVars_ = environmentVars;
   }
}

std::string RToolsInfo::url(const std::string& repos) const
{
   // strip period from name
   std::string ver = boost::algorithm::replace_all_copy(name(), ".", "");
   std::string url = core::http::URL::complete(
                        repos, "bin/windows/Rtools/Rtools" + ver + ".exe");
   return url;
}

std::ostream& operator<<(std::ostream& os, const RToolsInfo& info)
{
   os << "Rtools " << info.name() << std::endl;
   os << info.versionPredicate() << std::endl;
   BOOST_FOREACH(const FilePath& pathEntry, info.pathEntries())
   {
     os << pathEntry << std::endl;
   }
   BOOST_FOREACH(const core::system::Option& var, info.environmentVars())
   {
      os << var.first << "=" << var.second << std::endl;
   }

   return os;
}

Error scanRegistryForRTools(HKEY key,
                            bool usingMingwGcc49,
                            std::vector<RToolsInfo>* pRTools)
{
   core::system::RegistryKey regKey;
   Error error = regKey.open(key,
                             "Software\\R-core\\Rtools",
                             KEY_READ | KEY_WOW64_32KEY);
   if (error)
   {
      if (error.code() != boost::system::errc::no_such_file_or_directory)
         return error;
      else
         return Success();
   }

   std::vector<std::string> keys = regKey.keyNames();
   for (size_t i = 0; i < keys.size(); i++)
   {
      std::string name = keys.at(i);
      core::system::RegistryKey verKey;
      error = verKey.open(regKey.handle(),
                          name,
                          KEY_READ | KEY_WOW64_32KEY);
      if (error)
      {
         LOG_ERROR(error);
         continue;
      }

      std::string installPath = verKey.getStringValue("InstallPath", "");
      if (!installPath.empty())
      {
         std::string utf8InstallPath = string_utils::systemToUtf8(installPath);
         RToolsInfo toolsInfo(name, FilePath(utf8InstallPath), usingMingwGcc49);
         if (toolsInfo.isStillInstalled())
         {
            if (toolsInfo.isRecognized())
               pRTools->push_back(toolsInfo);
            else
               LOG_WARNING_MESSAGE("Unknown Rtools version: " + name);
         }
      }
   }

   return Success();
}

Error scanRegistryForRTools(bool usingMingwGcc49,
                            std::vector<RToolsInfo>* pRTools)
{
   // try HKLM first (backwards compatible with previous code)
   Error error = scanRegistryForRTools(HKEY_LOCAL_MACHINE,
                                       usingMingwGcc49,
                                       pRTools);
   if (error)
      return error;

   // try HKCU as a fallback
   if (pRTools->empty())
      return scanRegistryForRTools(HKEY_CURRENT_USER,
                                   usingMingwGcc49,
                                   pRTools);
   else
      return Success();
}

} // namespace r_util
} // namespace core
} // namespace rstudio

<|endoftext|>


<commit_before><commit_msg>fastuidraw/painter/stroked_caps_joins: bug fix<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sbxconv.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-10-12 14:32:25 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SBXCONV_HXX
#define _SBXCONV_HXX

#include "sbxdec.hxx"

// SBXSCAN.CXX
extern void ImpCvtNum( double nNum, short nPrec, String& rRes, BOOL bCoreString=FALSE );
extern SbxError ImpScan
    ( const String& rSrc, double& nVal, SbxDataType& rType, USHORT* pLen,
      BOOL bAllowIntntl=FALSE, BOOL bOnlyIntntl=FALSE );

// mit erweiterter Auswertung (International, "TRUE"/"FALSE")
extern BOOL ImpConvStringExt( String& rSrc, SbxDataType eTargetType );

// SBXINT.CXX

double      ImpRound( double );
INT16       ImpGetInteger( const SbxValues* );
void        ImpPutInteger( SbxValues*, INT16 );
sal_Int64   ImpGetInt64( const SbxValues* );
void        ImpPutInt64( SbxValues*, sal_Int64 );
sal_uInt64  ImpGetUInt64( const SbxValues* );
void        ImpPutUInt64( SbxValues*, sal_uInt64 );

sal_Int64   ImpDoubleToSalInt64( double d );
sal_uInt64  ImpDoubleToSalUInt64( double d );
double      ImpSalUInt64ToDouble( sal_uInt64 n );

// SBXLNG.CXX

INT32   ImpGetLong( const SbxValues* );
void    ImpPutLong( SbxValues*, INT32 );

// SBXSNG.CXX

float   ImpGetSingle( const SbxValues* );
void    ImpPutSingle( SbxValues*, float );

// SBXDBL.CXX

double  ImpGetDouble( const SbxValues* );
void    ImpPutDouble( SbxValues*, double, BOOL bCoreString=FALSE );

#if FALSE
// SBX64.CXX

SbxINT64  ImpGetINT64( const SbxValues* );
void      ImpPutINT64( SbxValues*, const SbxINT64& );
SbxUINT64 ImpGetUINT64( const SbxValues* );
void      ImpPutUINT64( SbxValues*, const SbxUINT64& );
#endif

// SBXCURR.CXX

SbxUINT64 ImpDoubleToUINT64( double );
double    ImpUINT64ToDouble( const SbxUINT64& );
SbxINT64  ImpDoubleToINT64( double );
double    ImpINT64ToDouble( const SbxINT64& );

#if TRUE
INT32     ImpGetCurrLong( const SbxValues* );
void      ImpPutCurrLong( SbxValues*, INT32 );
INT32     ImpDoubleToCurrLong( double );
double    ImpCurrLongToDouble( INT32 );
#endif

SbxINT64  ImpGetCurrency( const SbxValues* );
void      ImpPutCurrency( SbxValues*, const SbxINT64& );
inline
SbxINT64  ImpDoubleToCurrency( double d )
          { return ImpDoubleToINT64( d * CURRENCY_FACTOR ); }
inline
double    ImpCurrencyToDouble( const SbxINT64 &r )
          { return ImpINT64ToDouble( r ) / CURRENCY_FACTOR; }

// SBXDEC.CXX

SbxDecimal* ImpCreateDecimal( SbxValues* p );
SbxDecimal* ImpGetDecimal( const SbxValues* p );
void ImpPutDecimal( SbxValues* p, SbxDecimal* pDec );

// SBXDATE.CXX

double  ImpGetDate( const SbxValues* );
void    ImpPutDate( SbxValues*, double );

// SBXSTR.CXX

String  ImpGetString( const SbxValues* );
String  ImpGetCoreString( const SbxValues* );
void    ImpPutString( SbxValues*, const String* );

// SBXCHAR.CXX

sal_Unicode ImpGetChar( const SbxValues* );
void    ImpPutChar( SbxValues*, sal_Unicode );

// SBXBYTE.CXX
BYTE    ImpGetByte( const SbxValues* );
void    ImpPutByte( SbxValues*, BYTE );

// SBXUINT.CXX

UINT16  ImpGetUShort( const SbxValues* );
void    ImpPutUShort( SbxValues*, UINT16 );

// SBXULNG.CXX

UINT32  ImpGetULong( const SbxValues* );
void    ImpPutULong( SbxValues*, UINT32 );

// SBXBOOL.CXX

enum SbxBOOL ImpGetBool( const SbxValues* );
void    ImpPutBool( SbxValues*, INT16 );

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.4.154); FILE MERGED 2008/03/28 16:07:44 rt 1.4.154.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: sbxconv.hxx,v $
 * $Revision: 1.5 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SBXCONV_HXX
#define _SBXCONV_HXX

#include "sbxdec.hxx"

// SBXSCAN.CXX
extern void ImpCvtNum( double nNum, short nPrec, String& rRes, BOOL bCoreString=FALSE );
extern SbxError ImpScan
    ( const String& rSrc, double& nVal, SbxDataType& rType, USHORT* pLen,
      BOOL bAllowIntntl=FALSE, BOOL bOnlyIntntl=FALSE );

// mit erweiterter Auswertung (International, "TRUE"/"FALSE")
extern BOOL ImpConvStringExt( String& rSrc, SbxDataType eTargetType );

// SBXINT.CXX

double      ImpRound( double );
INT16       ImpGetInteger( const SbxValues* );
void        ImpPutInteger( SbxValues*, INT16 );
sal_Int64   ImpGetInt64( const SbxValues* );
void        ImpPutInt64( SbxValues*, sal_Int64 );
sal_uInt64  ImpGetUInt64( const SbxValues* );
void        ImpPutUInt64( SbxValues*, sal_uInt64 );

sal_Int64   ImpDoubleToSalInt64( double d );
sal_uInt64  ImpDoubleToSalUInt64( double d );
double      ImpSalUInt64ToDouble( sal_uInt64 n );

// SBXLNG.CXX

INT32   ImpGetLong( const SbxValues* );
void    ImpPutLong( SbxValues*, INT32 );

// SBXSNG.CXX

float   ImpGetSingle( const SbxValues* );
void    ImpPutSingle( SbxValues*, float );

// SBXDBL.CXX

double  ImpGetDouble( const SbxValues* );
void    ImpPutDouble( SbxValues*, double, BOOL bCoreString=FALSE );

#if FALSE
// SBX64.CXX

SbxINT64  ImpGetINT64( const SbxValues* );
void      ImpPutINT64( SbxValues*, const SbxINT64& );
SbxUINT64 ImpGetUINT64( const SbxValues* );
void      ImpPutUINT64( SbxValues*, const SbxUINT64& );
#endif

// SBXCURR.CXX

SbxUINT64 ImpDoubleToUINT64( double );
double    ImpUINT64ToDouble( const SbxUINT64& );
SbxINT64  ImpDoubleToINT64( double );
double    ImpINT64ToDouble( const SbxINT64& );

#if TRUE
INT32     ImpGetCurrLong( const SbxValues* );
void      ImpPutCurrLong( SbxValues*, INT32 );
INT32     ImpDoubleToCurrLong( double );
double    ImpCurrLongToDouble( INT32 );
#endif

SbxINT64  ImpGetCurrency( const SbxValues* );
void      ImpPutCurrency( SbxValues*, const SbxINT64& );
inline
SbxINT64  ImpDoubleToCurrency( double d )
          { return ImpDoubleToINT64( d * CURRENCY_FACTOR ); }
inline
double    ImpCurrencyToDouble( const SbxINT64 &r )
          { return ImpINT64ToDouble( r ) / CURRENCY_FACTOR; }

// SBXDEC.CXX

SbxDecimal* ImpCreateDecimal( SbxValues* p );
SbxDecimal* ImpGetDecimal( const SbxValues* p );
void ImpPutDecimal( SbxValues* p, SbxDecimal* pDec );

// SBXDATE.CXX

double  ImpGetDate( const SbxValues* );
void    ImpPutDate( SbxValues*, double );

// SBXSTR.CXX

String  ImpGetString( const SbxValues* );
String  ImpGetCoreString( const SbxValues* );
void    ImpPutString( SbxValues*, const String* );

// SBXCHAR.CXX

sal_Unicode ImpGetChar( const SbxValues* );
void    ImpPutChar( SbxValues*, sal_Unicode );

// SBXBYTE.CXX
BYTE    ImpGetByte( const SbxValues* );
void    ImpPutByte( SbxValues*, BYTE );

// SBXUINT.CXX

UINT16  ImpGetUShort( const SbxValues* );
void    ImpPutUShort( SbxValues*, UINT16 );

// SBXULNG.CXX

UINT32  ImpGetULong( const SbxValues* );
void    ImpPutULong( SbxValues*, UINT32 );

// SBXBOOL.CXX

enum SbxBOOL ImpGetBool( const SbxValues* );
void    ImpPutBool( SbxValues*, INT16 );

#endif
<|endoftext|>


<commit_before>#include "extlineedit.h"
#include <QPushButton>
#include <QIcon>
#include <QPropertyAnimation>
#include <QSignalTransition>

CExtLineEdit::CExtLineEdit(QWidget* parent)
    : QLineEdit(parent)
    , m_animated(true)
    , m_animationDurationMS(500)
    , m_clearButton(new QPushButton(this))
    , m_textStateMachine(new QStateMachine(this))
    , m_textNotEmptyState(new QState(m_textStateMachine))
    , m_textEmptyState(new QState(m_textStateMachine))
    , m_animHideClearButton(new QPropertyAnimation(m_clearButton, "pos"))
    , m_animShowClearButton(new QPropertyAnimation(m_clearButton, "pos"))
{
    QPixmap buttonImage(":/Icon/remove_16.png");
    QIcon icon;
    icon.addPixmap(buttonImage, QIcon::Normal, QIcon::Off);

    m_clearButton->setFlat(true);
    m_clearButton->setIcon(icon);
    m_clearButton->setFocusPolicy(Qt::NoFocus);
    m_clearButton->setCursor(Qt::ArrowCursor);

    m_animHideClearButton->setDuration(m_animationDurationMS);
    m_animHideClearButton->setEasingCurve(QEasingCurve::OutExpo);
    m_animShowClearButton->setDuration(m_animationDurationMS);
    m_animShowClearButton->setEasingCurve(QEasingCurve::OutBounce);

    // Note on the StateMachine:
    // Propertyassignment is added in CExtLineEdit::layoutClearButton()
    // because we don't no the size of the button here.
    // Starting of the the StateMachine is also done in CExtLineEdit::layoutClearButton().
    QSignalTransition *transition;
    transition = m_textNotEmptyState->addTransition(this, SIGNAL(textEmptyToggled()), m_textEmptyState);
    transition->addAnimation(m_animHideClearButton);

    transition = m_textEmptyState->addTransition(this, SIGNAL(textEmptyToggled()), m_textNotEmptyState);
    transition->addAnimation(m_animShowClearButton);

    connect(m_clearButton, SIGNAL(clicked()), this, SLOT(clear()));
    connect(this, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString)));
}

bool CExtLineEdit::isAnimated()
{
    return m_animated;
}

void CExtLineEdit::setAnimated(bool animate)
{
    m_animated = animate;
    if ( m_animated ) {
        m_animHideClearButton->setDuration(m_animationDurationMS);
        m_animShowClearButton->setDuration(m_animationDurationMS);
    } else {
        m_animHideClearButton->setDuration(0);
        m_animShowClearButton->setDuration(0);
    }
}

int CExtLineEdit::animationDuration() {
    return m_animationDurationMS;
}

void CExtLineEdit::setAnimationDuration(int durationInMS) {
    m_animationDurationMS = durationInMS;
    if ( isAnimated() ) {
        m_animHideClearButton->setDuration(m_animationDurationMS);
        m_animShowClearButton->setDuration(m_animationDurationMS);
    }
}

void CExtLineEdit::ensureStateMachineIsRunning()
{
    if ( !m_textStateMachine->isRunning() ) {
        if ( text().isEmpty() ) {
            m_textStateMachine->setInitialState(m_textEmptyState);
        } else {
            m_textStateMachine->setInitialState(m_textNotEmptyState);
        }
        m_textStateMachine->start();
    }
}

void CExtLineEdit::resizeEvent(QResizeEvent* event)
{
      QLineEdit::resizeEvent(event);
      layoutClearButton();
}

void CExtLineEdit::layoutClearButton()
{
    ensurePolished();

    // If the statemachine is not running we start it here with the correct state.
    // This has to be done here because otherwise it is possible that someone calls
    // setText on the LineEdit and then the statemachine would be in the wrong state.
    ensureStateMachineIsRunning();

    QSize buttonSize = m_clearButton->minimumSizeHint();
    QPoint buttonVisiblePos(rect().right() - buttonSize.width(),(rect().height() - buttonSize.height() ) / 2);
    QPoint buttonInvisiblePos(rect().right(), (rect().height() - buttonSize.height() ) / 2);

    m_textNotEmptyState->assignProperty(m_clearButton, "pos", buttonVisiblePos);
    m_textEmptyState->assignProperty(m_clearButton, "pos", buttonInvisiblePos);

    if (m_textStateMachine->configuration().contains(m_textNotEmptyState)) {
        m_clearButton->setProperty("pos", buttonVisiblePos);
    } else {
        m_clearButton->setProperty("pos", buttonInvisiblePos);
    }
    //maybe the size has changed so we better set the text margins again
    int left, top, bottom;
    this->getTextMargins (&left, &top, 0, &bottom );
    this->setTextMargins(left, top, 2 + m_clearButton->minimumSizeHint().width() + 2, bottom);
}

void CExtLineEdit::onTextChanged(const QString &text)
{
    if (    ( text.isEmpty() && m_textStateMachine->configuration().contains(m_textNotEmptyState))
         || (!text.isEmpty() && m_textStateMachine->configuration().contains(m_textEmptyState))
       ) {
        emit textEmptyToggled();
    }
}
<commit_msg>Fixed typo<commit_after>#include "extlineedit.h"
#include <QPushButton>
#include <QIcon>
#include <QPropertyAnimation>
#include <QSignalTransition>

CExtLineEdit::CExtLineEdit(QWidget* parent)
    : QLineEdit(parent)
    , m_animated(true)
    , m_animationDurationMS(500)
    , m_clearButton(new QPushButton(this))
    , m_textStateMachine(new QStateMachine(this))
    , m_textNotEmptyState(new QState(m_textStateMachine))
    , m_textEmptyState(new QState(m_textStateMachine))
    , m_animHideClearButton(new QPropertyAnimation(m_clearButton, "pos"))
    , m_animShowClearButton(new QPropertyAnimation(m_clearButton, "pos"))
{
    QPixmap buttonImage(":/Icon/remove_16.png");
    QIcon icon;
    icon.addPixmap(buttonImage, QIcon::Normal, QIcon::Off);

    m_clearButton->setFlat(true);
    m_clearButton->setIcon(icon);
    m_clearButton->setFocusPolicy(Qt::NoFocus);
    m_clearButton->setCursor(Qt::ArrowCursor);

    m_animHideClearButton->setDuration(m_animationDurationMS);
    m_animHideClearButton->setEasingCurve(QEasingCurve::OutExpo);
    m_animShowClearButton->setDuration(m_animationDurationMS);
    m_animShowClearButton->setEasingCurve(QEasingCurve::OutBounce);

    // Note on the StateMachine:
    // Propertyassignment is added in CExtLineEdit::layoutClearButton()
    // because we don't know the size of the button here.
    // Starting of the the StateMachine is also done in CExtLineEdit::layoutClearButton().
    QSignalTransition *transition;
    transition = m_textNotEmptyState->addTransition(this, SIGNAL(textEmptyToggled()), m_textEmptyState);
    transition->addAnimation(m_animHideClearButton);

    transition = m_textEmptyState->addTransition(this, SIGNAL(textEmptyToggled()), m_textNotEmptyState);
    transition->addAnimation(m_animShowClearButton);

    connect(m_clearButton, SIGNAL(clicked()), this, SLOT(clear()));
    connect(this, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString)));
}

bool CExtLineEdit::isAnimated()
{
    return m_animated;
}

void CExtLineEdit::setAnimated(bool animate)
{
    m_animated = animate;
    if ( m_animated ) {
        m_animHideClearButton->setDuration(m_animationDurationMS);
        m_animShowClearButton->setDuration(m_animationDurationMS);
    } else {
        m_animHideClearButton->setDuration(0);
        m_animShowClearButton->setDuration(0);
    }
}

int CExtLineEdit::animationDuration() {
    return m_animationDurationMS;
}

void CExtLineEdit::setAnimationDuration(int durationInMS) {
    m_animationDurationMS = durationInMS;
    if ( isAnimated() ) {
        m_animHideClearButton->setDuration(m_animationDurationMS);
        m_animShowClearButton->setDuration(m_animationDurationMS);
    }
}

void CExtLineEdit::ensureStateMachineIsRunning()
{
    if ( !m_textStateMachine->isRunning() ) {
        if ( text().isEmpty() ) {
            m_textStateMachine->setInitialState(m_textEmptyState);
        } else {
            m_textStateMachine->setInitialState(m_textNotEmptyState);
        }
        m_textStateMachine->start();
    }
}

void CExtLineEdit::resizeEvent(QResizeEvent* event)
{
      QLineEdit::resizeEvent(event);
      layoutClearButton();
}

void CExtLineEdit::layoutClearButton()
{
    ensurePolished();

    // If the statemachine is not running we start it here with the correct state.
    // This has to be done here because otherwise it is possible that someone calls
    // setText on the LineEdit and then the statemachine would be in the wrong state.
    ensureStateMachineIsRunning();

    QSize buttonSize = m_clearButton->minimumSizeHint();
    QPoint buttonVisiblePos(rect().right() - buttonSize.width(),(rect().height() - buttonSize.height() ) / 2);
    QPoint buttonInvisiblePos(rect().right(), (rect().height() - buttonSize.height() ) / 2);

    m_textNotEmptyState->assignProperty(m_clearButton, "pos", buttonVisiblePos);
    m_textEmptyState->assignProperty(m_clearButton, "pos", buttonInvisiblePos);

    if (m_textStateMachine->configuration().contains(m_textNotEmptyState)) {
        m_clearButton->setProperty("pos", buttonVisiblePos);
    } else {
        m_clearButton->setProperty("pos", buttonInvisiblePos);
    }
    //maybe the size has changed so we better set the text margins again
    int left, top, bottom;
    this->getTextMargins (&left, &top, 0, &bottom );
    this->setTextMargins(left, top, 2 + m_clearButton->minimumSizeHint().width() + 2, bottom);
}

void CExtLineEdit::onTextChanged(const QString &text)
{
    if (    ( text.isEmpty() && m_textStateMachine->configuration().contains(m_textNotEmptyState))
         || (!text.isEmpty() && m_textStateMachine->configuration().contains(m_textEmptyState))
       ) {
        emit textEmptyToggled();
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.

#include "browser/url_request_context_getter.h"

#include <algorithm>

#include "browser/network_delegate.h"

#include "base/command_line.h"
#include "base/strings/string_util.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/worker_pool.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_store_factory.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "net/base/host_mapping_rules.h"
#include "net/cert/cert_verifier.h"
#include "net/cookies/cookie_monster.h"
#include "net/dns/mapped_host_resolver.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_cache.h"
#include "net/http/http_server_properties_impl.h"
#include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
#include "net/proxy/proxy_config_service.h"
#include "net/proxy/proxy_script_fetcher_impl.h"
#include "net/proxy/proxy_service.h"
#include "net/proxy/proxy_service_v8.h"
#include "net/ssl/default_server_bound_cert_store.h"
#include "net/ssl/server_bound_cert_service.h"
#include "net/ssl/ssl_config_service_defaults.h"
#include "net/url_request/data_protocol_handler.h"
#include "net/url_request/file_protocol_handler.h"
#include "net/url_request/protocol_intercept_job_factory.h"
#include "net/url_request/static_http_user_agent_settings.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_storage.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "webkit/browser/quota/special_storage_policy.h"

using content::BrowserThread;

namespace brightray {

namespace {

// Comma-separated list of rules that control how hostnames are mapped.
//
// For example:
//    "MAP * 127.0.0.1" --> Forces all hostnames to be mapped to 127.0.0.1
//    "MAP *.google.com proxy" --> Forces all google.com subdomains to be
//                                 resolved to "proxy".
//    "MAP test.com [::1]:77 --> Forces "test.com" to resolve to IPv6 loopback.
//                               Will also force the port of the resulting
//                               socket address to be 77.
//    "MAP * baz, EXCLUDE www.google.com" --> Remaps everything to "baz",
//                                            except for "www.google.com".
//
// These mappings apply to the endpoint host in a net::URLRequest (the TCP
// connect and host resolver in a direct connection, and the CONNECT in an http
// proxy connection, and the endpoint host in a SOCKS proxy connection).
const char kHostRules[] = "host-rules";

// Don't use a proxy server, always make direct connections. Overrides any
// other proxy server flags that are passed.
const char kNoProxyServer[] = "no-proxy-server";

}  // namespace

URLRequestContextGetter::URLRequestContextGetter(
    const base::FilePath& base_path,
    base::MessageLoop* io_loop,
    base::MessageLoop* file_loop,
    base::Callback<scoped_ptr<NetworkDelegate>(void)> network_delegate_factory,
    URLRequestJobFactoryFactory job_factory_factory,
    content::ProtocolHandlerMap* protocol_handlers,
    content::ProtocolHandlerScopedVector protocol_interceptors)
    : base_path_(base_path),
      io_loop_(io_loop),
      file_loop_(file_loop),
      network_delegate_factory_(network_delegate_factory),
      job_factory_factory_(job_factory_factory),
      protocol_interceptors_(protocol_interceptors.Pass()) {
  // Must first be created on the UI thread.
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  std::swap(protocol_handlers_, *protocol_handlers);

  proxy_config_service_.reset(net::ProxyService::CreateSystemProxyConfigService(
      io_loop_->message_loop_proxy(), file_loop_));
}

URLRequestContextGetter::~URLRequestContextGetter() {
}

net::HostResolver* URLRequestContextGetter::host_resolver() {
  return url_request_context_->host_resolver();
}

net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  const CommandLine& command_line = *CommandLine::ForCurrentProcess();

  if (!url_request_context_.get()) {
    url_request_context_.reset(new net::URLRequestContext());
    network_delegate_ = network_delegate_factory_.Run().Pass();
    url_request_context_->set_network_delegate(network_delegate_.get());
    storage_.reset(
        new net::URLRequestContextStorage(url_request_context_.get()));
    auto cookie_config = content::CookieStoreConfig(
        base_path_.Append(FILE_PATH_LITERAL("Cookies")),
        content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES,
        nullptr,
        nullptr);
    storage_->set_cookie_store(content::CreateCookieStore(cookie_config));
    storage_->set_server_bound_cert_service(new net::ServerBoundCertService(
        new net::DefaultServerBoundCertStore(NULL),
        base::WorkerPool::GetTaskRunner(true)));
    storage_->set_http_user_agent_settings(
        new net::StaticHttpUserAgentSettings(
            "en-us,en", base::EmptyString()));

    scoped_ptr<net::HostResolver> host_resolver(
        net::HostResolver::CreateDefaultResolver(NULL));

    // --host-resolver-rules
    if (command_line.HasSwitch(switches::kHostResolverRules)) {
      scoped_ptr<net::MappedHostResolver> remapped_resolver(
          new net::MappedHostResolver(host_resolver.Pass()));
      remapped_resolver->SetRulesFromString(
          command_line.GetSwitchValueASCII(switches::kHostResolverRules));
      host_resolver = remapped_resolver.PassAs<net::HostResolver>();
    }

    net::DhcpProxyScriptFetcherFactory dhcp_factory;
    if (command_line.HasSwitch(kNoProxyServer))
      storage_->set_proxy_service(net::ProxyService::CreateDirect());
    else
      storage_->set_proxy_service(
          net::CreateProxyServiceUsingV8ProxyResolver(
              proxy_config_service_.release(),
              new net::ProxyScriptFetcherImpl(url_request_context_.get()),
              dhcp_factory.Create(url_request_context_.get()),
              host_resolver.get(),
              NULL,
              url_request_context_->network_delegate()));

    storage_->set_cert_verifier(net::CertVerifier::CreateDefault());
    storage_->set_transport_security_state(new net::TransportSecurityState);
    storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults);
    storage_->set_http_auth_handler_factory(
        net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
    scoped_ptr<net::HttpServerProperties> server_properties(
        new net::HttpServerPropertiesImpl);
    storage_->set_http_server_properties(server_properties.Pass());

    base::FilePath cache_path = base_path_.Append(FILE_PATH_LITERAL("Cache"));
    net::HttpCache::DefaultBackend* main_backend =
        new net::HttpCache::DefaultBackend(
            net::DISK_CACHE,
            net::CACHE_BACKEND_DEFAULT,
            cache_path,
            0,
            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE));

    net::HttpNetworkSession::Params network_session_params;
    network_session_params.cert_verifier =
        url_request_context_->cert_verifier();
    network_session_params.transport_security_state =
        url_request_context_->transport_security_state();
    network_session_params.server_bound_cert_service =
        url_request_context_->server_bound_cert_service();
    network_session_params.proxy_service =
        url_request_context_->proxy_service();
    network_session_params.ssl_config_service =
        url_request_context_->ssl_config_service();
    network_session_params.http_auth_handler_factory =
        url_request_context_->http_auth_handler_factory();
    network_session_params.network_delegate =
        url_request_context_->network_delegate();
    network_session_params.http_server_properties =
        url_request_context_->http_server_properties();
    network_session_params.ignore_certificate_errors = false;

    // --host-rules
    if (command_line.HasSwitch(kHostRules)) {
      host_mapping_rules_.reset(new net::HostMappingRules);
      host_mapping_rules_->SetRulesFromString(command_line.GetSwitchValueASCII(kHostRules));
      network_session_params.host_mapping_rules = host_mapping_rules_.get();
    }

    // Give |storage_| ownership at the end in case it's |mapped_host_resolver|.
    storage_->set_host_resolver(host_resolver.Pass());
    network_session_params.host_resolver =
        url_request_context_->host_resolver();

    net::HttpCache* main_cache = new net::HttpCache(
        network_session_params, main_backend);
    storage_->set_http_transaction_factory(main_cache);

    // Give user a chance to create their own job factory.
    scoped_ptr<net::URLRequestJobFactory> user_job_factory(
        job_factory_factory_.Run(&protocol_handlers_, &protocol_interceptors_));
    if (user_job_factory) {
      storage_->set_job_factory(user_job_factory.release());
      return url_request_context_.get();
    }

    scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
        new net::URLRequestJobFactoryImpl());
    for (auto it = protocol_handlers_.begin(),
        end = protocol_handlers_.end(); it != end; ++it) {
      bool set_protocol = job_factory->SetProtocolHandler(
          it->first, it->second.release());
      DCHECK(set_protocol);
      (void)set_protocol;  // silence unused-variable warning in Release builds on Windows
    }
    protocol_handlers_.clear();
    job_factory->SetProtocolHandler(
        content::kDataScheme, new net::DataProtocolHandler);
    job_factory->SetProtocolHandler(
        content::kFileScheme,
        new net::FileProtocolHandler(
            BrowserThread::GetBlockingPool()->
                GetTaskRunnerWithShutdownBehavior(
                    base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));

    // Set up interceptors in the reverse order.
    scoped_ptr<net::URLRequestJobFactory> top_job_factory =
        job_factory.PassAs<net::URLRequestJobFactory>();
    for (content::ProtocolHandlerScopedVector::reverse_iterator i =
             protocol_interceptors_.rbegin();
         i != protocol_interceptors_.rend();
         ++i) {
      top_job_factory.reset(new net::ProtocolInterceptJobFactory(
          top_job_factory.Pass(), make_scoped_ptr(*i)));
    }
    protocol_interceptors_.weak_clear();

    storage_->set_job_factory(top_job_factory.release());
  }

  return url_request_context_.get();
}

scoped_refptr<base::SingleThreadTaskRunner>
    URLRequestContextGetter::GetNetworkTaskRunner() const {
  return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
}

}  // namespace brightray
<commit_msg>Add --proxy-server switch.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.

#include "browser/url_request_context_getter.h"

#include <algorithm>

#include "browser/network_delegate.h"

#include "base/command_line.h"
#include "base/strings/string_util.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/worker_pool.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_store_factory.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "net/base/host_mapping_rules.h"
#include "net/cert/cert_verifier.h"
#include "net/cookies/cookie_monster.h"
#include "net/dns/mapped_host_resolver.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_cache.h"
#include "net/http/http_server_properties_impl.h"
#include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
#include "net/proxy/proxy_config_service.h"
#include "net/proxy/proxy_script_fetcher_impl.h"
#include "net/proxy/proxy_service.h"
#include "net/proxy/proxy_service_v8.h"
#include "net/ssl/default_server_bound_cert_store.h"
#include "net/ssl/server_bound_cert_service.h"
#include "net/ssl/ssl_config_service_defaults.h"
#include "net/url_request/data_protocol_handler.h"
#include "net/url_request/file_protocol_handler.h"
#include "net/url_request/protocol_intercept_job_factory.h"
#include "net/url_request/static_http_user_agent_settings.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_storage.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "webkit/browser/quota/special_storage_policy.h"

using content::BrowserThread;

namespace brightray {

namespace {

// Comma-separated list of rules that control how hostnames are mapped.
//
// For example:
//    "MAP * 127.0.0.1" --> Forces all hostnames to be mapped to 127.0.0.1
//    "MAP *.google.com proxy" --> Forces all google.com subdomains to be
//                                 resolved to "proxy".
//    "MAP test.com [::1]:77 --> Forces "test.com" to resolve to IPv6 loopback.
//                               Will also force the port of the resulting
//                               socket address to be 77.
//    "MAP * baz, EXCLUDE www.google.com" --> Remaps everything to "baz",
//                                            except for "www.google.com".
//
// These mappings apply to the endpoint host in a net::URLRequest (the TCP
// connect and host resolver in a direct connection, and the CONNECT in an http
// proxy connection, and the endpoint host in a SOCKS proxy connection).
const char kHostRules[] = "host-rules";

// Don't use a proxy server, always make direct connections. Overrides any
// other proxy server flags that are passed.
const char kNoProxyServer[] = "no-proxy-server";

// Uses a specified proxy server, overrides system settings. This switch only
// affects HTTP and HTTPS requests.
const char kProxyServer[] = "proxy-server";

}  // namespace

URLRequestContextGetter::URLRequestContextGetter(
    const base::FilePath& base_path,
    base::MessageLoop* io_loop,
    base::MessageLoop* file_loop,
    base::Callback<scoped_ptr<NetworkDelegate>(void)> network_delegate_factory,
    URLRequestJobFactoryFactory job_factory_factory,
    content::ProtocolHandlerMap* protocol_handlers,
    content::ProtocolHandlerScopedVector protocol_interceptors)
    : base_path_(base_path),
      io_loop_(io_loop),
      file_loop_(file_loop),
      network_delegate_factory_(network_delegate_factory),
      job_factory_factory_(job_factory_factory),
      protocol_interceptors_(protocol_interceptors.Pass()) {
  // Must first be created on the UI thread.
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  std::swap(protocol_handlers_, *protocol_handlers);

  proxy_config_service_.reset(net::ProxyService::CreateSystemProxyConfigService(
      io_loop_->message_loop_proxy(), file_loop_));
}

URLRequestContextGetter::~URLRequestContextGetter() {
}

net::HostResolver* URLRequestContextGetter::host_resolver() {
  return url_request_context_->host_resolver();
}

net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  const CommandLine& command_line = *CommandLine::ForCurrentProcess();

  if (!url_request_context_.get()) {
    url_request_context_.reset(new net::URLRequestContext());
    network_delegate_ = network_delegate_factory_.Run().Pass();
    url_request_context_->set_network_delegate(network_delegate_.get());
    storage_.reset(
        new net::URLRequestContextStorage(url_request_context_.get()));
    auto cookie_config = content::CookieStoreConfig(
        base_path_.Append(FILE_PATH_LITERAL("Cookies")),
        content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES,
        nullptr,
        nullptr);
    storage_->set_cookie_store(content::CreateCookieStore(cookie_config));
    storage_->set_server_bound_cert_service(new net::ServerBoundCertService(
        new net::DefaultServerBoundCertStore(NULL),
        base::WorkerPool::GetTaskRunner(true)));
    storage_->set_http_user_agent_settings(
        new net::StaticHttpUserAgentSettings(
            "en-us,en", base::EmptyString()));

    scoped_ptr<net::HostResolver> host_resolver(
        net::HostResolver::CreateDefaultResolver(NULL));

    // --host-resolver-rules
    if (command_line.HasSwitch(switches::kHostResolverRules)) {
      scoped_ptr<net::MappedHostResolver> remapped_resolver(
          new net::MappedHostResolver(host_resolver.Pass()));
      remapped_resolver->SetRulesFromString(
          command_line.GetSwitchValueASCII(switches::kHostResolverRules));
      host_resolver = remapped_resolver.PassAs<net::HostResolver>();
    }

    net::DhcpProxyScriptFetcherFactory dhcp_factory;
    if (command_line.HasSwitch(kNoProxyServer))
      storage_->set_proxy_service(net::ProxyService::CreateDirect());
    else if (command_line.HasSwitch(kProxyServer))
      storage_->set_proxy_service(net::ProxyService::CreateFixed(
          command_line.GetSwitchValueASCII(kProxyServer)));
    else
      storage_->set_proxy_service(
          net::CreateProxyServiceUsingV8ProxyResolver(
              proxy_config_service_.release(),
              new net::ProxyScriptFetcherImpl(url_request_context_.get()),
              dhcp_factory.Create(url_request_context_.get()),
              host_resolver.get(),
              NULL,
              url_request_context_->network_delegate()));

    storage_->set_cert_verifier(net::CertVerifier::CreateDefault());
    storage_->set_transport_security_state(new net::TransportSecurityState);
    storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults);
    storage_->set_http_auth_handler_factory(
        net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
    scoped_ptr<net::HttpServerProperties> server_properties(
        new net::HttpServerPropertiesImpl);
    storage_->set_http_server_properties(server_properties.Pass());

    base::FilePath cache_path = base_path_.Append(FILE_PATH_LITERAL("Cache"));
    net::HttpCache::DefaultBackend* main_backend =
        new net::HttpCache::DefaultBackend(
            net::DISK_CACHE,
            net::CACHE_BACKEND_DEFAULT,
            cache_path,
            0,
            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE));

    net::HttpNetworkSession::Params network_session_params;
    network_session_params.cert_verifier =
        url_request_context_->cert_verifier();
    network_session_params.transport_security_state =
        url_request_context_->transport_security_state();
    network_session_params.server_bound_cert_service =
        url_request_context_->server_bound_cert_service();
    network_session_params.proxy_service =
        url_request_context_->proxy_service();
    network_session_params.ssl_config_service =
        url_request_context_->ssl_config_service();
    network_session_params.http_auth_handler_factory =
        url_request_context_->http_auth_handler_factory();
    network_session_params.network_delegate =
        url_request_context_->network_delegate();
    network_session_params.http_server_properties =
        url_request_context_->http_server_properties();
    network_session_params.ignore_certificate_errors = false;

    // --host-rules
    if (command_line.HasSwitch(kHostRules)) {
      host_mapping_rules_.reset(new net::HostMappingRules);
      host_mapping_rules_->SetRulesFromString(command_line.GetSwitchValueASCII(kHostRules));
      network_session_params.host_mapping_rules = host_mapping_rules_.get();
    }

    // Give |storage_| ownership at the end in case it's |mapped_host_resolver|.
    storage_->set_host_resolver(host_resolver.Pass());
    network_session_params.host_resolver =
        url_request_context_->host_resolver();

    net::HttpCache* main_cache = new net::HttpCache(
        network_session_params, main_backend);
    storage_->set_http_transaction_factory(main_cache);

    // Give user a chance to create their own job factory.
    scoped_ptr<net::URLRequestJobFactory> user_job_factory(
        job_factory_factory_.Run(&protocol_handlers_, &protocol_interceptors_));
    if (user_job_factory) {
      storage_->set_job_factory(user_job_factory.release());
      return url_request_context_.get();
    }

    scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
        new net::URLRequestJobFactoryImpl());
    for (auto it = protocol_handlers_.begin(),
        end = protocol_handlers_.end(); it != end; ++it) {
      bool set_protocol = job_factory->SetProtocolHandler(
          it->first, it->second.release());
      DCHECK(set_protocol);
      (void)set_protocol;  // silence unused-variable warning in Release builds on Windows
    }
    protocol_handlers_.clear();
    job_factory->SetProtocolHandler(
        content::kDataScheme, new net::DataProtocolHandler);
    job_factory->SetProtocolHandler(
        content::kFileScheme,
        new net::FileProtocolHandler(
            BrowserThread::GetBlockingPool()->
                GetTaskRunnerWithShutdownBehavior(
                    base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));

    // Set up interceptors in the reverse order.
    scoped_ptr<net::URLRequestJobFactory> top_job_factory =
        job_factory.PassAs<net::URLRequestJobFactory>();
    for (content::ProtocolHandlerScopedVector::reverse_iterator i =
             protocol_interceptors_.rbegin();
         i != protocol_interceptors_.rend();
         ++i) {
      top_job_factory.reset(new net::ProtocolInterceptJobFactory(
          top_job_factory.Pass(), make_scoped_ptr(*i)));
    }
    protocol_interceptors_.weak_clear();

    storage_->set_job_factory(top_job_factory.release());
  }

  return url_request_context_.get();
}

scoped_refptr<base::SingleThreadTaskRunner>
    URLRequestContextGetter::GetNetworkTaskRunner() const {
  return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
}

}  // namespace brightray
<|endoftext|>


<commit_before><commit_msg>Solution of prob 10<commit_after>#include <stdio.h>

int count(const int *numbers_a, const int *numbers_b, const int size_a, const int size_b, const int index_a, const int index_b)
{
    /* base case */
    if(index_a >= size_a || index_b >= size_b) return 0;

    /* recursive case */
    if(numbers_a[index_a] == numbers_b[index_b]) /* match */
        return 1 + count(numbers_a, numbers_b, size_a, size_b, index_a + 1, index_b + 1);
    else /* not match */
    {
        if(numbers_a[index_a] < numbers_b[index_b]) return count(numbers_a, numbers_b, size_a, size_b, index_a + 1, index_b);
        if(numbers_a[index_a] > numbers_b[index_b]) return count(numbers_a, numbers_b, size_a, size_b, index_a, index_b + 1);
    }
}

int count_of_two_sum(const int *numbers_a, const int *numbers_b, const int number_count_a, const int number_count_b)
{
    count(numbers_a, numbers_b, number_count_a, number_count_b, 0, 0);
}

int main(void)
{
    printf("count of two sum\n");

    int size_of_array_a, size_of_array_b;

    printf("Enter size_of_array_a= "); scanf("%d", &size_of_array_a);
    int array_a[size_of_array_a];
    printf("Enter in ascending order\n");
    for(int i = 0; i < size_of_array_a; i++)
    {
        printf("Enter array_a[%d]= ", i); scanf("%d", &array_a[i]);
    }

    printf("Enter size_of_array_b= "); scanf("%d", &size_of_array_b);
    int array_b[size_of_array_b];
    printf("Enter in ascending order\n");
    for(int i = 0; i < size_of_array_b; i++)
    {
        printf("Enter array_b[%d]= ", i); scanf("%d", &array_b[i]);
    }

    printf("Result is %d\n", count_of_two_sum(array_a, array_b, size_of_array_a, size_of_array_b));
    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 midnightBITS
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "pch.h"
#include <forms/vertical_renderer.hpp>
#include <fast_cgi.hpp>
#include "pages/reader_form.hpp"
#include <utils.hpp>

namespace FastCGI { namespace app { namespace reader { namespace errors {

	class ErrorPageHandler : public ErrorHandler
	{
	protected:
		virtual const char* pageTitle(int errorCode) { return nullptr; }
		virtual const char* pageTitle(int errorCode, PageTranslation& tr) { return pageTitle(errorCode); }
		std::string getTitle(int errorCode, Request& request, PageTranslation& tr, bool hasStrings)
		{
			std::string title = hasStrings ? tr(lng::LNG_GLOBAL_SITENAME) : "reedr";
			const char* page = hasStrings ? pageTitle(errorCode, tr) : pageTitle(errorCode);
			if (!page) return title;
			title += " » ";
			title += page;
			return title;
		}

		virtual void header(int errorCode, const SessionPtr& session, Request& request, PageTranslation& tr, bool hasStrings)
		{
			request << "<!DOCTYPE html "
				"PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" "
				"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n"
				"\r\n"
				"  \r\n"
				"    <title>" << getTitle(errorCode, request, tr, hasStrings) << "</title>\r\n"
				"    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\r\n"
				"    \r\n"
				"    \r\n"
				"    \r\n"
				"    \r\n"
				//"    \r\n"
				"    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no\"/>\r\n";
#if DEBUG_CGI
			request <<
				"    \r\n";
#endif
			const char* description = hasStrings ? tr(lng::LNG_GLOBAL_DESCRIPTION) : "stay up to date";
			request <<
				"    \r\n"
				"    \r\n"
				"    \r\n"
				"    \r\n"
				"    \r\n"
				"    \r\n"
				"    \r\n"
				"  \r\n"
				"  \r\n"
				"

\r\n"
				"
<img src='" << static_web << "images/auth_logo.png' />
\r\n"
				"
" << description << "
\r\n"
				"

\r\n"
				"\r\n"
				"
\r\n";
		}

		virtual void footer(const SessionPtr& session, Request& request, PageTranslation& tr, bool hasStrings)
		{
			request << "\r\n"
				"
 \r\n"
				"  \r\n"
				"</html\r\n";
		}

		virtual void contents(int errorCode, const SessionPtr& session, Request& request, PageTranslation& tr, bool hasStrings)
		{
			request <<
				"
" << errorCode << "
\r\n"
				"
A message
\r\n"
				;
		}

		void onError(int errorCode, Request& request) override
		{
			auto session = request.getSession(false);
			PageTranslation tr{};

			bool hasStrings = tr.init(session, request);

			header(errorCode, session, request, tr, hasStrings);
			contents(errorCode, session, request, tr, hasStrings);
			footer(session, request, tr, hasStrings);
		}
	};

	void setErrorHandlers(Application& app)
	{
		app.setErrorHandler(0, std::make_shared<ErrorPageHandler>());
	}

}}}} // FastCGI::app::reader::errors
<commit_msg>Handler for 400 and 404<commit_after>/*
 * Copyright (C) 2013 midnightBITS
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "pch.h"
#include <forms/vertical_renderer.hpp>
#include <fast_cgi.hpp>
#include "pages/reader_form.hpp"
#include <utils.hpp>

namespace FastCGI { namespace app { namespace reader { namespace errors {

        struct String
        {
                lng::LNG lngId;
                const char* fallback;
        };

	struct FallbackTranslation
	{
		PageTranslation tr;
		bool hasStrings;
	public:
		void init(const SessionPtr& session, Request& request)
		{
			hasStrings = tr.init(session, request);
		}

		const char* operator()(const String& s)
		{
			return hasStrings ? tr(s.lngId) : s.fallback;
		}

		const char* operator()(lng::LNG id, const char* fallback)
		{
                        return hasStrings ? tr(id) : fallback;
		}
	};

	class ErrorPageHandler : public ErrorHandler
	{
	protected:
		virtual const char* pageTitle(int errorCode, FallbackTranslation& tr) { return nullptr; }
		std::string getTitle(int errorCode, Request& request, FallbackTranslation& tr)
		{
			std::string title = tr(lng::LNG_GLOBAL_SITENAME, "reedr");
			const char* page = pageTitle(errorCode, tr);
			if (!page) return title;
			title += " » ";
			title += page;
			return title;
		}

		virtual void header(int errorCode, const SessionPtr& session, Request& request, FallbackTranslation& tr)
		{
			request << "<!DOCTYPE html "
				"PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" "
				"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n"
				"\r\n"
				"  \r\n"
				"    <title>" << getTitle(errorCode, request, tr) << "</title>\r\n"
				"    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\r\n"
				"    \r\n"
				"    \r\n"
				"    \r\n"
				"    \r\n"
				//"    \r\n"
				"    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no\"/>\r\n";
#if DEBUG_CGI
			request <<
				"    \r\n";
#endif
			const char* description = tr(lng::LNG_GLOBAL_DESCRIPTION, "stay up to date");
			request <<
				"    \r\n"
				"    \r\n"
				"    \r\n"
				"    \r\n"
				"    \r\n"
				"    \r\n"
				"    \r\n"
				"  \r\n"
				"  \r\n"
				"

\r\n"
				"
<img src='" << static_web << "images/auth_logo.png' />
\r\n"
				"
" << description << "
\r\n"
				"

\r\n"
				"\r\n"
				"
\r\n";
		}

		virtual void footer(const SessionPtr& session, Request& request, FallbackTranslation& tr)
		{
			request << "\r\n"
				"
 \r\n"
				"  \r\n"
				"</html\r\n";
		}

		virtual void contents(int errorCode, const SessionPtr& session, Request& request, FallbackTranslation& tr)
		{
			request <<
				"
" << errorCode << "
\r\n"
				"
A message
\r\n"
				;
		}

		void onError(int errorCode, Request& request) override
		{
			auto session = request.getSession(false);
			FallbackTranslation tr{};

			tr.init(session, request);

			header(errorCode, session, request, tr);
			contents(errorCode, session, request, tr);
			footer(session, request, tr);
		}
	};

	struct ErrorInfo
	{
		String title;
		String oops;
		String info;
	};

	static inline void error_contents(Request& request, FallbackTranslation& tr, const ErrorInfo& nfo)
	{
		request << "
" << tr(nfo.title) << "
\r\n"
			"
" << tr(nfo.oops) << "
\r\n"
			"
" << tr(nfo.info) << "
\r\n";
	}

	class Error404 : public ErrorPageHandler
	{
	public:
		void contents(int errorCode, const SessionPtr& session, Request& request, FallbackTranslation& tr) override
		{
			error_contents(request, tr, {
				{ lng::LNG_ERROR_404_TITLE, "404
FILE NOT FOUND" },
				{ lng::LNG_ERROR_404_OOPS,  "Well, that was not supposed to happen." },
				{ lng::LNG_ERROR_404_INFO,  "This link has nothing to show, maybe you mistyped the link or followed a bad one." }
			});
		}
	};

	class Error400 : public ErrorPageHandler
	{
	public:
		void contents(int errorCode, const SessionPtr& session, Request& request, FallbackTranslation& tr) override
		{
			error_contents(request, tr, {
				{ lng::LNG_ERROR_400_TITLE, "400
BAD REQUEST" },
				{ lng::LNG_ERROR_400_OOPS,  "Hmm, this request looks mighty strange." },
				{ lng::LNG_ERROR_400_INFO,  "The request your browser made was not understood." }
			});
		}
	};

	void setErrorHandlers(Application& app)
	{
		app.setErrorHandler(0, std::make_shared<ErrorPageHandler>());
		app.setErrorHandler(400, std::make_shared<Error400>());
		app.setErrorHandler(404, std::make_shared<Error404>());
	}

}}}} // FastCGI::app::reader::errors
<|endoftext|>