passenger 4.0.3 → 4.0.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (46) hide show
  1. data.tar.gz.asc +7 -7
  2. data/NEWS +30 -0
  3. data/build/agents.rb +3 -0
  4. data/build/apache2.rb +2 -3
  5. data/build/basics.rb +20 -0
  6. data/build/common_library.rb +15 -0
  7. data/build/cxx_tests.rb +4 -1
  8. data/build/packaging.rb +22 -32
  9. data/doc/Packaging.html +792 -0
  10. data/doc/Users guide Nginx.html +2 -2
  11. data/doc/Users guide Nginx.txt +2 -2
  12. data/ext/apache2/Configuration.cpp +34 -62
  13. data/ext/apache2/Configuration.hpp +1 -14
  14. data/ext/apache2/DirectoryMapper.h +134 -104
  15. data/ext/apache2/Hooks.cpp +33 -19
  16. data/ext/common/AgentsStarter.cpp +22 -22
  17. data/ext/common/AgentsStarter.h +25 -25
  18. data/ext/common/ApplicationPool2/AppTypes.cpp +6 -6
  19. data/ext/common/ApplicationPool2/AppTypes.h +61 -9
  20. data/ext/common/ApplicationPool2/Implementation.cpp +14 -2
  21. data/ext/common/Constants.h +54 -23
  22. data/ext/common/Constants.h.erb +42 -0
  23. data/ext/common/ServerInstanceDir.h +6 -11
  24. data/ext/common/Utils/CachedFileStat.cpp +10 -9
  25. data/ext/common/Utils/CachedFileStat.h +8 -8
  26. data/ext/common/Utils/LargeFiles.cpp +12 -4
  27. data/ext/common/agents/HelperAgent/RequestHandler.h +1 -0
  28. data/ext/common/agents/Watchdog/Main.cpp +2 -2
  29. data/ext/nginx/Configuration.c +1 -1
  30. data/ext/nginx/Configuration.h +0 -1
  31. data/ext/nginx/ContentHandler.c +15 -15
  32. data/ext/nginx/ngx_http_passenger_module.c +48 -48
  33. data/ext/nginx/ngx_http_passenger_module.h +7 -9
  34. data/helper-scripts/wsgi-loader.py +2 -2
  35. data/lib/phusion_passenger.rb +1 -3
  36. data/lib/phusion_passenger/admin_tools/server_instance.rb +5 -11
  37. data/lib/phusion_passenger/constants.rb +42 -0
  38. data/lib/phusion_passenger/packaging.rb +8 -6
  39. data/lib/phusion_passenger/platform_info.rb +11 -6
  40. data/lib/phusion_passenger/standalone/command.rb +4 -2
  41. data/lib/phusion_passenger/standalone/runtime_installer.rb +1 -1
  42. data/resources/templates/standalone/config.erb +14 -2
  43. data/test/ruby/admin_tools_spec.rb +14 -16
  44. metadata +4 -3
  45. metadata.gz.asc +7 -7
  46. data/lib/phusion_passenger/wsgi/request_handler.py +0 -199
@@ -149,6 +149,24 @@ private:
149
149
  return OK;
150
150
  }
151
151
  };
152
+
153
+ class ReportDocumentRootDeterminationError: public ErrorReport {
154
+ private:
155
+ DocumentRootDeterminationError e;
156
+
157
+ public:
158
+ ReportDocumentRootDeterminationError(const DocumentRootDeterminationError &ex): e(ex) { }
159
+
160
+ int report(request_rec *r) {
161
+ r->status = 500;
162
+ ap_set_content_type(r, "text/html; charset=UTF-8");
163
+ ap_rputs("<h1>Passenger error #1</h1>\n", r);
164
+ ap_rputs("Cannot determine the document root for the current request.", r);
165
+ P_ERROR("Cannot determine the document root for the current request.\n" <<
166
+ " Backtrace:\n" << e.backtrace());
167
+ return OK;
168
+ }
169
+ };
152
170
 
