/* ZazouMiniWebServer Copyright (C) 2003-2011 Xavier Garreau This file is part of ZazouMiniWebServer. ZazouMiniWebServer is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. ZazouMiniWebServer 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 General Public License for more details. You should have received a copy of the GNU General Public License along with ZazouMiniWebServer; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ // ZMWSConfig.cpp: implementation of the ZMWSConfig class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "ZMWSConfig.h" #include "ZMWSFileUtils.h" #include "ZMWSCommon.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// void ZMWSConfig::GetCBaseConfig(CBaseZMWSConfig* conf) const { (*conf).bindAddr = strdup(bindAddr.c_str()); (*conf).documentRoot = strdup(documentRoot.c_str()); (*conf).serverRoot = strdup(serverRoot.c_str()); (*conf).logsDir = strdup(logsDir.c_str()); (*conf).pathToConfigFile = strdup(pathToConfigFile.c_str()); (*conf).pathToPHP = strdup(pathToPHP.c_str()); (*conf).browserCmd = strdup(browserCmd.c_str()); (*conf).defCharSet = strdup(defCharSet.c_str()); (*conf).startPages = strdup(startPages.c_str()); (*conf).allowFrom = strdup(allowFrom.c_str()); (*conf).denyFrom = strdup(denyFrom.c_str()); (*conf).port = port; (*conf).sport = sport; (*conf).maxClients = maxClients; (*conf).hideConsole = hideConsole; (*conf).try808xPorts = try808xPorts; (*conf).canIndex = canIndex; (*conf).beQuiet = beQuiet; (*conf).canStop = canStop; (*conf).closeBrowser = closeBrowser; (*conf).reverseDNS = reverseDNS; (*conf).writeLogs = writeLogs; (*conf).browseNow = browseNow; (*conf).dropClients = dropClients; (*conf).pbtoken = pbtoken; } void ZMWSConfig::FreeCBaseConfig(CBaseZMWSConfig* conf) const { free ((*conf).bindAddr); free ((*conf).documentRoot); free ((*conf).serverRoot); free ((*conf).logsDir); free ((*conf).pathToConfigFile); free ((*conf).pathToPHP); free ((*conf).browserCmd); free ((*conf).defCharSet); free ((*conf).startPages); free ((*conf).allowFrom); free ((*conf).denyFrom); } ZMWSConfig::ZMWSConfig(const int& p, const int& httpsp, const std::string& dr, const std::string& ld, const std::string& ptp, const std::string& bc, const std::string& sp, const std::string& af, const std::string& df, const pbtoken_type pbt, const DWORD& mc, const BOOL& wl, const BOOL& hc, const BOOL& tp, const BOOL& rv, const BOOL& ci, const BOOL& bq, const BOOL& cs, const BOOL& cb, const BOOL& bn, const BOOL& dc ) { char exeFilename[MAX_PATH]; std::string exePath; std::string::size_type lastSlashPos; // On se place dans le répertoire de l'exécutable GetModuleFileName(NULL,exeFilename,sizeof(exeFilename)); exePath = exeFilename; lastSlashPos = exePath.find_last_of("/\\"); exePath.erase(lastSlashPos); SetCurrentDirectory(exePath.c_str()); this->port = p; this->sport = httpsp; this->documentRoot = dr; this->writeLogs = wl; this->logsDir = dr+ld; this->pathToPHP = ptp; this->browserCmd = bc; this->startPages = sp; this->allowFrom = af; this->denyFrom = af; this->pbtoken = pbt; this->maxClients = mc; this->hideConsole = hc; this->try808xPorts = tp; this->reverseDNS = rv; this->canIndex = ci; this->beQuiet = bq; this->canStop = cs; this->closeBrowser = cb; this->browseNow = bn; this->dropClients = dc; ConfFeatures = 0; pathToConfigFile = "_config.zmwsc"; // Reset config parts this->DirAliases.clear(); this->Handlers.clear(); this->PerUrlConfigs.clear(); this->VHostsAliases.clear(); this->VHostsConfig.clear(); /* Can we load openssl dlls ? */ /* If no, disable https */ HMODULE Hlib = LoadLibrary("libeay32.dll"); if (!Hlib) { this->sport = 0; } else { FreeLibrary (Hlib); } HMODULE Hssl = LoadLibrary("ssleay32.dll"); if (!Hssl) { this->sport = 0; } else { FreeLibrary (Hssl); } /* Get the serverRoot */ LPTSTR CurDir = NULL; DWORD szCurDir = 0; if (szCurDir = GetCurrentDirectory(szCurDir, CurDir)) { CurDir = (LPTSTR)malloc(szCurDir); szCurDir = GetCurrentDirectory(szCurDir, CurDir); } if (CurDir) { int cdtaille = strlen(CurDir); if (CurDir[cdtaille-1]== '\\') { CurDir[cdtaille-1] = '\0'; } this->serverRoot = CurDir; free (CurDir); } /* set documentRoot to current directory if dr is empty */ if (!dr.length()) { ZMWSFileUtils zfu; zfu.getFile(serverRoot + "\\_web.zmwsc"); if ( zfu.fileExists() && zfu.isDir()) { documentRoot = serverRoot + "\\_web.zmwsc"; } else { documentRoot = serverRoot; } } /* Try to find php */ BYTE phpOK = 0; if (!phpOK) { if ( ! ZMWSFileUtils::fileExists((pathToPHP+".exe").c_str())) { pathToPHP = ""; } else { phpOK = 1; } } if (!phpOK) { pathToPHP = "php\\php-cgi"; if ( ! ZMWSFileUtils::fileExists((pathToPHP+".exe").c_str())) { pathToPHP = ""; } else { phpOK = 1; } } if (!phpOK) { pathToPHP = "c:\\php\\php-cgi"; if ( ! ZMWSFileUtils::fileExists((pathToPHP+".exe").c_str())) { pathToPHP = ""; } else { phpOK = 1; } } if (!phpOK) { pathToPHP = "c:\\php4\\php-cgi"; if ( ! ZMWSFileUtils::fileExists((pathToPHP+".exe").c_str())) { pathToPHP = ""; } else { phpOK = 1; } } if (!phpOK) { pathToPHP = "c:\\php5\\php-cgi"; if ( ! ZMWSFileUtils::fileExists((pathToPHP+".exe").c_str())) { pathToPHP = ""; } else { phpOK = 1; } } if (!phpOK) { pathToPHP = "php5\\php"; if ( ! ZMWSFileUtils::fileExists((pathToPHP+".exe").c_str())) { pathToPHP = ""; } else { phpOK = 1; } } if (!phpOK) { pathToPHP = "php\\php"; if ( ! ZMWSFileUtils::fileExists((pathToPHP+".exe").c_str())) { pathToPHP = ""; } else { phpOK = 1; } } if (!phpOK) { pathToPHP = "c:\\php\\php"; if ( ! ZMWSFileUtils::fileExists((pathToPHP+".exe").c_str())) { pathToPHP = ""; } else { phpOK = 1; } } if (!phpOK) { pathToPHP = "c:\\php4\\php"; if ( ! ZMWSFileUtils::fileExists((pathToPHP+".exe").c_str())) { pathToPHP = ""; } else { phpOK = 1; } } /* Can send directories listing if there's no index.* ? */ canIndex = ! ZMWSFileUtils::fileExists("_noIndex.zmwsc"); /* Hide Console ? */ hideConsole = ZMWSFileUtils::fileExists("_hideConsole.zmwsc"); } ZMWSConfig::~ZMWSConfig() { } BOOL ZMWSConfig::SetPathToConfigFile(const std::string& path) { std::string tmpPath = path; BOOL result = ZMWSFileUtils::normalizePath(tmpPath); if (result) { pathToConfigFile = tmpPath; } return result; } BOOL ZMWSConfig::SetPathToPHP(const std::string& path) { std::string tmpPath = path + "\\php-cgi.exe"; ZMWSFileUtils::normalizePath(tmpPath); BOOL result = ZMWSFileUtils::fileExists(tmpPath.c_str()); if (result) { pathToPHP = tmpPath; return result; } tmpPath = path+"\\php.exe"; ZMWSFileUtils::normalizePath(tmpPath); result = ZMWSFileUtils::fileExists(tmpPath.c_str()); if (result) { pathToPHP = tmpPath; return result; } tmpPath = path + ".exe"; ZMWSFileUtils::normalizePath(tmpPath); result = ZMWSFileUtils::fileExists(tmpPath.c_str()); if (result) { pathToPHP = tmpPath; return result; } tmpPath = path; ZMWSFileUtils::normalizePath(tmpPath); result = ZMWSFileUtils::fileExists(tmpPath.c_str()); if (result) { pathToPHP = tmpPath; return result; } return result; } BOOL ZMWSConfig::SetLogsDir(const std::string& ld, const std::string& vhost) { if (!GetWriteLogs()) return TRUE; BOOL result = TRUE; std::string tmpLogsDir, tmpLogFileName; if (ld.find(':') != std::string::npos || ld.at(0) == '\\' || ld.at(0) == '/') { // Absolute path tmpLogsDir = ld; } else { // Relative path tmpLogsDir = serverRoot + "\\" + ld; } ZMWSFileUtils::normalizePath(tmpLogsDir); /* Try to Create logs dir */ if (!CreateDirectory(tmpLogsDir.c_str(), NULL)) { DWORD ErrCode = GetLastError(); if (ErrCode != ERROR_ALREADY_EXISTS) { tmpLogFileName = tmpLogsDir+"\\access_log"; if (vhost.length()) { tmpLogFileName += "_" + vhost; } ZMWSFileUtils::normalizePath(tmpLogFileName); std::ofstream logFile (tmpLogFileName.c_str(), std::ios::ate); if (!logFile) { SetWriteLogs(false); result = FALSE; logsDir = ""; } else { logFile.close(); } } } if (!vhost.length()) { logsDir = tmpLogsDir; } else { VHostsConfig[vhost].logsDir = tmpLogsDir; } return result; } BOOL ZMWSConfig::SetDocumentRoot(const std::string& dr, const std::string& vhost) { BOOL result = TRUE; std::string tmpDocRoot; tmpDocRoot = dr; while ((tmpDocRoot.length() > 1) && (tmpDocRoot[tmpDocRoot.length()-1]=='/' || tmpDocRoot[tmpDocRoot.length()-1]=='\\') ) { tmpDocRoot = tmpDocRoot.substr(0, tmpDocRoot.length()-1); } if (tmpDocRoot.find(':') == std::string::npos && tmpDocRoot.at(0) != '\\' && tmpDocRoot.at(0) != '/') { // Relative path tmpDocRoot = serverRoot + "\\" + tmpDocRoot; } ZMWSFileUtils::normalizePath(tmpDocRoot); if (!vhost.length()) documentRoot = tmpDocRoot; else VHostsConfig[vhost].documentRoot = tmpDocRoot; return result; } BOOL ZMWSConfig::AddDirAlias(const std::string& alias, const std::string& real, const std::string& vhost) { BOOL isVHost = FALSE; std::string realpath; ZMWSVHostConfig vhc; if (vhost.length()) { isVHost = this->GetVHostConfig(vhost, vhc); if (!isVHost) { return FALSE; } } // Si c'est un chemin absolu on le stocke tel quel if (real.at(1)==':' || real.at(0) == '\\') { realpath = real; } else { if (real.at(0) == '/') { // Si le chemin commence par un / // il est relatif au docRoot if (isVHost) { realpath = vhc.documentRoot; } else { realpath = this->documentRoot; } } else { // Si le chemin ne commence pas par un / // il est relatif au serverRoot realpath = this->serverRoot + '\\'; } realpath += real; } ZMWSFileUtils::normalizePath(realpath); if (isVHost) { vhc.DirAliases.push_back(DirAliasType(alias, realpath)); SetVHostConfig(vhc.domain, vhc); } else { DirAliases.push_back(DirAliasType(alias, realpath)); } return TRUE; } std::string ZMWSConfig::GetAliasedDir(const std::string& alias, std::string& AliasedReqRootDir, const std::string& vhost) { DirAliasesTypeIterator it; std::string result = ""; int score = 0; // nombre de caract�es en commun if (vhost.length()) { ZMWSVHostConfig vhc; if (GetVHostConfig(vhost, vhc)) { for (it = vhc.DirAliases.begin(); it != vhc.DirAliases.end(); ++it) { if (0 == alias.compare(0, it->first.length(), it->first)) { if (score < it->first.length()) { score = it->first.length(); result = it->second+alias.substr(score); AliasedReqRootDir = it->second; } } } } } for (it = DirAliases.begin(); it != DirAliases.end(); ++it) { if (0 == alias.compare(0, it->first.length(), it->first)) { if (score < it->first.length()) { score = it->first.length(); result = it->second+alias.substr(score); AliasedReqRootDir = it->second; } } } int next_path_pos = result.find_first_of("/\\", AliasedReqRootDir.length()-2); if (next_path_pos != std::string::npos) { AliasedReqRootDir = result.substr(0, next_path_pos+1); } return result; } BOOL ZMWSConfig::GetVHostConfig(const std::string& VHostName, ZMWSVHostConfig& vhc) { BOOL VHostExists = false; std::string tmpHostName; if (VHostsAliases.find(VHostName) != VHostsAliases.end()) tmpHostName = VHostsAliases[VHostName]; else tmpHostName = VHostName; if (VHostsConfig.find(tmpHostName) != VHostsConfig.end()) { vhc = VHostsConfig[tmpHostName]; VHostExists = true; } return VHostExists; } BOOL ZMWSConfig::SetVHostConfig(const std::string& VHostName, const ZMWSVHostConfig& vhc) { BOOL VHostExists = false; std::string tmpHostName; if (VHostsAliases.find(VHostName) != VHostsAliases.end()) tmpHostName = VHostsAliases[VHostName]; else tmpHostName = VHostName; if (VHostsConfig.find(tmpHostName) != VHostsConfig.end()) { VHostsConfig[tmpHostName] = vhc; VHostExists = true; } return VHostExists; } void ZMWSConfig::ConfigureVHosts() { ZMWSFileUtils zfu; if (!zfu.getFile(documentRoot + "\\_vhosts.zmwsc\\*")) return; do { if (zfu.isDir() && (zfu.getFileName()!=".") && (zfu.getFileName()!="..")) { CreateDefaultVHost(zfu.getFileName()); } } while (zfu.getNextFile()); } BOOL ZMWSConfig::CreateDefaultVHost (const std::string& domainName) { ZMWSVHostConfig vhc, vhc2; vhc.canIndex = this->canIndex; vhc.reverseDNS = true; vhc.allowFrom = ""; vhc.denyFrom = ""; vhc.domain = domainName; vhc.documentRoot = documentRoot + "\\_vhosts.zmwsc\\" + vhc.domain; vhc.logsDir = logsDir; vhc.maxKBytes = 0; vhc.maxKBytesDTime = 0; if (!GetVHostConfig(vhc.domain, vhc2)) { VHostsConfig[vhc.domain] = vhc; print_dbg (("Created VHost : "+vhc.domain+"\n").c_str()); } return TRUE; } std::string ZMWSConfig::GetDomainForVHostAlias(const std::string& alias) { std::string tmpHostName = ""; if (VHostsAliases.find(alias) != VHostsAliases.end()) { tmpHostName = VHostsAliases[alias]; } else { if (VHostsConfig.find(alias) != VHostsConfig.end()) { tmpHostName = alias; } } return tmpHostName; } void ZMWSConfig::AddVHostAlias(const std::string& alias, const std::string& domain) { VHostsAliases[alias] = domain; } ZMWSHandler ZMWSConfig::GetHandler(const std::string& extension, const std::string& vhost) { ZMWSHandler tmpHandler; if (vhost.length()) { ZMWSVHostConfig vhc; if (GetVHostConfig(vhost, vhc)) { HandlersType::const_iterator it = vhc.Handlers.find(extension); if (it != vhc.Handlers.end()) { tmpHandler = it->second; return tmpHandler; } } } HandlersType::const_iterator it = Handlers.find(extension); if (it != Handlers.end()) { tmpHandler = it->second; } return tmpHandler; } void ZMWSConfig::AddHandler(const std::string& extension, const ZMWSHandler& handler, const std::string& vhost) { ZMWSHandler theHandler = handler; // if (handler.handlerPath.length()) { // if (handler.handlerPath.find(":") != 1 && handler.handlerPath.at(0) != '\\' && handler.handlerPath.at(0) != '/') { // theHandler.handlerPath = serverRoot + '\\' + handler.handlerPath; // } // } // Don't normalize HandlerPaths because, these are command lines not paths // eg for .bat cmd /c, we don't want it to become cmd \c do we ? :p // ZMWSFileUtils::normalizePath(theHandler.handlerPath); if (vhost.length()) { ZMWSVHostConfig vhc; if (GetVHostConfig(vhost, vhc)) { vhc.Handlers[extension] = theHandler; SetVHostConfig(vhc.domain, vhc); } } else { Handlers[extension] = theHandler; } } BOOL ZMWSConfig::GetPerUrlConfig(const std::string& url, ZMWSPerUrlConfig& puc, const BOOL& exact) { PerUrlConfigsTypeIterator it; int score = 0; for (it = PerUrlConfigs.begin(); it != PerUrlConfigs.end(); ++it) { if (exact) { if (url == it->first) { puc = it->second; return TRUE; } } else { if (0 == url.compare(0, it->first.length(), it->first)) { if (score < it->first.length()) { score = it->first.length(); puc = it->second; } } } } return score; } BOOL ZMWSConfig::SetPerUrlConfig(const std::string& url, const ZMWSPerUrlConfig& puc) { PerUrlConfigsTypeIterator it; for (it = PerUrlConfigs.begin(); it != PerUrlConfigs.end(); ++it) { if (0 == url.compare(0, it->first.length(), it->first)) { it->second = puc; return TRUE; } } PerUrlConfigs.push_back(PerUrlConfigType(url, puc)); return FALSE; } BOOL ZMWSConfig::SetDefaultCharset(const std::string& cs, const std::string& vhost) { if (!vhost.length()) defCharSet = cs; else VHostsConfig[vhost].defCharSet = cs; return TRUE; } BOOL ZMWSConfig::SetAllowFrom(const std::string& af, const std::string& vhost) { if (!vhost.length()) allowFrom = af; else VHostsConfig[vhost].allowFrom = af; return TRUE; } BOOL ZMWSConfig::SetDenyFrom(const std::string& df, const std::string& vhost) { if (!vhost.length()) denyFrom = df; else VHostsConfig[vhost].denyFrom = df; return TRUE; } BOOL ZMWSPerUrlConfig::AddHandler (const std::string& extension, const ZMWSHandler& handler) { ZMWSHandler theHandler = handler; // if (handler.handlerPath.length()) { // if (handler.handlerPath.find(":")==1 && handler.handlerPath.at(0) != '\\' && handler.handlerPath.at(0) != '/' ) { // theHandler.handlerPath = serverRoot + '\\' + handler.handlerPath; // } // } // Don't normalize handler paths // ZMWSFileUtils::normalizePath(theHandler.handlerPath); Handlers[extension] = theHandler; return true; } ZMWSHandler ZMWSPerUrlConfig::GetHandler(const std::string& extension) const { ZMWSHandler tmpHandler; HandlersType::const_iterator it = Handlers.find(extension); if (it != Handlers.end()) { tmpHandler = it->second; } return tmpHandler; }