00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef _PASSENGER_DIRECTORY_MAPPER_H_
00026 #define _PASSENGER_DIRECTORY_MAPPER_H_
00027
00028 #include <string>
00029 #include <set>
00030 #include <cstring>
00031
00032 #include <oxt/backtrace.hpp>
00033
00034 #include "CachedFileStat.hpp"
00035 #include "Configuration.h"
00036 #include "Utils.h"
00037
00038
00039
00040 #include <httpd.h>
00041 #include <http_core.h>
00042
00043 namespace Passenger {
00044
00045 using namespace std;
00046 using namespace oxt;
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 class DirectoryMapper {
00058 public:
00059 enum ApplicationType {
00060 NONE,
00061 RAILS,
00062 RACK,
00063 WSGI
00064 };
00065
00066 private:
00067 DirConfig *config;
00068 request_rec *r;
00069 CachedFileStat *cstat;
00070 unsigned int throttleRate;
00071 bool baseURIKnown;
00072 const char *baseURI;
00073 ApplicationType appType;
00074
00075 inline bool shouldAutoDetectRails() {
00076 return config->autoDetectRails == DirConfig::ENABLED ||
00077 config->autoDetectRails == DirConfig::UNSET;
00078 }
00079
00080 inline bool shouldAutoDetectRack() {
00081 return config->autoDetectRack == DirConfig::ENABLED ||
00082 config->autoDetectRack == DirConfig::UNSET;
00083 }
00084
00085 inline bool shouldAutoDetectWSGI() {
00086 return config->autoDetectWSGI == DirConfig::ENABLED ||
00087 config->autoDetectWSGI == DirConfig::UNSET;
00088 }
00089
00090 public:
00091
00092
00093
00094
00095
00096
00097
00098
00099 DirectoryMapper(request_rec *r, DirConfig *config,
00100 CachedFileStat *cstat, unsigned int throttleRate) {
00101 this->r = r;
00102 this->config = config;
00103 this->cstat = cstat;
00104 this->throttleRate = throttleRate;
00105 appType = NONE;
00106 baseURIKnown = false;
00107 baseURI = NULL;
00108 }
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 const char *getBaseURI() {
00128 TRACE_POINT();
00129 if (baseURIKnown) {
00130 return baseURI;
00131 }
00132
00133 set<string>::const_iterator it;
00134 const char *uri = r->uri;
00135 size_t uri_len = strlen(uri);
00136
00137 if (uri_len == 0 || uri[0] != '/') {
00138 baseURIKnown = true;
00139 return NULL;
00140 }
00141
00142 UPDATE_TRACE_POINT();
00143 for (it = config->railsBaseURIs.begin(); it != config->railsBaseURIs.end(); it++) {
00144 const string &base(*it);
00145 if ( base == "/"
00146 || ( uri_len == base.size() && memcmp(uri, base.c_str(), uri_len) == 0 )
00147 || ( uri_len > base.size() && memcmp(uri, base.c_str(), base.size()) == 0
00148 && uri[base.size()] == '/' )
00149 ) {
00150 baseURIKnown = true;
00151 baseURI = base.c_str();
00152 appType = RAILS;
00153 return baseURI;
00154 }
00155 }
00156
00157 UPDATE_TRACE_POINT();
00158 for (it = config->rackBaseURIs.begin(); it != config->rackBaseURIs.end(); it++) {
00159 const string &base(*it);
00160 if ( base == "/"
00161 || ( uri_len == base.size() && memcmp(uri, base.c_str(), uri_len) == 0 )
00162 || ( uri_len > base.size() && memcmp(uri, base.c_str(), base.size()) == 0
00163 && uri[base.size()] == '/' )
00164 ) {
00165 baseURIKnown = true;
00166 baseURI = base.c_str();
00167 appType = RACK;
00168 return baseURI;
00169 }
00170 }
00171
00172 UPDATE_TRACE_POINT();
00173 if (shouldAutoDetectRails()
00174 && verifyRailsDir(config->getAppRoot(ap_document_root(r)), cstat, throttleRate)) {
00175 baseURIKnown = true;
00176 baseURI = "/";
00177 appType = RAILS;
00178 return baseURI;
00179 }
00180
00181 UPDATE_TRACE_POINT();
00182 if (shouldAutoDetectRack()
00183 && verifyRackDir(config->getAppRoot(ap_document_root(r)), cstat, throttleRate)) {
00184 baseURIKnown = true;
00185 baseURI = "/";
00186 appType = RACK;
00187 return baseURI;
00188 }
00189
00190 UPDATE_TRACE_POINT();
00191 if (shouldAutoDetectWSGI()
00192 && verifyWSGIDir(config->getAppRoot(ap_document_root(r)), cstat, throttleRate)) {
00193 baseURIKnown = true;
00194 baseURI = "/";
00195 appType = WSGI;
00196 return baseURI;
00197 }
00198
00199 baseURIKnown = true;
00200 return NULL;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 string getPublicDirectory() {
00213 if (!baseURIKnown) {
00214 getBaseURI();
00215 }
00216 if (baseURI == NULL) {
00217 return "";
00218 }
00219
00220 const char *docRoot = ap_document_root(r);
00221 size_t len = strlen(docRoot);
00222 if (len > 0) {
00223 string path;
00224 if (docRoot[len - 1] == '/') {
00225 path.assign(docRoot, len - 1);
00226 } else {
00227 path.assign(docRoot, len);
00228 }
00229 if (strcmp(baseURI, "/") != 0) {
00230
00231
00232
00233 path.append(baseURI);
00234 path = resolveSymlink(path);
00235 }
00236 return path;
00237 } else {
00238 return "";
00239 }
00240 }
00241
00242
00243
00244
00245
00246
00247 ApplicationType getApplicationType() {
00248 if (!baseURIKnown) {
00249 getBaseURI();
00250 }
00251 return appType;
00252 }
00253
00254
00255
00256
00257
00258
00259
00260 const char *getApplicationTypeString() {
00261 if (!baseURIKnown) {
00262 getBaseURI();
00263 }
00264 switch (appType) {
00265 case RAILS:
00266 return "rails";
00267 case RACK:
00268 return "rack";
00269 case WSGI:
00270 return "wsgi";
00271 default:
00272 return NULL;
00273 };
00274 }
00275
00276
00277
00278
00279
00280
00281 const char *getEnvironment() {
00282 switch (getApplicationType()) {
00283 case RAILS:
00284 return config->getRailsEnv();
00285 case RACK:
00286 return config->getRackEnv();
00287 default:
00288 return "production";
00289 }
00290 }
00291 };
00292
00293 }
00294
00295 #endif
00296