153
171
  struct RequestNote {
154
172
  DirectoryMapper mapper;
@@ -313,13 +331,6 @@ private:
313
331
  return m_hasModXsendfile == YES;
314
332
  }
315
333
 
316
- int reportDocumentRootDeterminationError(request_rec *r) {
317
- ap_set_content_type(r, "text/html; charset=UTF-8");
318
- ap_rputs("<h1>Passenger error #1</h1>\n", r);
319
- ap_rputs("Cannot determine the document root for the current request.", r);
320
- return OK;
321
- }
322
-
323
334
  int reportBusyException(request_rec *r) {
324
335
  ap_custom_response(r, HTTP_SERVICE_UNAVAILABLE,
325
336
  "This website is too busy right now. Please try again later.");
@@ -352,11 +363,17 @@ private:
352
363
 
353
364
  DirectoryMapper mapper(r, config, &cstat, config->getStatThrottleRate());
354
365
  try {
355
- if (mapper.getBaseURI() == NULL) {
366
+ if (mapper.getApplicationType() == PAT_NONE) {
356
367
  // (B) is not true.
357
368
  disableRequestNote(r);
358
369
  return false;
359
370
  }
371
+ } catch (const DocumentRootDeterminationError &e) {
372
+ auto_ptr<RequestNote> note(new RequestNote(mapper, config));
373
+ note->errorReport = new ReportDocumentRootDeterminationError(e);
374
+ apr_pool_userdata_set(note.release(), "Phusion Passenger",
375
+ RequestNote::cleanup, r->pool);
376
+ return true;
360
377
  } catch (const FileSystemException &e) {
361
378
  /* DirectoryMapper tried to examine the filesystem in order
362
379
  * to autodetect the application type (e.g. by checking whether
@@ -482,14 +499,11 @@ private:
482
499
  TRACE_POINT();
483
500
  DirConfig *config = note->config;
484
501
  DirectoryMapper &mapper = note->mapper;
485
- string publicDirectory, appRoot;
486
502
 
487
503
  try {
488
- publicDirectory = mapper.getPublicDirectory();
489
- if (publicDirectory.empty()) {
490
- return reportDocumentRootDeterminationError(r);
491
- }
492
- appRoot = config->getAppRoot(publicDirectory.c_str());
504
+ mapper.getPublicDirectory();
505
+ } catch (const DocumentRootDeterminationError &e) {
506
+ return ReportDocumentRootDeterminationError(e).report(r);
493
507
  } catch (const FileSystemException &e) {
494
508
  /* The application root cannot be determined. This could
495
509
  * happen if, for example, the user specified 'RailsBaseURI /foo'
@@ -570,7 +584,7 @@ private:
570
584
  requestData.reserve(3);
571
585
  headerData.reserve(1024 * 2);
572
586
  requestData.push_back(StaticString());
573
- size = constructHeaders(r, config, requestData, mapper, appRoot, headerData);
587
+ size = constructHeaders(r, config, requestData, mapper, headerData);
574
588
  requestData.push_back(",");
575
589
 
576
590
  ret = snprintf(sizeString, sizeof(sizeString) - 1, "%u:", size);
@@ -857,7 +871,7 @@ private:
857
871
  }
858
872
 
859
873
  unsigned int constructHeaders(request_rec *r, DirConfig *config,
860
- vector<StaticString> &requestData, DirectoryMapper &mapper, const string &appRoot,
874
+ vector<StaticString> &requestData, DirectoryMapper &mapper,
861
875
  string &output)
862
876
  {
863
877
  const char *baseURI = mapper.getBaseURI();
@@ -920,7 +934,7 @@ private:
920
934
  addHeader(output, "REQUEST_URI", request_uri);
921
935
  }
922
936
 
923
- if (strcmp(baseURI, "/") == 0) {
937
+ if (baseURI == NULL) {
924
938
  addHeader(output, "SCRIPT_NAME", "");
925
939
  addHeader(output, "PATH_INFO", escapedUri);
926
940
  } else {
@@ -953,8 +967,8 @@ private:
953
967
 
954
968
  // Phusion Passenger options.
955
969
  addHeader(output, "PASSENGER_STATUS_LINE", "false");
956
- addHeader(output, "PASSENGER_APP_ROOT", appRoot);
957
- addHeader(output, "PASSENGER_APP_GROUP_NAME", config->getAppGroupName(appRoot));
970
+ addHeader(output, "PASSENGER_APP_ROOT", mapper.getAppRoot());
971
+ addHeader(output, "PASSENGER_APP_GROUP_NAME", config->getAppGroupName(mapper.getAppRoot()));
958
972
  addHeader(output, "PASSENGER_RUBY", config->ruby ? config->ruby : serverConfig.defaultRuby);
959
973
  addHeader(output, "PASSENGER_PYTHON", config->python);
960
974
  addHeader(output, "PASSENGER_ENV", config->getEnvironment());
@@ -33,13 +33,13 @@ using namespace boost;
33
33
  using namespace oxt;
34
34
 
35
35
 
36
- PSG_VariantMap *
37
- psg_variant_map_new() {
38
- return (PSG_VariantMap *) new Passenger::VariantMap();
36
+ PP_VariantMap *
37
+ pp_variant_map_new() {
38
+ return (PP_VariantMap *) new Passenger::VariantMap();
39
39
  }
40
40
 
41
41
  void
42
- psg_variant_map_set(PSG_VariantMap *m,
42
+ pp_variant_map_set(PP_VariantMap *m,
43
43
  const char *name,
44
44
  const char *value,
45
45
  unsigned int value_len)
@@ -49,7 +49,7 @@ psg_variant_map_set(PSG_VariantMap *m,
49
49
  }
50
50
 
51
51
  void
52
- psg_variant_map_set2(PSG_VariantMap *m,
52
+ pp_variant_map_set2(PP_VariantMap *m,
53
53
  const char *name,
54
54
  unsigned int name_len,
55
55
  const char *value,
@@ -60,7 +60,7 @@ psg_variant_map_set2(PSG_VariantMap *m,
60
60
  }
61
61
 
62
62
  void
63
- psg_variant_map_set_int(PSG_VariantMap *m,
63
+ pp_variant_map_set_int(PP_VariantMap *m,
64
64
  const char *name,
65
65
  int value)
66
66
  {
@@ -69,7 +69,7 @@ psg_variant_map_set_int(PSG_VariantMap *m,
69
69
  }
70
70
 
71
71
  void
72
- psg_variant_map_set_bool(PSG_VariantMap *m,
72
+ pp_variant_map_set_bool(PP_VariantMap *m,
73
73
  const char *name,
74
74
  int value)
75
75
  {
@@ -78,7 +78,7 @@ psg_variant_map_set_bool(PSG_VariantMap *m,
78
78
  }
79
79
 
80
80
  void
81
- psg_variant_map_set_strset(PSG_VariantMap *m,
81
+ pp_variant_map_set_strset(PP_VariantMap *m,
82
82
  const char *name,
83
83
  const char **strs,
84
84
  unsigned int count)
@@ -93,21 +93,21 @@ psg_variant_map_set_strset(PSG_VariantMap *m,
93
93
  }
94
94
 
95
95
  void
96
- psg_variant_map_free(PSG_VariantMap *m) {
96
+ pp_variant_map_free(PP_VariantMap *m) {
97
97
  delete (Passenger::VariantMap *) m;
98
98
  }
99
99
 
100
100
 
101
- PSG_AgentsStarter *
102
- psg_agents_starter_new(PSG_AgentsStarterType type, char **error_message) {
103
- return (PSG_AgentsStarter *) new Passenger::AgentsStarter(type);
101
+ PP_AgentsStarter *
102
+ pp_agents_starter_new(PP_AgentsStarterType type, char **error_message) {
103
+ return (PP_AgentsStarter *) new Passenger::AgentsStarter(type);
104
104
  }
105
105
 
106
106
  int
107
- psg_agents_starter_start(PSG_AgentsStarter *as,
107
+ pp_agents_starter_start(PP_AgentsStarter *as,
108
108
  const char *passengerRoot,
109
- PSG_VariantMap *extraParams,
110
- const PSG_AfterForkCallback afterFork,
109
+ PP_VariantMap *extraParams,
110
+ const PP_AfterForkCallback afterFork,
111
111
  void *callbackArgument,
112
112
  char **errorMessage)
113
113
  {
@@ -135,7 +135,7 @@ psg_agents_starter_start(PSG_AgentsStarter *as,
135
135
  }
136
136
 
137
137
  const char *
138
- psg_agents_starter_get_request_socket_filename(PSG_AgentsStarter *as, unsigned int *size) {
138
+ pp_agents_starter_get_request_socket_filename(PP_AgentsStarter *as, unsigned int *size) {
139
139
  Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
140
140
  if (size != NULL) {
141
141
  *size = agentsStarter->getRequestSocketFilename().size();
@@ -144,7 +144,7 @@ psg_agents_starter_get_request_socket_filename(PSG_AgentsStarter *as, unsigned i
144
144
  }
145
145
 
146
146
  const char *
147
- psg_agents_starter_get_request_socket_password(PSG_AgentsStarter *as, unsigned int *size) {
147
+ pp_agents_starter_get_request_socket_password(PP_AgentsStarter *as, unsigned int *size) {
148
148
  Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
149
149
  if (size != NULL) {
150
150
  *size = agentsStarter->getRequestSocketPassword().size();
@@ -153,31 +153,31 @@ psg_agents_starter_get_request_socket_password(PSG_AgentsStarter *as, unsigned i
153
153
  }
154
154
 
155
155
  const char *
156
- psg_agents_starter_get_server_instance_dir(PSG_AgentsStarter *as) {
156
+ pp_agents_starter_get_server_instance_dir(PP_AgentsStarter *as) {
157
157
  Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
158
158
  return agentsStarter->getServerInstanceDir()->getPath().c_str();
159
159
  }
160
160
 
161
161
  const char *
162
- psg_agents_starter_get_generation_dir(PSG_AgentsStarter *as) {
162
+ pp_agents_starter_get_generation_dir(PP_AgentsStarter *as) {
163
163
  Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
164
164
  return agentsStarter->getGeneration()->getPath().c_str();
165
165
  }
166
166
 
167
167
  pid_t
168
- psg_agents_starter_get_pid(PSG_AgentsStarter *as) {
168
+ pp_agents_starter_get_pid(PP_AgentsStarter *as) {
169
169
  Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
170
170
  return agentsStarter->getPid();
171
171
  }
172
172
 
173
173
  void
174
- psg_agents_starter_detach(PSG_AgentsStarter *as) {
174
+ pp_agents_starter_detach(PP_AgentsStarter *as) {
175
175
  Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
176
176
  agentsStarter->detach();
177
177
  }
178
178
 
179
179
  void
180
- psg_agents_starter_free(PSG_AgentsStarter *as) {
180
+ pp_agents_starter_free(PP_AgentsStarter *as) {
181
181
  Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
182
182
  delete agentsStarter;
183
183
  }
@@ -36,49 +36,49 @@
36
36
  typedef enum {
37
37
  AS_APACHE,
38
38
  AS_NGINX
39
- } PSG_AgentsStarterType;
39
+ } PP_AgentsStarterType;
40
40
 
41
- typedef void PSG_AgentsStarter;
42
- typedef void PSG_VariantMap;
43
- typedef void (*PSG_AfterForkCallback)(void *);
41
+ typedef void PP_AgentsStarter;
42
+ typedef void PP_VariantMap;
43
+ typedef void (*PP_AfterForkCallback)(void *);
44
44
 
45
- PSG_VariantMap *psg_variant_map_new();
46
- void psg_variant_map_set(PSG_VariantMap *m,
45
+ PP_VariantMap *pp_variant_map_new();
46
+ void pp_variant_map_set(PP_VariantMap *m,
47
47
  const char *name,
48
48
  const char *value,
49
49
  unsigned int value_len);
50
- void psg_variant_map_set2(PSG_VariantMap *m,
50
+ void pp_variant_map_set2(PP_VariantMap *m,
51
51
  const char *name,
52
52
  unsigned int name_len,
53
53
  const char *value,
54
54
  unsigned int value_len);
55
- void psg_variant_map_set_int(PSG_VariantMap *m,
55
+ void pp_variant_map_set_int(PP_VariantMap *m,
56
56
  const char *name,
57
57
  int value);
58
- void psg_variant_map_set_bool(PSG_VariantMap *m,
58
+ void pp_variant_map_set_bool(PP_VariantMap *m,
59
59
  const char *name,
60
60
  int value);
61
- void psg_variant_map_set_strset(PSG_VariantMap *m,
61
+ void pp_variant_map_set_strset(PP_VariantMap *m,
62
62
  const char *name,
63
63
  const char **strs,
64
64
  unsigned int count);
65
- void psg_variant_map_free(PSG_VariantMap *m);
65
+ void pp_variant_map_free(PP_VariantMap *m);
66
66
 
67
- PSG_AgentsStarter *psg_agents_starter_new(PSG_AgentsStarterType type,
67
+ PP_AgentsStarter *pp_agents_starter_new(PP_AgentsStarterType type,
68
68
  char **error_message);
69
- int psg_agents_starter_start(PSG_AgentsStarter *as,
69
+ int pp_agents_starter_start(PP_AgentsStarter *as,
70
70
  const char *passengerRoot,
71
- PSG_VariantMap *params,
72
- const PSG_AfterForkCallback afterFork,
71
+ PP_VariantMap *params,
72
+ const PP_AfterForkCallback afterFork,
73
73
  void *callbackArgument,
74
74
  char **errorMessage);
75
- const char *psg_agents_starter_get_request_socket_filename(PSG_AgentsStarter *as, unsigned int *size);
76
- const char *psg_agents_starter_get_request_socket_password(PSG_AgentsStarter *as, unsigned int *size);
77
- const char *psg_agents_starter_get_server_instance_dir(PSG_AgentsStarter *as);
78
- const char *psg_agents_starter_get_generation_dir(PSG_AgentsStarter *as);
79
- pid_t psg_agents_starter_get_pid(PSG_AgentsStarter *as);
80
- void psg_agents_starter_detach(PSG_AgentsStarter *as);
81
- void psg_agents_starter_free(PSG_AgentsStarter *as);
75
+ const char *pp_agents_starter_get_request_socket_filename(PP_AgentsStarter *as, unsigned int *size);
76
+ const char *pp_agents_starter_get_request_socket_password(PP_AgentsStarter *as, unsigned int *size);
77
+ const char *pp_agents_starter_get_server_instance_dir(PP_AgentsStarter *as);
78
+ const char *pp_agents_starter_get_generation_dir(PP_AgentsStarter *as);
79
+ pid_t pp_agents_starter_get_pid(PP_AgentsStarter *as);
80
+ void pp_agents_starter_detach(PP_AgentsStarter *as);
81
+ void pp_agents_starter_free(PP_AgentsStarter *as);
82
82
 
83
83
  #ifdef __cplusplus
84
84
  } /* extern "C" */
@@ -121,7 +121,7 @@ using namespace oxt;
121
121
  */
122
122
  class AgentsStarter {
123
123
  private:
124
- PSG_AgentsStarterType type;
124
+ PP_AgentsStarterType type;
125
125
 
126
126
  /** The watchdog's PID. Equals 0 if the watchdog hasn't been started yet
127
127
  * or if detach() is called. */
@@ -288,7 +288,7 @@ public:
288
288
  *
289
289
  * @param type Whether one wants to start the Apache or the Nginx helper agent.
290
290
  */
291
- AgentsStarter(PSG_AgentsStarterType type) {
291
+ AgentsStarter(PP_AgentsStarterType type) {
292
292
  this->type = type;
293
293
  pid = 0;
294
294
  }
@@ -329,7 +329,7 @@ public:
329
329
  /**
330
330
  * Returns the type as was passed to the constructor.
331
331
  */
332
- PSG_AgentsStarterType getType() const {
332
+ PP_AgentsStarterType getType() const {
333
333
  return type;
334
334
  }
335
335
 
@@ -42,18 +42,18 @@ const AppTypeDefinition appTypeDefinitions[] = {
42
42
  using namespace Passenger;
43
43
  using namespace Passenger::ApplicationPool2;
44
44
 
45
- PassengerAppTypeDetector *
46
- passenger_app_type_detector_new() {
45
+ PP_AppTypeDetector *
46
+ pp_app_type_detector_new() {
47
47
  return new AppTypeDetector();
48
48
  }
49
49
 
50
50
  void
51
- passenger_app_type_detector_free(PassengerAppTypeDetector *detector) {
51
+ pp_app_type_detector_free(PP_AppTypeDetector *detector) {
52
52
  delete (AppTypeDetector *) detector;
53
53
  }
54
54
 
55
55
  PassengerAppType
56
- passenger_app_type_detector_check_document_root(PassengerAppTypeDetector *_detector,
56
+ pp_app_type_detector_check_document_root(PP_AppTypeDetector *_detector,
57
57
  const char *documentRoot, unsigned int len, int resolveFirstSymlink)
58
58
  {
59
59
  AppTypeDetector *detector = (AppTypeDetector *) _detector;
@@ -61,7 +61,7 @@ passenger_app_type_detector_check_document_root(PassengerAppTypeDetector *_detec
61
61
  }
62
62
 
63
63
  PassengerAppType
64
- passenger_app_type_detector_check_app_root(PassengerAppTypeDetector *_detector,
64
+ pp_app_type_detector_check_app_root(PP_AppTypeDetector *_detector,
65
65
  const char *appRoot, unsigned int len)
66
66
  {
67
67
  AppTypeDetector *detector = (AppTypeDetector *) _detector;
@@ -69,6 +69,6 @@ passenger_app_type_detector_check_app_root(PassengerAppTypeDetector *_detector,
69
69
  }
70
70
 
71
71
  const char *
72
- passenger_get_app_type_name(PassengerAppType type) {
72
+ pp_get_app_type_name(PassengerAppType type) {
73
73
  return getAppTypeName(type);
74
74
  }
@@ -25,6 +25,15 @@
25
25
  #ifndef _PASSENGER_APPLICATION_POOL2_APP_TYPES_H_
26
26
  #define _PASSENGER_APPLICATION_POOL2_APP_TYPES_H_
27
27
 
28
+ /**
29
+ * Application type registry
30
+ *
31
+ * All supported application types (e.g. Rack, classic Rails, WSGI, etc)
32
+ * are registered here. The AppTypeDetector is responsible for checking
33
+ * what kind of application lives under the given directory.
34
+ */
35
+
36
+
28
37
  #ifdef __cplusplus
29
38
  extern "C" {
30
39
  #endif /* __cplusplus */
@@ -36,16 +45,16 @@ typedef enum {
36
45
  PAT_NONE
37
46
  } PassengerAppType;
38
47
 
39
- typedef void PassengerAppTypeDetector;
48
+ typedef void PP_AppTypeDetector;
40
49
 
41
- PassengerAppTypeDetector *passenger_app_type_detector_new();
42
- void passenger_app_type_detector_free(PassengerAppTypeDetector *detector);
43
- PassengerAppType passenger_app_type_detector_check_document_root(PassengerAppTypeDetector *detector,
50
+ PP_AppTypeDetector *pp_app_type_detector_new();
51
+ void pp_app_type_detector_free(PP_AppTypeDetector *detector);
52
+ PassengerAppType pp_app_type_detector_check_document_root(PP_AppTypeDetector *detector,
44
53
  const char *documentRoot, unsigned int len, int resolveFirstSymlink);
45
- PassengerAppType passenger_app_type_detector_check_app_root(PassengerAppTypeDetector *detector,
54
+ PassengerAppType pp_app_type_detector_check_app_root(PP_AppTypeDetector *detector,
46
55
  const char *appRoot, unsigned int len);
47
56
 
48
- const char *passenger_get_app_type_name(PassengerAppType type);
57
+ const char *pp_get_app_type_name(PassengerAppType type);
49
58
 
50
59
  #ifdef __cplusplus
51
60
  }
@@ -56,6 +65,7 @@ const char *passenger_get_app_type_name(PassengerAppType type);
56
65
  #include <oxt/macros.hpp>
57
66
  #include <oxt/backtrace.hpp>
58
67
  #include <cstdlib>
68
+ #include <string>
59
69
  #include <Logging.h>
60
70
  #include <StaticString.h>
61
71
  #include <Utils.h>
@@ -65,6 +75,8 @@ const char *passenger_get_app_type_name(PassengerAppType type);
65
75
  namespace Passenger {
66
76
  namespace ApplicationPool2 {
67
77
 
78
+ using namespace std;
79
+
68
80
 
69
81
  struct AppTypeDefinition {
70
82
  const PassengerAppType type;
@@ -114,18 +126,58 @@ public:
114
126
  }
115
127
  }
116
128
 
117
- PassengerAppType checkDocumentRoot(const StaticString &documentRoot, bool resolveFirstSymlink = false) {
129
+ /**
130
+ * Given a web server document root (that is, some subdirectory under the
131
+ * application root, e.g. "/webapps/foobar/public"), returns the type of
132
+ * application that lives there. Returns PAT_NONE if it wasn't able to detect
133
+ * a supported application type.
134
+ *
135
+ * If `resolveFirstSymlink` is given, and `documentRoot` is a symlink, then
136
+ * this function will check the parent directory
137
+ * of the directory that the symlink points to (i.e. `resolve(documentRoot) + "/.."`),
138
+ * instead of checking the directory that the symlink is located in (i.e.
139
+ * `dirname(documentRoot)`).
140
+ *
141
+ * If `appRoot` is non-NULL, then the inferred application root will be stored here.
142
+ *
143
+ * @throws FileSystemException Unable to check because of a filesystem error.
144
+ * @throws TimeRetrievalException
145
+ * @throws boost::thread_interrupted
146
+ */
147
+ PassengerAppType checkDocumentRoot(const StaticString &documentRoot,
148
+ bool resolveFirstSymlink = false,
149
+ string *appRoot = NULL)
150
+ {
118
151
  if (!resolveFirstSymlink) {
119
- return checkAppRoot(extractDirNameStatic(documentRoot));
152
+ if (appRoot != NULL) {
153
+ *appRoot = extractDirNameStatic(documentRoot);
154
+ return checkAppRoot(*appRoot);
155
+ } else {
156
+ return checkAppRoot(extractDirNameStatic(documentRoot));
157
+ }
120
158
  } else {
121
159
  char ntDocRoot[documentRoot.size() + 1];
122
160
  memcpy(ntDocRoot, documentRoot.data(), documentRoot.size());
123
161
  ntDocRoot[documentRoot.size()] = '\0';
124
162
  string resolvedDocumentRoot = resolveSymlink(ntDocRoot);
125
- return checkAppRoot(extractDirNameStatic(resolvedDocumentRoot));
163
+ if (appRoot != NULL) {
164
+ *appRoot = extractDirNameStatic(resolvedDocumentRoot);
165
+ return checkAppRoot(*appRoot);
166
+ } else {
167
+ return checkAppRoot(extractDirNameStatic(resolvedDocumentRoot));
168
+ }
126
169
  }
127
170
  }
128
171
 
172
+ /**
173
+ * Returns the type of application that lives under the application
174
+ * directory `appRoot`. Returns PAT_NONE if it wasn't able to detect
175
+ * a supported application type.
176
+ *
177
+ * @throws FileSystemException Unable to check because of a filesystem error.
178
+ * @throws TimeRetrievalException
179
+ * @throws boost::thread_interrupted
180
+ */
129
181
  PassengerAppType checkAppRoot(const StaticString &appRoot) {
130
182
  char buf[appRoot.size() + 32];
131
183
  const char *end = buf + appRoot.size() + 32;