Пример #1
0
bool TestCppBase::TestCollectionHdf() {
  IniSetting::Map ini = IniSetting::Map::object;
  Hdf hdf;
  hdf.fromString(
    "  Server {\n"
    "    AllowedDirectories.* = /var/www\n"
    "    AllowedDirectories.* = /usr/bin\n"
    "    HighPriorityEndPoints.* = /end\n"
    "    HighPriorityEndPoints.* = /point\n"
    "    HighPriorityEndPoints.* = /power\n"
    "  }\n"
  );
  RuntimeOption::AllowedDirectories.clear();

  Config::Bind(RuntimeOption::AllowedDirectories, ini,
               hdf, "Server.AllowedDirectories");
  VERIFY(RuntimeOption::AllowedDirectories.size() == 2);
  std::vector<std::string> ad =
    Config::GetVector(ini, hdf, "Server.AllowedDirectories",
                      RuntimeOption::AllowedDirectories);
  VERIFY(RuntimeOption::AllowedDirectories.size() == 2);
  VERIFY(ad.size() == 2);
  Config::Bind(RuntimeOption::ServerHighPriorityEndPoints, ini,
               hdf, "Server.HighPriorityEndPoints");
  VERIFY(RuntimeOption::ServerHighPriorityEndPoints.size() == 3);
  return Count(true);
}
Пример #2
0
bool TestCppBase::TestSatelliteServer() {
  IniSetting::Map ini = IniSetting::Map::object;
  Hdf hdf;
  hdf.fromString(
    "Satellites {\n"
    "  rpc {\n"
    "    Type = RPCServer\n"
    "    Port = 9999\n"
    "    RequestInitDocument = my/rpc/rpc.php\n"
    "    RequestInitFunction = init_me\n"
    "    Password = abcd0987\n"
    "    Passwords {\n"
    "      * = abcd0987\n"
    "    }\n"
    "  }\n"
    "  ips {\n"
    "    Type = InternalPageServer\n"
    "    BlockMainServer = false\n"
    "  }\n"
    "}\n"
  );


  std::vector<std::shared_ptr<SatelliteServerInfo>> infos;
  RuntimeOption::ReadSatelliteInfo(ini, hdf, infos,
                                   RuntimeOption::XboxPassword,
                                   RuntimeOption::XboxPasswords);
  for (auto& info_ptr : infos) {
    auto info = info_ptr.get();
    auto name = info->getName();
    if (name == "rpc") {
      VERIFY(info->getType() == SatelliteServer::Type::KindOfRPCServer);
      VERIFY(info->getPort() == 9999);
      VERIFY(info->getThreadCount() == 5);
      VERIFY(info->getTimeoutSeconds() ==
        std::chrono::seconds(RuntimeOption::RequestTimeoutSeconds));
      VERIFY(info->getURLs().size() == 0);
      VERIFY(info->getMaxRequest() == 500);
      VERIFY(info->getMaxDuration() == 120);
      VERIFY(info->getReqInitFunc() == "init_me");
      VERIFY(info->getReqInitDoc() == "my/rpc/rpc.php");
      VERIFY(info->getPassword() == "abcd0987");
      VERIFY(info->getPasswords().size() == 1);
      VERIFY(info->getPasswords().find("abcd0987") !=
             info->getPasswords().end());
      VERIFY(info->alwaysReset() == false);
      VERIFY(RuntimeOption::XboxPassword == "abcd0987");
    } else if (name == "ips") {
      VERIFY(info->getType() ==
             SatelliteServer::Type::KindOfInternalPageServer);
      VERIFY(info->getURLs().size() == 0);
    }
  }
  return Count(true);
}
Пример #3
0
bool TestUtil::TestHDF() {
  // This was causing a crash
  {
    Hdf doc, node;
    node = doc["Node"];
  }

  {
    Hdf doc;
    doc.fromString(
      "node.* {\n"
      "  name = value\n"
      "}");
    VS(doc["node"][0]["name"].getString(), "value");
  }

  return Count(true);
}
Пример #4
0
bool TestUtil::TestHDF() {
  // This was causing a crash
  {
    Hdf doc, node;
    node = doc["Node"];
  }

  {
    IniSetting::Map ini = IniSetting::Map::object;
    Hdf doc;
    doc.fromString(
      "node.* {\n"
      "  name = value\n"
      "}");
    VS(Config::GetString(ini, doc, "node.0.name"), "value");
  }

  return Count(true);
}
Пример #5
0
void Config::ParseHdfString(const std::string hdfStr, Hdf &hdf) {
  hdf.fromString(hdfStr.c_str());
}
Пример #6
0
void RuntimeOption::Load(Hdf &config, StringVec *overwrites /* = NULL */) {
  // Machine metrics
  string hostname, tier, cpu;
  {
    Hdf machine = config["Machine"];

    hostname = machine["name"].getString();
    if (hostname.empty()) {
      hostname = Process::GetHostName();
    }

    tier = machine["tier"].getString();

    cpu = machine["cpu"].getString();
    if (cpu.empty()) {
      cpu = Process::GetCPUModel();
    }
  }

  // Tier overwrites
  {
    Hdf tiers = config["Tiers"];
    for (Hdf hdf = tiers.firstChild(); hdf.exists(); hdf = hdf.next()) {
      if (matchHdfPattern(hostname, hdf["machine"]) &&
          matchHdfPattern(tier, hdf["tier"]) &&
          matchHdfPattern(cpu, hdf["cpu"])) {
        Tier = hdf.getName();
        config.copy(hdf["overwrite"]);
        // no break here, so we can continue to match more overwrites
      }
      hdf["overwrite"].setVisited(); // avoid lint complaining
    }
  }

  // More overwrites
  if (overwrites) {
    for (unsigned int i = 0; i < overwrites->size(); i++) {
      config.fromString(overwrites->at(i).c_str());
    }
  }

  PidFile = config["PidFile"].getString("www.pid");

  {
    Hdf logger = config["Log"];
    if (logger["Level"] == "None") {
      Logger::LogLevel = Logger::LogNone;
    } else if (logger["Level"] == "Error") {
      Logger::LogLevel = Logger::LogError;
    } else if (logger["Level"] == "Warning") {
      Logger::LogLevel = Logger::LogWarning;
    } else if (logger["Level"] == "Info") {
      Logger::LogLevel = Logger::LogInfo;
    } else if (logger["Level"] == "Verbose") {
      Logger::LogLevel = Logger::LogVerbose;
    }
    Logger::LogHeader = logger["Header"].getBool();
    bool logInjectedStackTrace = logger["InjectedStackTrace"].getBool();
    if (logInjectedStackTrace) {
      Logger::SetTheLogger(new ExtendedLogger());
      ExtendedLogger::EnabledByDefault = true;
    }
    Logger::LogNativeStackTrace = logger["NativeStackTrace"].getBool(true);
    Logger::MaxMessagesPerRequest =
      logger["MaxMessagesPerRequest"].getInt32(-1);

    Logger::UseLogFile = logger["UseLogFile"].getBool(true);
    Logger::UseCronolog = logger["UseCronolog"].getBool(false);
    if (Logger::UseLogFile) {
      LogFile = logger["File"].getString();
      LogFileSymLink = logger["SymLink"].getString();
    }
    Logger::DropCacheChunkSize =
      logger["DropCacheChunkSize"].getInt32(1 << 20);
    AlwaysEscapeLog = logger["AlwaysEscapeLog"].getBool(false);

    Hdf aggregator = logger["Aggregator"];
    Logger::UseLogAggregator = aggregator.getBool();
    LogAggregatorFile = aggregator["File"].getString();
    LogAggregatorDatabase = aggregator["Database"].getString();
    LogAggregatorSleepSeconds = aggregator["SleepSeconds"].getInt16(10);

    AlwaysLogUnhandledExceptions =
      logger["AlwaysLogUnhandledExceptions"].getBool(true);
    NoSilencer = logger["NoSilencer"].getBool();
    EnableApplicationLog = logger["ApplicationLog"].getBool(true);
    RuntimeErrorReportingLevel =
      logger["RuntimeErrorReportingLevel"].getInt32(ErrorConstants::HPHP_ALL);

    AccessLogDefaultFormat = logger["AccessLogDefaultFormat"].
      getString("%h %l %u %t \"%r\" %>s %b");
    {
      Hdf access = logger["Access"];
      for (Hdf hdf = access.firstChild(); hdf.exists();
           hdf = hdf.next()) {
        string fname = hdf["File"].getString();
        if (fname.empty()) {
          continue;
        }
        string symLink = hdf["SymLink"].getString();
        AccessLogs.
          push_back(AccessLogFileData(fname, symLink, hdf["Format"].
                                      getString(AccessLogDefaultFormat)));
      }
    }

    AdminLogFormat = logger["AdminLog.Format"].getString("%h %t %s %U");
    AdminLogFile = logger["AdminLog.File"].getString();
    AdminLogSymLink = logger["AdminLog.SymLink"].getString();
  }
  {
    Hdf error = config["ErrorHandling"];

    /* Remove this, once its removed from production configs */
    (void)error["NoInfiniteLoopDetection"].getBool();

    MaxSerializedStringSize =
      error["MaxSerializedStringSize"].getInt32(64 * 1024 * 1024);
    CallUserHandlerOnFatals = error["CallUserHandlerOnFatals"].getBool(true);
    MaxLoopCount = error["MaxLoopCount"].getInt32(0);
    NoInfiniteRecursionDetection =
      error["NoInfiniteRecursionDetection"].getBool();
    ThrowBadTypeExceptions = error["ThrowBadTypeExceptions"].getBool();
    ThrowTooManyArguments = error["ThrowTooManyArguments"].getBool();
    WarnTooManyArguments = error["WarnTooManyArguments"].getBool();
    ThrowMissingArguments = error["ThrowMissingArguments"].getBool();
    ThrowInvalidArguments = error["ThrowInvalidArguments"].getBool();
    EnableHipHopErrors = error["EnableHipHopErrors"].getBool(true);
    AssertActive = error["AssertActive"].getBool();
    AssertWarning = error["AssertWarning"].getBool();
    NoticeFrequency = error["NoticeFrequency"].getInt32(1);
    WarningFrequency = error["WarningFrequency"].getInt32(1);
  }
  {
    Hdf rlimit = config["ResourceLimit"];
    setResourceLimit(RLIMIT_CORE,   rlimit, "CoreFileSize");
    setResourceLimit(RLIMIT_NOFILE, rlimit, "MaxSocket");
    setResourceLimit(RLIMIT_DATA,   rlimit, "RSS");
    MaxRSS = rlimit["MaxRSS"].getInt64(0);
    SocketDefaultTimeout = rlimit["SocketDefaultTimeout"].getInt16(5);
    MaxRSSPollingCycle = rlimit["MaxRSSPollingCycle"].getInt64(0);
    DropCacheCycle = rlimit["DropCacheCycle"].getInt64(0);
    MaxSQLRowCount = rlimit["MaxSQLRowCount"].getInt64(0);
    MaxMemcacheKeyCount = rlimit["MaxMemcacheKeyCount"].getInt64(0);
    SerializationSizeLimit = rlimit["SerializationSizeLimit"].getInt64(0);
    StringOffsetLimit = rlimit["StringOffsetLimit"].getInt64(10 * 1024 * 1024);
  }
  {
    Hdf server = config["Server"];
    Host = server["Host"].getString();
    DefaultServerNameSuffix = server["DefaultServerNameSuffix"].getString();
    ServerIP = server["IP"].getString("0.0.0.0");
    ServerPrimaryIP = Util::GetPrimaryIP();
    ServerPort = server["Port"].getInt16(80);
    ServerBacklog = server["Backlog"].getInt16(128);
    ServerConnectionLimit = server["ConnectionLimit"].getInt16(0);
    ServerThreadCount = server["ThreadCount"].getInt32(50);
    ServerThreadRoundRobin = server["ThreadRoundRobin"].getBool();
    ServerThreadDropCacheTimeoutSeconds =
      server["ThreadDropCacheTimeoutSeconds"].getInt32(0);
    ServerThreadJobLIFO = server["ThreadJobLIFO"].getBool();
    RequestTimeoutSeconds = server["RequestTimeoutSeconds"].getInt32(0);
    RequestMemoryMaxBytes = server["RequestMemoryMaxBytes"].getInt64(-1);
    ResponseQueueCount = server["ResponseQueueCount"].getInt32(0);
    if (ResponseQueueCount <= 0) {
      ResponseQueueCount = ServerThreadCount / 10;
      if (ResponseQueueCount <= 0) ResponseQueueCount = 1;
    }
    ServerGracefulShutdownWait = server["GracefulShutdownWait"].getInt16(0);
    ServerHarshShutdown = server["HarshShutdown"].getBool(true);
    ServerEvilShutdown = server["EvilShutdown"].getBool(true);
    ServerDanglingWait = server["DanglingWait"].getInt16(0);
    if (ServerGracefulShutdownWait < ServerDanglingWait) {
      ServerGracefulShutdownWait = ServerDanglingWait;
    }
    GzipCompressionLevel = server["GzipCompressionLevel"].getInt16(3);

    ForceCompressionURL    = server["ForceCompression"]["URL"].getString();
    ForceCompressionCookie = server["ForceCompression"]["Cookie"].getString();
    ForceCompressionParam  = server["ForceCompression"]["Param"].getString();

    EnableMagicQuotesGpc = server["EnableMagicQuotesGpc"].getBool();
    EnableKeepAlive = server["EnableKeepAlive"].getBool(true);
    ExposeHPHP = server["ExposeHPHP"].getBool(true);
    ExposeXFBServer = server["ExposeXFBServer"].getBool();
    ConnectionTimeoutSeconds = server["ConnectionTimeoutSeconds"].getInt16(-1);
    EnableOutputBuffering = server["EnableOutputBuffering"].getBool();
    OutputHandler = server["OutputHandler"].getString();
    ImplicitFlush = server["ImplicitFlush"].getBool();
    EnableEarlyFlush = server["EnableEarlyFlush"].getBool(true);
    ForceChunkedEncoding = server["ForceChunkedEncoding"].getBool();
    MaxPostSize = (server["MaxPostSize"].getInt32(100)) * (1LL << 20);
    AlwaysPopulateRawPostData = server["AlwaysPopulateRawPostData"].getBool();
    LibEventSyncSend = server["LibEventSyncSend"].getBool(true);
    TakeoverFilename = server["TakeoverFilename"].getString();
    ExpiresActive = server["ExpiresActive"].getBool(true);
    ExpiresDefault = server["ExpiresDefault"].getInt32(2592000);
    if (ExpiresDefault < 0) ExpiresDefault = 2592000;
    DefaultCharsetName = server["DefaultCharsetName"].getString("utf-8");

    RequestBodyReadLimit = server["RequestBodyReadLimit"].getInt32(-1);

    EnableSSL = server["EnableSSL"].getBool();
    SSLPort = server["SSLPort"].getInt16(443);
    SSLCertificateFile = server["SSLCertificateFile"].getString();
    SSLCertificateKeyFile = server["SSLCertificateKeyFile"].getString();

    SourceRoot = Util::normalizeDir(server["SourceRoot"].getString());
    if (!SourceRoot.empty()) {
      // Guaranteed empty on empty load so avoid setting FileCache::SourceRoot
      // since it may not be initialized
      FileCache::SourceRoot = SourceRoot;
    }
    server["IncludeSearchPaths"].get(IncludeSearchPaths);
    for (unsigned int i = 0; i < IncludeSearchPaths.size(); i++) {
      IncludeSearchPaths[i] = Util::normalizeDir(IncludeSearchPaths[i]);
    }
    IncludeSearchPaths.insert(IncludeSearchPaths.begin(), "./");

    FileCache = server["FileCache"].getString();
    DefaultDocument = server["DefaultDocument"].getString();
    ErrorDocument404 = server["ErrorDocument404"].getString();
    normalizePath(ErrorDocument404);
    ErrorDocument500 = server["ErrorDocument500"].getString();
    normalizePath(ErrorDocument500);
    FatalErrorMessage = server["FatalErrorMessage"].getString();
    FontPath = Util::normalizeDir(server["FontPath"].getString());
    EnableStaticContentCache =
      server["EnableStaticContentCache"].getBool(true);
    EnableStaticContentFromDisk =
      server["EnableStaticContentFromDisk"].getBool(true);
    EnableOnDemandUncompress =
      server["EnableOnDemandUncompress"].getBool(true);
    EnableStaticContentMMap =
      server["EnableStaticContentMMap"].getBool(true);
    if (EnableStaticContentMMap) {
      EnableOnDemandUncompress = true;
    }
    RTTIDirectory =
      Util::normalizeDir(server["RTTIDirectory"].getString("/tmp/"));
    EnableCliRTTI = server["EnableCliRTTI"].getBool();
    Utf8izeReplace = server["Utf8izeReplace"].getBool(true);

    StartupDocument = server["StartupDocument"].getString();
    normalizePath(StartupDocument);
    WarmupDocument = server["WarmupDocument"].getString();
    RequestInitFunction = server["RequestInitFunction"].getString();
    RequestInitDocument = server["RequestInitDocument"].getString();
    server["ThreadDocuments"].get(ThreadDocuments);
    for (unsigned int i = 0; i < ThreadDocuments.size(); i++) {
      normalizePath(ThreadDocuments[i]);
    }
    server["ThreadLoopDocuments"].get(ThreadLoopDocuments);
    for (unsigned int i = 0; i < ThreadLoopDocuments.size(); i++) {
      normalizePath(ThreadLoopDocuments[i]);
    }

    SafeFileAccess = server["SafeFileAccess"].getBool();
    server["AllowedDirectories"].get(AllowedDirectories);
    for (unsigned int i = 0; i < AllowedDirectories.size(); i++) {
      string &directory = AllowedDirectories[i];
      char resolved_path[PATH_MAX];
      if (realpath(directory.c_str(), resolved_path) &&
          directory != resolved_path) {
        RuntimeOption::AllowedDirectories.push_back(resolved_path);
      }
    }
    server["AllowedFiles"].get(AllowedFiles);

    server["ForbiddenFileExtensions"].get(ForbiddenFileExtensions);

    EnableMemoryManager = server["EnableMemoryManager"].getBool(true);
    CheckMemory = server["CheckMemory"].getBool();
    UseHphpArray = server["UseHphpArray"].getBool(false);
    UseSmallArray = server["UseSmallArray"].getBool(false);
    UseDirectCopy = server["UseDirectCopy"].getBool(false);
    AlwaysUseRelativePath = server["AlwaysUseRelativePath"].getBool(false);

    Hdf apc = server["APC"];
    EnableApc = apc["EnableApc"].getBool(true);
    EnableConstLoad = apc["EnableConstLoad"].getBool(false);
    ForceConstLoadToAPC = apc["ForceConstLoadToAPC"].getBool(true);
    ApcPrimeLibrary = apc["PrimeLibrary"].getString();
    ApcLoadThread = apc["LoadThread"].getInt16(2);
    apc["CompletionKeys"].get(ApcCompletionKeys);

    string apcTableType = apc["TableType"].getString("concurrent");
    if (strcasecmp(apcTableType.c_str(), "hash") == 0) {
      ApcTableType = ApcHashTable;
    } else if (strcasecmp(apcTableType.c_str(), "concurrent") == 0) {
      ApcTableType = ApcConcurrentTable;
    } else {
      throw InvalidArgumentException("apc table type",
                                     "Invalid table type");
    }
    string apcLockType = apc["LockType"].getString("readwritelock");
    if (strcasecmp(apcLockType.c_str(), "readwritelock") == 0) {
      ApcTableLockType = ApcReadWriteLock;
    } else if (strcasecmp(apcLockType.c_str(), "mutex") == 0) {
      ApcTableLockType = ApcMutex;
    } else {
      throw InvalidArgumentException("apc lock type",
                                     "Invalid lock type");
    }

    ApcExpireOnSets = apc["ExpireOnSets"].getBool();
    ApcPurgeFrequency = apc["PurgeFrequency"].getInt32(4096);

    ApcAllowObj = apc["AllowObject"].getBool();

    ApcKeyMaturityThreshold = apc["KeyMaturityThreshold"].getInt32(20);
    ApcMaximumCapacity = apc["MaximumCapacity"].getInt64(0);
    ApcKeyFrequencyUpdatePeriod = apc["KeyFrequencyUpdatePeriod"].
      getInt32(1000);


    Hdf dns = server["DnsCache"];
    EnableDnsCache = dns["Enable"].getBool();
    DnsCacheTTL = dns["TTL"].getInt32(600); // 10 minutes
    DnsCacheKeyMaturityThreshold = dns["KeyMaturityThreshold"].getInt32(20);
    DnsCacheMaximumCapacity = dns["MaximumCapacity"].getInt64(0);
    DnsCacheKeyFrequencyUpdatePeriod = dns["KeyFrequencyUpdatePeriod"].
      getInt32(1000);

    Hdf upload = server["Upload"];
    UploadMaxFileSize =
      (upload["UploadMaxFileSize"].getInt32(100)) * (1LL << 20);
    UploadTmpDir = upload["UploadTmpDir"].getString("/tmp");
    RuntimeOption::AllowedDirectories.push_back(UploadTmpDir);
    EnableFileUploads = upload["EnableFileUploads"].getBool(true);
    EnableUploadProgress = upload["EnableUploadProgress"].getBool();
    Rfc1867Freq = upload["Rfc1867Freq"].getInt32(256 * 1024);
    if (Rfc1867Freq < 0) Rfc1867Freq = 256 * 1024;
    Rfc1867Prefix = upload["Rfc1867Prefix"].getString("vupload_");
    Rfc1867Name = upload["Rfc1867Name"].getString("video_ptoken");

    ImageMemoryMaxBytes = server["ImageMemoryMaxBytes"].getInt64(0);
    if (ImageMemoryMaxBytes == 0) {
      ImageMemoryMaxBytes = UploadMaxFileSize * 2;
    }
    SharedStores::Create();

    LightProcessFilePrefix =
      server["LightProcessFilePrefix"].getString("./lightprocess");
    LightProcessCount = server["LightProcessCount"].getInt32(0);

    InjectedStackTrace = server["InjectedStackTrace"].getBool(true);
    InjectedStackTraceLimit = server["InjectedStackTraceLimit"].getInt32(-1);

    ForceServerNameToHeader = server["ForceServerNameToHeader"].getBool();

    ServerUser = server["User"].getString("");
  }
  {
    Hdf hosts = config["VirtualHost"];
    if (hosts.exists()) {
      for (Hdf hdf = hosts.firstChild(); hdf.exists(); hdf = hdf.next()) {
        if (hdf.getName() == "default") {
          VirtualHost::GetDefault().init(hdf);
        } else {
          VirtualHostPtr host(new VirtualHost(hdf));
          VirtualHosts.push_back(host);
        }
      }
      for (unsigned int i = 0; i < VirtualHosts.size(); i++) {
        if (!VirtualHosts[i]->valid()) {
          throw InvalidArgumentException("virtual host",
                                         "missing prefix or pattern");
        }
      }
    }
  }
  {
    Hdf ipblocks = config["IpBlockMap"];
    IpBlocks = IpBlockMapPtr(new IpBlockMap(ipblocks));
  }
  {
    Hdf satellites = config["Satellites"];
    if (satellites.exists()) {
      for (Hdf hdf = satellites.firstChild(); hdf.exists(); hdf = hdf.next()) {
        SatelliteServerInfoPtr satellite(new SatelliteServerInfo(hdf));
        SatelliteServerInfos.push_back(satellite);
        if (satellite->getType() == SatelliteServer::KindOfRPCServer) {
          XboxPassword = satellite->getPassword();
        }
      }
    }
  }
  {
    Hdf xbox = config["Xbox"];
    XboxServerThreadCount = xbox["ServerInfo.ThreadCount"].getInt32(0);
    XboxServerPort = xbox["ServerInfo.Port"].getInt32(0);
    XboxDefaultLocalTimeoutMilliSeconds =
      xbox["DefaultLocalTimeoutMilliSeconds"].getInt32(500);
    XboxDefaultRemoteTimeoutSeconds =
      xbox["DefaultRemoteTimeoutSeconds"].getInt32(5);
    XboxServerInfoMaxRequest = xbox["ServerInfo.MaxRequest"].getInt32(500);
    XboxServerInfoDuration = xbox["ServerInfo.MaxDuration"].getInt32(120);
    XboxServerInfoWarmupDoc = xbox["ServerInfo.WarmupDocument"].get("");
    XboxServerInfoReqInitFunc = xbox["ServerInfo.RequestInitFunction"].get("");
    XboxServerInfoReqInitDoc = xbox["ServerInfo.RequestInitDocument"].get("");
    XboxProcessMessageFunc =
      xbox["ProcessMessageFunc"].get("xbox_process_message");
  }
  {
    Hdf pagelet = config["PageletServer"];
    PageletServerThreadCount = pagelet["ThreadCount"].getInt32(0);
    PageletServerThreadRoundRobin = pagelet["ThreadRoundRobin"].getBool();
    PageletServerThreadDropCacheTimeoutSeconds =
      pagelet["ThreadDropCacheTimeoutSeconds"].getInt32(0);
  }
  {
    FiberCount = config["Fiber.ThreadCount"].getInt32(Process::GetCPUCount());
  }
  {
    Hdf content = config["StaticFile"];
    content["Extensions"].get(StaticFileExtensions);
    content["Generators"].get(StaticFileGenerators);

    Hdf matches = content["FilesMatch"];
    if (matches.exists()) {
      for (Hdf hdf = matches.firstChild(); hdf.exists(); hdf = hdf.next()) {
        FilesMatches.push_back(FilesMatchPtr(new FilesMatch(hdf)));
      }
    }
  }
  {
    Hdf admin = config["AdminServer"];
    AdminServerPort = admin["Port"].getInt16(8088);
    AdminThreadCount = admin["ThreadCount"].getInt32(1);
    AdminPassword = admin["Password"].getString();
  }
  {
    Hdf proxy = config["Proxy"];
    ProxyOrigin = proxy["Origin"].getString();
    ProxyRetry = proxy["Retry"].getInt16(3);
    UseServeURLs = proxy["ServeURLs"].getBool();
    proxy["ServeURLs"].get(ServeURLs);
    UseProxyURLs = proxy["ProxyURLs"].getBool();
    ProxyPercentage = proxy["Percentage"].getByte(0);
    proxy["ProxyURLs"].get(ProxyURLs);
    proxy["ProxyPatterns"].get(ProxyPatterns);
  }
  {
    Hdf mysql = config["MySQL"];
    MySQLReadOnly = mysql["ReadOnly"].getBool();
    MySQLLocalize = mysql["Localize"].getBool();
    MySQLConnectTimeout = mysql["ConnectTimeout"].getInt32(1000);
    MySQLReadTimeout = mysql["ReadTimeout"].getInt32(1000);
    MySQLWaitTimeout = mysql["WaitTimeout"].getInt32(-1);
    MySQLSlowQueryThreshold = mysql["SlowQueryThreshold"].getInt32(1000);
    MySQLKillOnTimeout = mysql["KillOnTimeout"].getBool();
  }
  {
    Hdf http = config["Http"];
    HttpDefaultTimeout = http["DefaultTimeout"].getInt32(30);
    HttpSlowQueryThreshold = http["SlowQueryThreshold"].getInt32(5000);
  }
  {
    Hdf debug = config["Debug"];
    NativeStackTrace = debug["NativeStackTrace"].getBool();
    StackTrace::Enabled = NativeStackTrace;
    TranslateLeakStackTrace = debug["TranslateLeakStackTrace"].getBool();
    FullBacktrace = debug["FullBacktrace"].getBool();
    ServerStackTrace = debug["ServerStackTrace"].getBool();
    ServerErrorMessage = debug["ServerErrorMessage"].getBool();
    TranslateSource = debug["TranslateSource"].getBool();
    RecordInput = debug["RecordInput"].getBool();
    ClearInputOnSuccess = debug["ClearInputOnSuccess"].getBool(true);
    ProfilerOutputDir = debug["ProfilerOutputDir"].getString("/tmp");
    CoreDumpEmail = debug["CoreDumpEmail"].getString();
    if (!CoreDumpEmail.empty()) {
      StackTrace::ReportEmail = CoreDumpEmail;
    }
    CoreDumpReport = debug["CoreDumpReport"].getBool(true);
    if (CoreDumpReport) {
      StackTrace::InstallReportOnErrors();
    }
    std::string reportDirectory = debug["CoreDumpReportDirectory"].getString();
    if (!reportDirectory.empty()) {
      StackTraceBase::ReportDirectory = reportDirectory;
    }
    LocalMemcache = debug["LocalMemcache"].getBool();
    MemcacheReadOnly = debug["MemcacheReadOnly"].getBool();

    {
      Hdf simpleCounter = debug["SimpleCounter"];
      SimpleCounter::SampleStackCount =
        simpleCounter["SampleStackCount"].getInt32(0);
      SimpleCounter::SampleStackDepth =
        simpleCounter["SampleStackDepth"].getInt32(5);
    }
  }
  {
    Hdf stats = config["Stats"];
    EnableStats = stats.getBool(); // main switch

    EnableWebStats = stats["Web"].getBool();
    EnableMemoryStats = stats["Memory"].getBool();
    EnableMallocStats = stats["Malloc"].getBool();
    EnableAPCStats = stats["APC"].getBool();
    EnableAPCKeyStats = stats["APCKey"].getBool();
    EnableMemcacheStats = stats["Memcache"].getBool();
    EnableMemcacheKeyStats = stats["MemcacheKey"].getBool();
    EnableSQLStats = stats["SQL"].getBool();
    EnableSQLTableStats = stats["SQLTable"].getBool();
    EnableNetworkIOStatus = stats["NetworkIO"].getBool();

    if (EnableStats && EnableMallocStats) {
      LeakDetectable::EnableMallocStats(true);
    }

    StatsXSL = stats["XSL"].getString();
    StatsXSLProxy = stats["XSLProxy"].getString();

    StatsSlotDuration = stats["SlotDuration"].getInt32(10 * 60); // 10 minutes
    StatsMaxSlot = stats["MaxSlot"].getInt32(12 * 6); // 12 hours

    {
      Hdf apcSize = stats["APCSize"];
      EnableAPCSizeStats = apcSize["Enable"].getBool();
      EnableAPCSizeGroup = apcSize["Group"].getBool();
      apcSize["SpecialPrefix"].get(APCSizeSpecialPrefix);
      for (unsigned int i = 0; i < APCSizeSpecialPrefix.size(); i++) {
        string &prefix = APCSizeSpecialPrefix[i];
        string prefixReplace = prefix + "{A}";
        APCSizePrefixReplace.push_back(prefixReplace);
      }
      apcSize["SpecialMiddle"].get(APCSizeSpecialMiddle);
      for (unsigned int i = 0; i < APCSizeSpecialMiddle.size(); i++) {
        string &middle = APCSizeSpecialMiddle[i];
        string middleReplace = "{A}" + middle + "{A}";
        APCSizeMiddleReplace.push_back(middleReplace);
      }
      apcSize["SkipPrefix"].get(APCSizeSkipPrefix);
      EnableAPCSizeDetail = apcSize["Individual"].getBool();
      EnableAPCFetchStats = apcSize["FetchStats"].getBool();
      if (EnableAPCFetchStats) EnableAPCSizeDetail = true;
      if (EnableAPCSizeDetail) EnableAPCSizeGroup = true;
      APCSizeCountPrime = apcSize["CountPrime"].getBool();
    }

    EnableHotProfiler = stats["EnableHotProfiler"].getBool(true);
    ProfilerTraceBuffer = stats["ProfilerTraceBuffer"].getInt32(2000000);
    ProfilerTraceExpansion = stats["ProfilerTraceExpansion"].getDouble(1.2);
    ProfilerMaxTraceBuffer = stats["ProfilerMaxTraceBuffer"].getInt32(0);
  }
  {
    config["ServerVariables"].get(ServerVariables);
    config["EnvVariables"].get(EnvVariables);
  }
  {
    Hdf eval = config["Eval"];
    EnableHipHopSyntax = eval["EnableHipHopSyntax"].getBool();
    EnableHipHopExperimentalSyntax =
      eval["EnableHipHopExperimentalSyntax"].getBool();
    EnableShortTags= eval["EnableShortTags"].getBool(true);
    if (EnableShortTags) ScannerType |= Scanner::AllowShortTags;
    else ScannerType &= ~Scanner::AllowShortTags;

    EnableAspTags = eval["EnableAspTags"].getBool();
    if (EnableAspTags) ScannerType |= Scanner::AllowAspTags;
    else ScannerType &= ~Scanner::AllowAspTags;

    EnableXHP = eval["EnableXHP"].getBool(true);
    EnableObjDestructCall = eval["EnableObjDestructCall"].getBool(false);
    CheckSymLink = eval["CheckSymLink"].getBool(false);
    NativeXHP = eval["NativeXHP"].getBool(true);
    if (EnableXHP && !NativeXHP) ScannerType |= Scanner::PreprocessXHP;
    else ScannerType &= ~Scanner::PreprocessXHP;

    EnableStrict = eval["EnableStrict"].getBool();
    StrictLevel = eval["StrictLevel"].getInt32(1); // StrictBasic
    StrictFatal = eval["StrictFatal"].getBool();
    RecordCodeCoverage = eval["RecordCodeCoverage"].getBool();
    CodeCoverageOutputFile = eval["CodeCoverageOutputFile"].getString();
    {
      Hdf debugger = eval["Debugger"];
      EnableDebugger = debugger["EnableDebugger"].getBool();
      EnableDebuggerServer = debugger["EnableDebuggerServer"].getBool();
      DebuggerServerPort = debugger["Port"].getInt16(8089);
      DebuggerStartupDocument = debugger["StartupDocument"].getString();
      DebuggerDefaultSandboxPath = debugger["DefaultSandboxPath"].getString();

      DebuggerDefaultRpcPort = debugger["RPC.DefaultPort"].getInt16(8083);
      DebuggerDefaultRpcAuth = debugger["RPC.DefaultAuth"].getString();
      DebuggerRpcHostDomain = debugger["RPC.HostDomain"].getString();
      DebuggerDefaultRpcTimeout = debugger["RPC.DefaultTimeout"].getInt32(30);
    }
  }
  {
    Hdf sandbox = config["Sandbox"];
    SandboxMode = sandbox["SandboxMode"].getBool();
    SandboxPattern = Util::format_pattern
      (sandbox["Pattern"].getString(), true);
    SandboxHome = sandbox["Home"].getString();
    SandboxFallback = sandbox["Fallback"].getString();
    SandboxConfFile = sandbox["ConfFile"].getString();
    SandboxFromCommonRoot = sandbox["FromCommonRoot"].getBool();
    SandboxDirectoriesRoot = sandbox["DirectoriesRoot"].getString();
    SandboxLogsRoot = sandbox["LogsRoot"].getString();
    sandbox["ServerVariables"].get(SandboxServerVariables);
  }
  {
    Hdf mail = config["Mail"];
    SendmailPath = mail["SendmailPath"].getString("sendmail -t -i");
    MailForceExtraParameters = mail["ForceExtraParameters"].getString();
  }
  {
    Hdf preg = config["Preg"];
    PregBacktraceLimit = preg["BacktraceLimit"].getInt32(100000);
    PregRecursionLimit = preg["RecursionLimit"].getInt32(100000);
  }

  Extension::LoadModules(config);
}
Пример #7
0
bool TestCppBase::TestIpBlockMap() {
  struct in6_addr addr;
  int bits;

  VERIFY(IpBlockMap::ReadIPv6Address("204.15.21.0/22", &addr, bits));
  VS(bits, 118);
  VS(in6addrWord(addr, 0), 0x00000000L);
  VS(in6addrWord(addr, 1), 0x00000000L);
  VS(in6addrWord(addr, 2), 0x0000FFFFL);
  VS(in6addrWord(addr, 3), 0xCC0F1500L);

  VERIFY(IpBlockMap::ReadIPv6Address("127.0.0.1", &addr, bits));
  VS(bits, 128);
  VS(in6addrWord(addr, 0), 0x00000000L);
  VS(in6addrWord(addr, 1), 0x00000000L);
  VS(in6addrWord(addr, 2), 0x0000FFFFL);
  VS(in6addrWord(addr, 3), 0x7F000001L);

  VERIFY(IpBlockMap::ReadIPv6Address(
    "1111:2222:3333:4444:5555:6666:789a:bcde", &addr, bits));
  VS(bits, 128);
  VS(in6addrWord(addr, 0), 0x11112222L);
  VS(in6addrWord(addr, 1), 0x33334444L);
  VS(in6addrWord(addr, 2), 0x55556666L);
  VS(in6addrWord(addr, 3), 0x789abcdeL);

  VERIFY(IpBlockMap::ReadIPv6Address(
    "1111:2222:3333:4444:5555:6666:789a:bcde/68", &addr, bits));
  VS(bits, 68);
  VS(in6addrWord(addr, 0), 0x11112222L);
  VS(in6addrWord(addr, 1), 0x33334444L);
  VS(in6addrWord(addr, 2), 0x55556666L);
  VS(in6addrWord(addr, 3), 0x789abcdeL);

  IpBlockMap::BinaryPrefixTrie root(true);
  unsigned char value[16];

  // Default value with no additional nodes
  memset(value, 0, 16);
  VERIFY(root.isAllowed(value, 1));
  value[0] = 0x80;
  VERIFY(root.isAllowed(value));

  // Inheritance of parent allow value through multiple levels of new nodes
  IpBlockMap::BinaryPrefixTrie::InsertNewPrefix(&root, value, 1, false);
  value[0] = 0xf0;
  IpBlockMap::BinaryPrefixTrie::InsertNewPrefix(&root, value, 4, true);
  VERIFY(root.isAllowed(value));
  value[0] = 0xe0;
  VERIFY(!root.isAllowed(value));
  value[0] = 0xc0;
  VERIFY(!root.isAllowed(value));
  value[0] = 0x80;
  VERIFY(!root.isAllowed(value));
  value[0] = 0;
  VERIFY(root.isAllowed(value));

  // > 1 byte in address
  value[2] = 0xff;
  IpBlockMap::BinaryPrefixTrie::InsertNewPrefix(&root, value, 24, false);
  VERIFY(!root.isAllowed(value));
  value[3] = 0xff;
  VERIFY(!root.isAllowed(value));
  value[2] = 0xfe;
  VERIFY(root.isAllowed(value));

  // Exact address match
  value[2]  = 0xff;
  value[15] = 1;
  IpBlockMap::BinaryPrefixTrie::InsertNewPrefix(&root, value, 128, true);
  VERIFY(root.isAllowed(value));

  Hdf hdf;
  hdf.fromString(
    "  0 {\n"
    "    Location = /test\n"
    "    AllowFirst = true\n"
    "    Ip {\n"
    "      Allow {\n"
    "       * = 127.0.0.1\n"
    "     }\n"
    "     Deny {\n"
    "       * = 8.32.0.0/24\n"
    "       * = aaaa:bbbb:cccc:dddd:eeee:ffff:1111::/80\n"
    "     }\n"
    "    }\n"
    "  }\n"
  );

  IpBlockMap ibm(hdf);
  VERIFY(!ibm.isBlocking("test/blah.php", "127.0.0.1"));
  VERIFY(ibm.isBlocking("test/blah.php", "8.32.0.104"));
  VERIFY(ibm.isBlocking("test/blah.php",
                        "aaaa:bbbb:cccc:dddd:eeee:9999:8888:7777"));
  VERIFY(!ibm.isBlocking("test/blah.php",
                         "aaaa:bbbb:cccc:dddd:eee3:4444:3333:2222"));

  return Count(true);
}
Пример #8
0
void Config::ParseHdfString(const std::string hdfStr, Hdf &hdf,
                            IniSetting::Map &ini) {
  hdf.fromString(hdfStr.c_str());
}
Пример #9
0
bool TestCppBase::TestVirtualHost() {
  IniSetting::Map ini = IniSetting::Map::object;
  Hdf hdf;
  hdf.fromString(
    "  Server {\n"
    "    AllowedDirectories.* = /var/www\n"
    "    AllowedDirectories.* = /usr/bin\n"
    "  }\n"
    "  VirtualHost {\n"
    "    flibtest {\n"
    "      Prefix = flibtest.\n"
    "      PathTranslation = flib/_bin\n"
    "      ServerName = flibtest.facebook.com\n"
    "    }\n"
    "    upload {\n"
    "      Prefix = upload.\n"
    "      ServerVariables {\n"
    "        TFBENV = 8{\n"
    "      }\n"
    "      overwrite {\n"
    "        Server {\n"
    "          AllowedDirectories.* = /var/www\n"
    "          AllowedDirectories.* = /mnt\n"
    "          AllowedDirectories.* = /tmp\n"
    "          AllowedDirectories.* = /var/tmp/tao\n"
    "        }\n"
    "        MaxPostSize = 100MB\n"
    "        UploadMaxFileSize = 100MB\n"
    "        RequestTimeoutSeconds = 120\n"
    "      }\n"
    "      PathTranslation = html\n"
    "    }\n"
    "    default {\n"
    "      LogFilters {\n"
    "        * {\n"
    "          url = /method/searchme\n"
    "          params {\n"
    "            * = q\n"
    "            * = s\n"
    "            * = atoken\n"
    "            * = otoken\n"
    "          }\n"
    "        value = REMOVED\n"
    "        }\n"
    "      }\n"
    "      RewriteRules {\n"
    "        common {\n"
    "          pattern = /html/common/\n"
    "          to = http://3v4l.org\n"
    "          qsa = true\n"
    "          redirect = 301\n"
    "        }\n"
    "      }\n"
    "      PathTranslation = htm\n"
    "    }\n"
    "  }\n"
  );

  // reset RuntimeOption::AllowedDirectories to empty because if the INI
  // version of this test is run at the same time, we don't want to append
  // the same directories to it. We want to start fresh.
  RuntimeOption::AllowedDirectories.clear();
  std::vector<VirtualHost> hosts;
  RuntimeOption::AllowedDirectories =
    Config::GetVector(ini, hdf, "Server.AllowedDirectories");
  auto cb = [&] (const IniSetting::Map &ini_cb, const Hdf &hdf_cb,
                 const std::string &host) {
    if (VirtualHost::IsDefault(ini_cb, hdf_cb, host)) {
      VirtualHost::GetDefault().init(ini_cb, hdf_cb, host);
      VirtualHost::GetDefault().
        addAllowedDirectories(RuntimeOption::AllowedDirectories);
    } else {
      auto vh = VirtualHost(ini_cb, hdf_cb, host);
      // These will be added
      // "    AllowedDirectories.* = /var/www\n"
      // "    AllowedDirectories.* = /usr/bin\n"
      vh.addAllowedDirectories(RuntimeOption::AllowedDirectories);
      hosts.push_back(vh);
    }
  };
  Config::Iterate(cb, ini, hdf, "VirtualHost");

  for (auto& host : hosts) {
    VirtualHost::SetCurrent(&host);
    auto name = host.getName();
    if (name == "flibtest") {
      VERIFY(host.getPathTranslation() == "flib/_bin/"); // the / is added
      VERIFY(host.getDocumentRoot() ==
             RuntimeOption::SourceRoot + "flib/_bin");
      VERIFY(host.getServerVars().size() == 0);
      VERIFY(VirtualHost::GetAllowedDirectories().size() == 2);
      VERIFY(host.valid() == true);
      VERIFY(host.hasLogFilter() == false);
    } else if (name == "upload") {
      VERIFY(host.getPathTranslation() == "html/"); // the / is added
      VERIFY(host.getDocumentRoot() ==
             RuntimeOption::SourceRoot + "html");
      // SortALlowedDirectories might add something and remove
      // duplicates. In this case, /var/releases/continuous_www_scripts4
      // was added and the duplicate /var/www was removed.s
      VERIFY(VirtualHost::GetAllowedDirectories().size() == 6);
      VERIFY(host.valid() == true);
      VERIFY(host.hasLogFilter() == false);
      VERIFY(VirtualHost::GetMaxPostSize() == 104857600);
    }
  }

  VERIFY(VirtualHost::GetDefault().getPathTranslation() == "htm/");
  VERIFY(VirtualHost::GetDefault().hasLogFilter() == true);
  String rw("/html/common/");
  String h("default");
  bool q = false;
  int rd = 0;
  VirtualHost::GetDefault().rewriteURL(h, rw, q, rd);
  VERIFY(rw.toCppString() == "http://3v4l.org");
  VERIFY(rd == 301);
  return Count(true);
}
Пример #10
0
int prepareOptions(ProgramOptions &po, int argc, char **argv) {
  options_description desc("HipHop Compiler for PHP Usage:\n\n"
                           "\thphp <options> <inputs>\n\n"
                           "Options");
  desc.add_options()
    ("help", "display this message")
    ("version", "display version number")
    ("target,t", value<string>(&po.target)->default_value("run"),
     "lint | "
     "analyze | "
     "php | "
     "cpp | "
     "sep-ext-cpp | "
     "filecache | "
     "run (default)")
    ("format,f", value<string>(&po.format),
     "lint: (none); \n"
     "analyze: (none); \n"
     "php: trimmed (default) | inlined | pickled | typeinfo |"
     " <any combination of them by any separator>; \n"
     "cpp: cluster (default) | file | sys | exe | lib; \n"
     "run: cluster (default) | file")
    ("cluster-count", value<int>(&po.clusterCount)->default_value(0),
     "Cluster by file sizes and output roughly these many number of files. "
     "Use 0 for no clustering.")
    ("input-dir", value<string>(&po.inputDir), "input directory")
    ("program", value<string>(&po.program)->default_value("program"),
     "final program name to use")
    ("args", value<string>(&po.programArgs), "program arguments")
    ("inputs,i", value<vector<string> >(&po.inputs), "input file names")
    ("input-list", value<string>(&po.inputList),
     "file containing list of file names, one per line")
    ("include-path",
     value<vector<string> >(&Option::IncludeSearchPaths)->composing(),
     "a list of include paths to search for files being included in includes "
     "or requires but cannot be found assuming relative paths")
    ("module", value<vector<string> >(&po.modules)->composing(),
     "directories containing all input files")
    ("exclude-dir", value<vector<string> >(&po.excludeDirs)->composing(),
     "directories to exclude from the input")
    ("fmodule", value<vector<string> >(&po.fmodules)->composing(),
     "same with module, except no exclusion checking is performed, so these "
     "modules are forced to be included")
    ("ffile", value<vector<string> >(&po.ffiles)->composing(),
     "extra PHP files forced to include without exclusion checking")
    ("exclude-file", value<vector<string> >(&po.excludeFiles)->composing(),
     "files to exclude from the input, even if parse-on-demand finds it")
    ("exclude-pattern",
     value<vector<string> >(&po.excludePatterns)->composing(),
     "regex (in 'find' command's regex command line option format) of files "
     "or directories to exclude from the input, even if parse-on-demand finds "
     "it")
    ("exclude-static-pattern",
     value<vector<string> >(&po.excludeStaticPatterns)->composing(),
     "regex (in 'find' command's regex command line option format) of files "
     "or directories to exclude from static content cache")
    ("exclude-static-dir",
     value<vector<string> >(&po.excludeStaticDirs)->composing(),
     "directories to exclude from static content cache")
    ("exclude-static-file",
     value<vector<string> >(&po.excludeStaticFiles)->composing(),
     "files to exclude from static content cache")
    ("cfile", value<vector<string> >(&po.cfiles)->composing(),
     "extra static files forced to include without exclusion checking")
    ("cmodule", value<vector<string> >(&po.cmodules)->composing(),
     "extra directories for static files without exclusion checking")
    ("parse-on-demand", value<bool>(&po.parseOnDemand)->default_value(true),
     "whether to parse files that are not specified from command line")
    ("branch", value<string>(&po.branch), "SVN branch")
    ("revision", value<int>(&po.revision), "SVN revision")
    ("output-dir,o", value<string>(&po.outputDir), "output directory")
    ("output-file", value<string>(&po.outputFile), "output file")
    ("sync-dir", value<string>(&po.syncDir),
     "Files will be created in this directory first, then sync with output "
     "directory without overwriting identical files. Great for incremental "
     "compilation and build.")
    ("optimize-level", value<int>(&po.optimizeLevel)->default_value(1),
     "optimization level")
    ("gen-stats", value<bool>(&po.genStats)->default_value(false),
     "whether to generate code errors")
    ("keep-tempdir,k", value<bool>(&po.keepTempDir)->default_value(false),
     "whether to keep the temporary directory")
    ("db-stats", value<string>(&po.dbStats),
     "database connection string to save code errors: "
     "<username>:<password>@<host>:<port>/<db>")
    ("no-type-inference",
     value<bool>(&po.noTypeInference)->default_value(false),
     "turn off type inference for C++ code generation")
    ("no-min-include",
     value<bool>(&po.noMinInclude)->default_value(false),
     "turn off minimium include analysis when target is \"analyze\"")
    ("no-meta-info",
     value<bool>(&po.noMetaInfo)->default_value(false),
     "do not generate class map, function jump table and macros "
     "when generating code; good for demo purposes")
    ("config,c", value<vector<string> >(&po.config)->composing(),
     "config file name")
    ("config-dir", value<string>(&po.configDir),
     "root directory configuration is based on (for example, "
     "excluded directories may be relative path in configuration.")
    ("config-value,v", value<vector<string> >(&po.confStrings)->composing(),
     "individual configuration string in a format of name=value, where "
     "name can be any valid configuration for a config file")
    ("log,l",
     value<int>(&po.logLevel)->default_value(-1),
     "-1: (default); 0: no logging; 1: errors only; 2: warnings and errors; "
     "3: informational as well; 4: really verbose.")
    ("force",
     value<bool>(&po.force)->default_value(true),
     "force to ignore code generation errors and continue compilations")
    ("file-cache",
     value<string>(&po.filecache),
     "if specified, generate a static file cache with this file name")
    ("rtti-directory", value<string>(&po.rttiDirectory)->default_value(""),
     "the directory of rtti profiling data")
    ("java-root",
     value<string>(&po.javaRoot)->default_value("php"),
     "the root package of generated Java FFI classes")
    ("generate-ffi",
     value<bool>(&po.generateFFI)->default_value(false),
     "generate ffi stubs")
    ("dump",
     value<bool>(&po.dump)->default_value(false),
     "dump the program graph")
    ("coredump",
     value<bool>(&po.coredump)->default_value(false),
     "turn on coredump")
    ("nofork",
     value<bool>(&po.nofork)->default_value(false),
     "forking is needed for large compilation to release memory before g++"
     "compilation. turning off forking can help gdb debugging.")
    ("fl-annotate",
     value<bool>(&po.fl_annotate)->default_value(false),
     "Annote emitted source with compiler file-line info")
    ("opts",
     value<string>(&po.optimizations)->default_value("none"),
     "Set optimizations to enable/disable")
    ("ppp",
     value<string>(&po.ppp)->default_value(""),
     "Preprocessed partition configuration. To speed up distcc compilation, "
     "bin/ppp.php can pre-compute better partition between different .cpp "
     "files according to preprocessed file sizes, instead of original file "
     "sizes (default). Run bin/ppp.php to generate an HDF configuration file "
     "to specify here.")
    ;

  positional_options_description p;
  p.add("inputs", -1);
  variables_map vm;
  try {
    store(command_line_parser(argc, argv).options(desc).positional(p).run(),
          vm);
    notify(vm);
  } catch (unknown_option e) {
    cerr << "Error in command line: " << e.what() << "\n\n";
    cout << desc << "\n";
    return -1;
  }
  if (argc <= 1 || vm.count("help")) {
    cout << desc << "\n";
    return 1;
  }
  if (vm.count("version")) {
#ifdef HPHP_VERSION
#undefine HPHP_VERSION
#endif
#define HPHP_VERSION(v) cout << "HipHop Compiler v" #v << "\n";
#include "../version"
    return 1;
  }

  // log level
  if (po.logLevel != -1) {
    Logger::LogLevel = (Logger::LogLevelType)po.logLevel;
  } else if (po.target == "run") {
    Logger::LogLevel = Logger::LogNone;
  } else {
    Logger::LogLevel = Logger::LogInfo;
  }

  // config and system
  Option::GenerateCPPMain = true;
  if (po.noMetaInfo) {
    Option::GenerateCPPMetaInfo = false;
    Option::GenerateCPPMacros = false;
  }
  Option::FlAnnotate = po.fl_annotate;

  Hdf config;
  for (vector<string>::const_iterator it = po.config.begin();
       it != po.config.end(); ++it) {
    config.append(*it);
  }
  for (unsigned int i = 0; i < po.confStrings.size(); i++) {
    config.fromString(po.confStrings[i].c_str());
  }
  Option::Load(config);
  vector<string> badnodes;
  config.lint(badnodes);
  for (unsigned int i = 0; i < badnodes.size(); i++) {
    Logger::Error("Possible bad config node: %s", badnodes[i].c_str());
  }

  if (po.inputDir.empty()) {
    po.inputDir = '.';
  }
  po.inputDir = Util::normalizeDir(po.inputDir);
  if (po.configDir.empty()) {
    po.configDir = po.inputDir;
  }
  po.configDir = Util::normalizeDir(po.configDir);
  Option::RootDirectory = po.configDir;

  for (unsigned int i = 0; i < po.excludeDirs.size(); i++) {
    Option::PackageExcludeDirs.insert
      (Util::normalizeDir(po.excludeDirs[i]));
  }
  for (unsigned int i = 0; i < po.excludeFiles.size(); i++) {
    Option::PackageExcludeFiles.insert(po.excludeFiles[i]);
  }
  for (unsigned int i = 0; i < po.excludePatterns.size(); i++) {
    Option::PackageExcludePatterns.insert
      (Util::format_pattern(po.excludePatterns[i], true));
  }
  for (unsigned int i = 0; i < po.excludeStaticDirs.size(); i++) {
    Option::PackageExcludeStaticDirs.insert
      (Util::normalizeDir(po.excludeStaticDirs[i]));
  }
  for (unsigned int i = 0; i < po.excludeStaticFiles.size(); i++) {
    Option::PackageExcludeStaticFiles.insert(po.excludeStaticFiles[i]);
  }
  for (unsigned int i = 0; i < po.excludeStaticPatterns.size(); i++) {
    Option::PackageExcludeStaticPatterns.insert
      (Util::format_pattern(po.excludeStaticPatterns[i], true));
  }

  if (po.target == "cpp" && po.format == "sys") {
    BuiltinSymbols::NoSuperGlobals = true; // so to generate super globals
    Option::AnalyzePerfectVirtuals = false;
  }
  Option::SystemGen = (po.target == "cpp" && po.format == "sys") ;

  Option::ProgramName = po.program;
  Option::PreprocessedPartitionConfig = po.ppp;

  if (po.target == "cpp") {
    if (po.format.empty()) po.format = "cluster";
  } else if (po.target == "php") {
    if (po.format.empty()) po.format = "trimmed";
  } else if (po.target == "run") {
    if (po.format.empty()) po.format = "cluster";
  }

  if (po.optimizeLevel > 0) {
    Option::PreOptimization = true;
    Option::PostOptimization = true;
  }

  if (po.generateFFI) {
    Option::GenerateFFI = true;
    Option::JavaFFIRootPackage = po.javaRoot;
  }

  return 0;
}