passenger 3.0.2 → 3.0.3

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 (220) hide show
  1. data/NEWS +29 -0
  2. data/build/agents.rb +1 -0
  3. data/build/apache2.rb +2 -1
  4. data/build/cxx_tests.rb +7 -0
  5. data/build/rpm.rb +17 -22
  6. data/doc/cxxapi/Constants_8h_source.html +1 -1
  7. data/doc/cxxapi/Exceptions_8h_source.html +18 -4
  8. data/doc/cxxapi/Logging_8h_source.html +332 -262
  9. data/doc/cxxapi/annotated.html +1 -0
  10. data/doc/cxxapi/classes.html +4 -4
  11. data/doc/cxxapi/group__Exceptions.html +2 -0
  12. data/doc/cxxapi/hierarchy.html +1 -0
  13. data/doc/cxxapi/inherit__graph__35.map +1 -3
  14. data/doc/cxxapi/inherit__graph__35.md5 +1 -1
  15. data/doc/cxxapi/inherit__graph__35.png +0 -0
  16. data/doc/cxxapi/inherit__graph__36.map +3 -1
  17. data/doc/cxxapi/inherit__graph__36.md5 +1 -1
  18. data/doc/cxxapi/inherit__graph__36.png +0 -0
  19. data/doc/cxxapi/inherit__graph__37.map +1 -1
  20. data/doc/cxxapi/inherit__graph__37.md5 +1 -1
  21. data/doc/cxxapi/inherit__graph__37.png +0 -0
  22. data/doc/cxxapi/inherit__graph__38.map +1 -1
  23. data/doc/cxxapi/inherit__graph__38.md5 +1 -1
  24. data/doc/cxxapi/inherit__graph__38.png +0 -0
  25. data/doc/cxxapi/inherit__graph__39.map +1 -1
  26. data/doc/cxxapi/inherit__graph__39.md5 +1 -1
  27. data/doc/cxxapi/inherit__graph__39.png +0 -0
  28. data/doc/cxxapi/inherit__graph__40.map +1 -1
  29. data/doc/cxxapi/inherit__graph__40.md5 +1 -1
  30. data/doc/cxxapi/inherit__graph__40.png +0 -0
  31. data/doc/cxxapi/inherits.html +9 -6
  32. data/doc/cxxapi/namespacePassenger.html +2 -0
  33. data/doc/cxxapi/tree.html +2 -0
  34. data/doc/rdoc/classes/ConditionVariable.html +215 -0
  35. data/doc/rdoc/classes/Exception.html +120 -0
  36. data/doc/rdoc/classes/GC.html +113 -0
  37. data/doc/rdoc/classes/IO.html +221 -0
  38. data/doc/rdoc/classes/PhusionPassenger.html +397 -0
  39. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +180 -0
  40. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +647 -0
  41. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +654 -0
  42. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/InvalidPassword.html +92 -0
  43. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerAlreadyStarted.html +97 -0
  44. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerError.html +96 -0
  45. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerNotStarted.html +97 -0
  46. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/UnknownMessage.html +96 -0
  47. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +619 -0
  48. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +142 -0
  49. data/doc/rdoc/classes/PhusionPassenger/AdminTools/MemoryStats.html +368 -0
  50. data/doc/rdoc/classes/PhusionPassenger/AdminTools/MemoryStats/Process.html +231 -0
  51. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance.html +588 -0
  52. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/CorruptedDirectoryError.html +92 -0
  53. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/GenerationsAbsentError.html +92 -0
  54. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/Group.html +147 -0
  55. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/Process.html +279 -0
  56. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/RoleDeniedError.html +92 -0
  57. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/StaleDirectoryError.html +92 -0
  58. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/Stats.html +123 -0
  59. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/UnsupportedGenerationStructureVersionError.html +92 -0
  60. data/doc/rdoc/classes/PhusionPassenger/AnalyticsLogger.html +368 -0
  61. data/doc/rdoc/classes/PhusionPassenger/AnalyticsLogger/Log.html +299 -0
  62. data/doc/rdoc/classes/PhusionPassenger/AnalyticsLogger/SharedData.html +206 -0
  63. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +155 -0
  64. data/doc/rdoc/classes/PhusionPassenger/AppProcess.html +367 -0
  65. data/doc/rdoc/classes/PhusionPassenger/ClassicRails.html +95 -0
  66. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/ApplicationSpawner.html +351 -0
  67. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/ApplicationSpawner/Error.html +98 -0
  68. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/CGIFixed.html +200 -0
  69. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/FrameworkSpawner.html +410 -0
  70. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/FrameworkSpawner/Error.html +98 -0
  71. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/RequestHandler.html +156 -0
  72. data/doc/rdoc/classes/PhusionPassenger/ClassicRailsExtensions.html +115 -0
  73. data/doc/rdoc/classes/PhusionPassenger/ClassicRailsExtensions/AnalyticsLogging.html +202 -0
  74. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +172 -0
  75. data/doc/rdoc/classes/PhusionPassenger/DebugLogging.html +273 -0
  76. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +145 -0
  77. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +162 -0
  78. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +141 -0
  79. data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +92 -0
  80. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +673 -0
  81. data/doc/rdoc/classes/PhusionPassenger/MessageChannel/InvalidHashError.html +92 -0
  82. data/doc/rdoc/classes/PhusionPassenger/MessageClient.html +415 -0
  83. data/doc/rdoc/classes/PhusionPassenger/NativeSupportLoader.html +134 -0
  84. data/doc/rdoc/classes/PhusionPassenger/Packaging.html +129 -0
  85. data/doc/rdoc/classes/PhusionPassenger/PlatformInfo.html +1972 -0
  86. data/doc/rdoc/classes/PhusionPassenger/Plugin.html +237 -0
  87. data/doc/rdoc/classes/PhusionPassenger/Rack.html +91 -0
  88. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +312 -0
  89. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner/Error.html +98 -0
  90. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +218 -0
  91. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions.html +114 -0
  92. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging.html +259 -0
  93. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging/ACExtension.html +139 -0
  94. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging/ASBenchmarkableExtension.html +118 -0
  95. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging/ExceptionLogger.html +135 -0
  96. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +378 -0
  97. data/doc/rdoc/classes/PhusionPassenger/Standalone.html +111 -0
  98. data/doc/rdoc/classes/PhusionPassenger/Standalone/AppFinder.html +252 -0
  99. data/doc/rdoc/classes/PhusionPassenger/Standalone/Command.html +161 -0
  100. data/doc/rdoc/classes/PhusionPassenger/Standalone/ConfigFile.html +368 -0
  101. data/doc/rdoc/classes/PhusionPassenger/Standalone/ConfigFile/DisallowedContextError.html +132 -0
  102. data/doc/rdoc/classes/PhusionPassenger/Standalone/HelpCommand.html +151 -0
  103. data/doc/rdoc/classes/PhusionPassenger/Standalone/Main.html +189 -0
  104. data/doc/rdoc/classes/PhusionPassenger/Standalone/PackageRuntimeCommand.html +177 -0
  105. data/doc/rdoc/classes/PhusionPassenger/Standalone/RuntimeInstaller.html +341 -0
  106. data/doc/rdoc/classes/PhusionPassenger/Standalone/StartCommand.html +203 -0
  107. data/doc/rdoc/classes/PhusionPassenger/Standalone/StatusCommand.html +156 -0
  108. data/doc/rdoc/classes/PhusionPassenger/Standalone/StopCommand.html +168 -0
  109. data/doc/rdoc/classes/PhusionPassenger/Standalone/Utils.html +86 -0
  110. data/doc/rdoc/classes/PhusionPassenger/Standalone/VersionCommand.html +135 -0
  111. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +125 -0
  112. data/doc/rdoc/classes/PhusionPassenger/Utils.html +1543 -0
  113. data/doc/rdoc/classes/PhusionPassenger/Utils/FileSystemWatcher.html +204 -0
  114. data/doc/rdoc/classes/PhusionPassenger/Utils/FileSystemWatcher/DirInfo.html +171 -0
  115. data/doc/rdoc/classes/PhusionPassenger/Utils/FileSystemWatcher/FileInfo.html +140 -0
  116. data/doc/rdoc/classes/PhusionPassenger/Utils/HostsFileParser.html +260 -0
  117. data/doc/rdoc/classes/PhusionPassenger/Utils/PseudoIO.html +194 -0
  118. data/doc/rdoc/classes/PhusionPassenger/Utils/RewindableInput.html +265 -0
  119. data/doc/rdoc/classes/PhusionPassenger/Utils/RewindableInput/Tempfile.html +120 -0
  120. data/doc/rdoc/classes/PhusionPassenger/Utils/UnseekableSocket.html +561 -0
  121. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +140 -0
  122. data/doc/rdoc/classes/PhusionPassenger/WSGI.html +89 -0
  123. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +182 -0
  124. data/doc/rdoc/classes/Process.html +115 -0
  125. data/doc/rdoc/classes/Signal.html +139 -0
  126. data/doc/rdoc/created.rid +1 -0
  127. data/doc/rdoc/files/DEVELOPERS_TXT.html +280 -0
  128. data/doc/rdoc/files/README.html +157 -0
  129. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +130 -0
  130. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +135 -0
  131. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +126 -0
  132. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +128 -0
  133. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/memory_stats_rb.html +126 -0
  134. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/server_instance_rb.html +132 -0
  135. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +122 -0
  136. data/doc/rdoc/files/lib/phusion_passenger/analytics_logger_rb.html +129 -0
  137. data/doc/rdoc/files/lib/phusion_passenger/app_process_rb.html +127 -0
  138. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/application_spawner_rb.html +141 -0
  139. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/cgi_fixed_rb.html +126 -0
  140. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/framework_spawner_rb.html +146 -0
  141. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/request_handler_rb.html +125 -0
  142. data/doc/rdoc/files/lib/phusion_passenger/classic_rails_extensions/init_rb.html +132 -0
  143. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +126 -0
  144. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +122 -0
  145. data/doc/rdoc/files/lib/phusion_passenger/debug_logging_rb.html +122 -0
  146. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +147 -0
  147. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +122 -0
  148. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +127 -0
  149. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +120 -0
  150. data/doc/rdoc/files/lib/phusion_passenger/message_client_rb.html +127 -0
  151. data/doc/rdoc/files/lib/phusion_passenger/native_support_rb.html +132 -0
  152. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +122 -0
  153. data/doc/rdoc/files/lib/phusion_passenger/platform_info/apache_rb.html +127 -0
  154. data/doc/rdoc/files/lib/phusion_passenger/platform_info/binary_compatibility_rb.html +129 -0
  155. data/doc/rdoc/files/lib/phusion_passenger/platform_info/compiler_rb.html +127 -0
  156. data/doc/rdoc/files/lib/phusion_passenger/platform_info/curl_rb.html +126 -0
  157. data/doc/rdoc/files/lib/phusion_passenger/platform_info/documentation_tools_rb.html +126 -0
  158. data/doc/rdoc/files/lib/phusion_passenger/platform_info/linux_rb.html +126 -0
  159. data/doc/rdoc/files/lib/phusion_passenger/platform_info/operating_system_rb.html +127 -0
  160. data/doc/rdoc/files/lib/phusion_passenger/platform_info/ruby_rb.html +128 -0
  161. data/doc/rdoc/files/lib/phusion_passenger/platform_info/zlib_rb.html +126 -0
  162. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +122 -0
  163. data/doc/rdoc/files/lib/phusion_passenger/plugin_rb.html +127 -0
  164. data/doc/rdoc/files/lib/phusion_passenger/public_api_rb.html +127 -0
  165. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +137 -0
  166. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +125 -0
  167. data/doc/rdoc/files/lib/phusion_passenger/rails3_extensions/init_rb.html +127 -0
  168. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +122 -0
  169. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +160 -0
  170. data/doc/rdoc/files/lib/phusion_passenger/standalone/app_finder_rb.html +127 -0
  171. data/doc/rdoc/files/lib/phusion_passenger/standalone/command_rb.html +136 -0
  172. data/doc/rdoc/files/lib/phusion_passenger/standalone/config_file_rb.html +126 -0
  173. data/doc/rdoc/files/lib/phusion_passenger/standalone/help_command_rb.html +126 -0
  174. data/doc/rdoc/files/lib/phusion_passenger/standalone/main_rb.html +126 -0
  175. data/doc/rdoc/files/lib/phusion_passenger/standalone/package_runtime_command_rb.html +127 -0
  176. data/doc/rdoc/files/lib/phusion_passenger/standalone/runtime_installer_rb.html +133 -0
  177. data/doc/rdoc/files/lib/phusion_passenger/standalone/start_command_rb.html +136 -0
  178. data/doc/rdoc/files/lib/phusion_passenger/standalone/status_command_rb.html +126 -0
  179. data/doc/rdoc/files/lib/phusion_passenger/standalone/stop_command_rb.html +126 -0
  180. data/doc/rdoc/files/lib/phusion_passenger/standalone/utils_rb.html +126 -0
  181. data/doc/rdoc/files/lib/phusion_passenger/standalone/version_command_rb.html +127 -0
  182. data/doc/rdoc/files/lib/phusion_passenger/utils/file_system_watcher_rb.html +126 -0
  183. data/doc/rdoc/files/lib/phusion_passenger/utils/hosts_file_parser_rb.html +120 -0
  184. data/doc/rdoc/files/lib/phusion_passenger/utils/rewindable_input_rb.html +100 -0
  185. data/doc/rdoc/files/lib/phusion_passenger/utils/tmpdir_rb.html +122 -0
  186. data/doc/rdoc/files/lib/phusion_passenger/utils/unseekable_socket_rb.html +126 -0
  187. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +179 -0
  188. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +132 -0
  189. data/doc/rdoc/fr_class_index.html +139 -0
  190. data/doc/rdoc/fr_file_index.html +108 -0
  191. data/doc/rdoc/fr_method_index.html +439 -0
  192. data/doc/rdoc/index.html +26 -0
  193. data/doc/rdoc/rdoc-style.css +187 -0
  194. data/ext/apache2/Configuration.cpp +41 -0
  195. data/ext/apache2/Configuration.hpp +19 -0
  196. data/ext/apache2/Hooks.cpp +67 -5
  197. data/ext/common/Constants.h +1 -1
  198. data/ext/common/Exceptions.h +14 -0
  199. data/ext/common/Logging.h +76 -6
  200. data/ext/common/LoggingAgent/FilterSupport.h +1317 -0
  201. data/ext/common/LoggingAgent/LoggingServer.h +93 -4
  202. data/ext/common/LoggingAgent/RemoteSender.h +5 -5
  203. data/ext/common/Utils/StrIntUtils.cpp +12 -1
  204. data/ext/common/Utils/StrIntUtils.h +2 -1
  205. data/ext/common/Utils/StringMap.h +100 -0
  206. data/ext/nginx/Configuration.c +0 -1
  207. data/ext/nginx/ContentHandler.c +33 -7
  208. data/lib/phusion_passenger.rb +2 -2
  209. data/lib/phusion_passenger/abstract_request_handler.rb +5 -0
  210. data/lib/phusion_passenger/analytics_logger.rb +77 -11
  211. data/lib/phusion_passenger/dependencies.rb +11 -1
  212. data/lib/phusion_passenger/platform_info.rb +1 -1
  213. data/lib/phusion_passenger/utils.rb +9 -1
  214. data/test/cxx/FilterSupportTest.cpp +276 -0
  215. data/test/cxx/LoggingTest.cpp +28 -0
  216. data/test/cxx/StringMapTest.cpp +70 -0
  217. data/test/integration_tests/cgi_environment_spec.rb +10 -0
  218. metadata +170 -8
  219. data/ext/common/libboost_oxt/aggregate.cpp +0 -10
  220. data/ext/common/libpassenger_common/aggregate.cpp +0 -15
@@ -45,6 +45,7 @@
45
45
  #include "DataStoreId.h"
46
46
  #include "RemoteSender.h"
47
47
  #include "ChangeNotifier.h"
48
+ #include "FilterSupport.h"
48
49
  #include "../EventedMessageServer.h"
49
50
  #include "../MessageReadersWriters.h"
50
51
  #include "../StaticString.h"
@@ -55,6 +56,7 @@
55
56
  #include "../Utils/MD5.h"
56
57
  #include "../Utils/IOUtils.h"
57
58
  #include "../Utils/StrIntUtils.h"
59
+ #include "../Utils/StringMap.h"
58
60
 
59
61
 
60
62
  namespace Passenger {
@@ -299,6 +301,7 @@ private:
299
301
  int refcount;
300
302
  bool crashProtect, discarded;
301
303
  string data;
304
+ string filters;
302
305
 
303
306
  Transaction(LoggingServer *server) {
304
307
  this->server = server;
@@ -307,7 +310,7 @@ private:
307
310
 
308
311
  ~Transaction() {
309
312
  if (logSink != NULL) {
310
- if (!discarded) {
313
+ if (!discarded && passesFilter()) {
311
314
  logSink->append(dataStoreId, data);
312
315
  }
313
316
  server->closeLogSink(logSink);
@@ -338,6 +341,35 @@ private:
338
341
  stream << " Category: " << getCategory() << "\n";
339
342
  stream << " Refcount: " << refcount << "\n";
340
343
  }
344
+
345
+ private:
346
+ bool passesFilter() {
347
+ if (filters.empty()) {
348
+ return true;
349
+ }
350
+
351
+ const char *current = filters.data();
352
+ const char *end = filters.data() + filters.size();
353
+ bool result = true;
354
+ FilterSupport::ContextFromLog ctx(data);
355
+
356
+ // 'filters' may contain multiple filter sources, separated
357
+ // by '\1' characters. Process each.
358
+ while (current < end && result) {
359
+ StaticString tmp(current, end - current);
360
+ size_t pos = tmp.find('\1');
361
+ if (pos == string::npos) {
362
+ pos = tmp.size();
363
+ }
364
+
365
+ StaticString source(current, pos);
366
+ FilterSupport::Filter &filter = server->compileFilter(source);
367
+ result = filter.run(ctx);
368
+
369
+ current = tmp.data() + pos + 1;
370
+ }
371
+ return result;
372
+ }
341
373
  };
342
374
 
343
375
  typedef shared_ptr<Transaction> TransactionPtr;
@@ -372,6 +404,8 @@ private:
372
404
  typedef shared_ptr<Client> ClientPtr;
373
405
  typedef map<string, TransactionPtr> TransactionMap;
374
406
 
407
+ typedef shared_ptr<FilterSupport::Filter> FilterPtr;
408
+
375
409
  string dir;
376
410
  gid_t gid;
377
411
  string dirPermissions;
@@ -392,6 +426,7 @@ private:
392
426
  */
393
427
  list<LogSinkPtr> inactiveLogSinks;
394
428
  int inactiveLogSinksCount;
429
+ StringMap<FilterPtr> filters;
395
430
  RandomGenerator randomGenerator;
396
431
  bool refuseNewConnections;
397
432
  bool exitRequested;
@@ -412,6 +447,16 @@ private:
412
447
  }
413
448
  }
414
449
 
450
+ bool expectingMinArgumentsCount(Client *client, const vector<StaticString> &args, unsigned int size) {
451
+ if (args.size() >= size) {
452
+ return true;
453
+ } else {
454
+ sendErrorToClient(client, "Invalid number of arguments");
455
+ client->disconnect();
456
+ return false;
457
+ }
458
+ }
459
+
415
460
  bool expectingLoggerType(Client *client) {
416
461
  if (client->type == LOGGER) {
417
462
  return true;
@@ -432,6 +477,26 @@ private:
432
477
  }
433
478
  }
434
479
 
480
+ static bool getBool(const vector<StaticString> &args, unsigned int index,
481
+ bool defaultValue = false)
482
+ {
483
+ if (index < args.size()) {
484
+ return args[index] == "true";
485
+ } else {
486
+ return defaultValue;
487
+ }
488
+ }
489
+
490
+ static StaticString getStaticString(const vector<StaticString> &args,
491
+ unsigned int index, const StaticString &defaultValue = "")
492
+ {
493
+ if (index < args.size()) {
494
+ return args[index];
495
+ } else {
496
+ return defaultValue;
497
+ }
498
+ }
499
+
435
500
  bool validTxnId(const StaticString &txnId) const {
436
501
  // must contain timestamp
437
502
  // must contain separator
@@ -651,6 +716,16 @@ private:
651
716
  }
652
717
  }
653
718
 
719
+ FilterSupport::Filter &compileFilter(const StaticString &source) {
720
+ // TODO: garbage collect filters based on time
721
+ FilterPtr filter = filters.get(source);
722
+ if (filter == NULL) {
723
+ filter = make_shared<FilterSupport::Filter>(source);
724
+ filters.set(source, filter);
725
+ }
726
+ return *filter;
727
+ }
728
+
654
729
  bool writeLogEntry(Client *client, const TransactionPtr &transaction,
655
730
  const StaticString &timestamp, const StaticString &data)
656
731
  {
@@ -897,7 +972,7 @@ protected:
897
972
  }
898
973
 
899
974
  } else if (args[0] == "openTransaction") {
900
- if (OXT_UNLIKELY( !expectingArgumentsCount(client, args, 8)
975
+ if (OXT_UNLIKELY( !expectingMinArgumentsCount(client, args, 7)
901
976
  || !expectingLoggerType(client) )) {
902
977
  return true;
903
978
  }
@@ -908,7 +983,9 @@ protected:
908
983
  StaticString category = args[4];
909
984
  StaticString timestamp = args[5];
910
985
  StaticString unionStationKey = args[6];
911
- bool crashProtect = args[7] == "true";
986
+ bool crashProtect = getBool(args, 7, true);
987
+ bool ack = getBool(args, 8, false);
988
+ StaticString filters = getStaticString(args, 9);
912
989
 
913
990
  if (OXT_UNLIKELY( !validTxnId(txnId) )) {
914
991
  sendErrorToClient(client, "Invalid transaction ID format");
@@ -980,6 +1057,9 @@ protected:
980
1057
  transaction->writeCount = 0;
981
1058
  transaction->refcount = 0;
982
1059
  transaction->crashProtect = crashProtect;
1060
+ if (!filters.empty()) {
1061
+ transaction->filters = filters;
1062
+ }
983
1063
  transaction->discarded = false;
984
1064
  transactions.insert(make_pair(txnId, transaction));
985
1065
  } else {
@@ -1008,14 +1088,19 @@ protected:
1008
1088
  transaction->refcount++;
1009
1089
  writeLogEntry(client, transaction, timestamp, "ATTACH");
1010
1090
 
1091
+ if (ack) {
1092
+ client->writeArrayMessage("ok", NULL);
1093
+ }
1094
+
1011
1095
  } else if (args[0] == "closeTransaction") {
1012
- if (OXT_UNLIKELY( !expectingArgumentsCount(client, args, 3)
1096
+ if (OXT_UNLIKELY( !expectingMinArgumentsCount(client, args, 3)
1013
1097
  || !expectingLoggerType(client) )) {
1014
1098
  return true;
1015
1099
  }
1016
1100
 
1017
1101
  string txnId = args[1];
1018
1102
  StaticString timestamp = args[2];
1103
+ bool ack = getBool(args, 3, false);
1019
1104
 
1020
1105
  TransactionMap::iterator it = transactions.find(txnId);
1021
1106
  if (OXT_UNLIKELY( it == transactions.end() )) {
@@ -1044,6 +1129,10 @@ protected:
1044
1129
  transactions.erase(it);
1045
1130
  }
1046
1131
  }
1132
+
1133
+ if (ack) {
1134
+ client->writeArrayMessage("ok", NULL);
1135
+ }
1047
1136
 
1048
1137
  } else if (args[0] == "init") {
1049
1138
  if (OXT_UNLIKELY( client->type != UNINITIALIZED )) {
@@ -102,13 +102,13 @@ private:
102
102
  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
103
103
  } else {
104
104
  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
105
- /* No host name verification because Curl thinks the
106
- * host name is the IP address. Doesn't matter as
107
- * long as we have the certificate.
108
- */
109
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
110
105
  curl_easy_setopt(curl, CURLOPT_CAINFO, certificate.c_str());
111
106
  }
107
+ /* No host name verification because Curl thinks the
108
+ * host name is the IP address. But if we have the
109
+ * certificate then it doesn't matter.
110
+ */
111
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
112
112
  responseBody.clear();
113
113
  }
114
114
 
@@ -56,8 +56,9 @@ startsWith(const StaticString &str, const StaticString &substr) {
56
56
  }
57
57
  }
58
58
 
59
+ template<typename OutputString>
59
60
  void
60
- split(const string &str, char sep, vector<string> &output) {
61
+ _split(const StaticString &str, char sep, vector<OutputString> &output) {
61
62
  string::size_type start, pos;
62
63
  start = 0;
63
64
  output.clear();
@@ -68,6 +69,16 @@ split(const string &str, char sep, vector<string> &output) {
68
69
  output.push_back(str.substr(start));
69
70
  }
70
71
 
72
+ void
73
+ split(const StaticString &str, char sep, vector<string> &output) {
74
+ _split(str, sep, output);
75
+ }
76
+
77
+ void
78
+ split(const StaticString &str, char sep, vector<StaticString> &output) {
79
+ _split(str, sep, output);
80
+ }
81
+
71
82
  string toString(const vector<string> &vec) {
72
83
  vector<StaticString> vec2;
73
84
  vec2.reserve(vec.size());
@@ -70,7 +70,8 @@ bool startsWith(const StaticString &str, const StaticString &substr);
70
70
  * @param sep The separator to use.
71
71
  * @param output The vector to write the output to.
72
72
  */
73
- void split(const string &str, char sep, vector<string> &output);
73
+ void split(const StaticString &str, char sep, vector<string> &output);
74
+ void split(const StaticString &str, char sep, vector<StaticString> &output);
74
75
 
75
76
  /**
76
77
  * Convert anything to a string.
@@ -0,0 +1,100 @@
1
+ /*
2
+ * Phusion Passenger - http://www.modrails.com/
3
+ * Copyright (c) 2011 Phusion
4
+ *
5
+ * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ */
25
+ #ifndef _PASSENGER_STRING_MAP_H_
26
+ #define _PASSENGER_STRING_MAP_H_
27
+
28
+ #include <string>
29
+ #include <map>
30
+ #include <utility>
31
+
32
+ #include <StaticString.h>
33
+
34
+ namespace Passenger {
35
+
36
+ using namespace std;
37
+
38
+
39
+ /**
40
+ * An efficient map with string keys. map<string, T> forces one to construct an
41
+ * std::string object when looking up the map. StringMap interns all keys and
42
+ * allows lookups without constructing an std::string key.
43
+ *
44
+ * StringMap requires the following properties on T:
45
+ * - T's default constructor must be cheap, otherwise set() can be a bit slow.
46
+ * - T must support operator=().
47
+ */
48
+ template<typename T>
49
+ class StringMap {
50
+ private:
51
+ struct Entry {
52
+ string key;
53
+ T value;
54
+ };
55
+
56
+ typedef map<StaticString, Entry> InternalMap;
57
+ typedef typename InternalMap::iterator Iterator;
58
+ typedef typename InternalMap::const_iterator ConstIterator;
59
+ typedef typename InternalMap::value_type ValueType;
60
+ InternalMap store;
61
+
62
+ public:
63
+ T get(const StaticString &key) const {
64
+ ConstIterator it = store.find(key);
65
+ if (it == store.end()) {
66
+ return T();
67
+ } else {
68
+ return it->second.value;
69
+ }
70
+ }
71
+
72
+ bool set(const StaticString &key, const T &value) {
73
+ pair<Iterator, bool> result = store.insert(make_pair(key, Entry()));
74
+ if (result.second) {
75
+ // Key has been inserted. Copy it internally and point key
76
+ // to the copy.
77
+ ValueType &node = *result.first;
78
+ StaticString &originalKey = const_cast<StaticString &>(node.first);
79
+ Entry &entry = node.second;
80
+ entry.key = key;
81
+ entry.value = value;
82
+ originalKey = entry.key;
83
+ return true;
84
+ } else {
85
+ // Key already exists. Update value.
86
+ Entry &entry = result.first->second;
87
+ entry.value = value;
88
+ return false;
89
+ }
90
+ }
91
+
92
+ bool remove(const StaticString &key) {
93
+ return store.erase(key) > 0;
94
+ }
95
+ };
96
+
97
+
98
+ } // namespace Passenger
99
+
100
+ #endif /* _PASSENGER_STRING_MAP_H_ */
@@ -332,7 +332,6 @@ passenger_create_loc_conf(ngx_conf_t *cf)
332
332
  DEFINE_VAR_TO_PASS("SCGI", "1");
333
333
  DEFINE_VAR_TO_PASS("QUERY_STRING", "$query_string");
334
334
  DEFINE_VAR_TO_PASS("REQUEST_METHOD", "$request_method");
335
- DEFINE_VAR_TO_PASS("REQUEST_URI", "$uri$is_args$args");
336
335
  DEFINE_VAR_TO_PASS("SERVER_PROTOCOL", "$server_protocol");
337
336
  DEFINE_VAR_TO_PASS("SERVER_SOFTWARE", "nginx/$nginx_version");
338
337
  DEFINE_VAR_TO_PASS("REMOTE_ADDR", "$remote_addr");
@@ -321,6 +321,7 @@ create_request(ngx_http_request_t *r)
321
321
  size_t len, size, key_len, val_len, content_length;
322
322
  const u_char *app_type_string;
323
323
  size_t app_type_string_len;
324
+ ngx_str_t escaped_uri;
324
325
  u_char min_instances_string[12];
325
326
  u_char framework_spawner_idle_time_string[12];
326
327
  u_char app_spawner_idle_time_string[12];
@@ -367,6 +368,19 @@ create_request(ngx_http_request_t *r)
367
368
  }
368
369
 
369
370
 
371
+ /*
372
+ * Nginx unescapes URI's before passing them to Phusion Passenger,
373
+ * but backend processes expect the escaped version.
374
+ * http://code.google.com/p/phusion-passenger/issues/detail?id=404
375
+ */
376
+ escaped_uri.len =
377
+ 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len, NGX_ESCAPE_URI)
378
+ + r->uri.len;
379
+ escaped_uri.data = ngx_pnalloc(r->pool, escaped_uri.len + 1);
380
+ escaped_uri.data[escaped_uri.len] = '\0';
381
+ ngx_escape_uri(escaped_uri.data, r->uri.data, r->uri.len, NGX_ESCAPE_URI);
382
+
383
+
370
384
  /**************************************************
371
385
  * Determine the request header length.
372
386
  **************************************************/
@@ -381,16 +395,20 @@ create_request(ngx_http_request_t *r)
381
395
  /* +1 for trailing null */
382
396
  len = sizeof("CONTENT_LENGTH") + ngx_strlen(buf) + 1;
383
397
 
384
- /* DOCUMENT_ROOT, SCRIPT_NAME, RAILS_RELATIVE_URL_ROOT and PATH_INFO. */
398
+ /* DOCUMENT_ROOT, SCRIPT_NAME, RAILS_RELATIVE_URL_ROOT, PATH_INFO and REQUEST_URI. */
385
399
  len += sizeof("DOCUMENT_ROOT") + context->public_dir.len + 1;
386
400
  if (context->base_uri.len > 0) {
387
401
  len += sizeof("SCRIPT_NAME") + context->base_uri.len + 1;
388
402
  len += sizeof("RAILS_RELATIVE_URL_ROOT") +
389
403
  context->base_uri.len + 1;
390
- len += sizeof("PATH_INFO") + r->uri.len - context->base_uri.len + 1;
404
+ len += sizeof("PATH_INFO") + escaped_uri.len - context->base_uri.len + 1;
391
405
  } else {
392
406
  len += sizeof("SCRIPT_NAME") + sizeof("");
393
- len += sizeof("PATH_INFO") + r->uri.len + 1;
407
+ len += sizeof("PATH_INFO") + escaped_uri.len + 1;
408
+ }
409
+ len += sizeof("REQUEST_URI") + escaped_uri.len + 1;
410
+ if (r->args.len > 0) {
411
+ len += 1 + r->args.len;
394
412
  }
395
413
 
396
414
  /* Various other HTTP headers. */
@@ -569,7 +587,7 @@ create_request(ngx_http_request_t *r)
569
587
  b->last = ngx_snprintf(b->last, 10, "%ui", content_length);
570
588
  *b->last++ = (u_char) 0;
571
589
 
572
- /* Build DOCUMENT_ROOT, SCRIPT_NAME, RAILS_RELATIVE_URL_ROOT and PATH_INFO. */
590
+ /* Build DOCUMENT_ROOT, SCRIPT_NAME, RAILS_RELATIVE_URL_ROOT, PATH_INFO and REQUEST_URI. */
573
591
  b->last = ngx_copy(b->last, "DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT"));
574
592
  b->last = ngx_copy(b->last, context->public_dir.data,
575
593
  context->public_dir.len + 1);
@@ -585,18 +603,26 @@ create_request(ngx_http_request_t *r)
585
603
  context->base_uri.len + 1);
586
604
 
587
605
  b->last = ngx_copy(b->last, "PATH_INFO", sizeof("PATH_INFO"));
588
- b->last = ngx_copy(b->last, r->uri.data + context->base_uri.len,
589
- r->uri.len - context->base_uri.len);
606
+ b->last = ngx_copy(b->last, escaped_uri.data + context->base_uri.len,
607
+ escaped_uri.len - context->base_uri.len);
590
608
  b->last = ngx_copy(b->last, "", 1);
591
609
  } else {
592
610
  b->last = ngx_copy(b->last, "SCRIPT_NAME", sizeof("SCRIPT_NAME"));
593
611
  b->last = ngx_copy(b->last, "", sizeof(""));
594
612
 
595
613
  b->last = ngx_copy(b->last, "PATH_INFO", sizeof("PATH_INFO"));
596
- b->last = ngx_copy(b->last, r->uri.data, r->uri.len);
614
+ b->last = ngx_copy(b->last, escaped_uri.data, escaped_uri.len);
597
615
  b->last = ngx_copy(b->last, "", 1);
598
616
  }
599
617
 
618
+ b->last = ngx_copy(b->last, "REQUEST_URI", sizeof("REQUEST_URI"));
619
+ b->last = ngx_copy(b->last, escaped_uri.data, escaped_uri.len);
620
+ if (r->args.len > 0) {
621
+ b->last = ngx_copy(b->last, "?", 1);
622
+ b->last = ngx_copy(b->last, r->args.data, r->args.len);
623
+ }
624
+ b->last = ngx_copy(b->last, "", 1);
625
+
600
626
  /* Various other HTTP headers. */
601
627
  if (r->headers_in.content_type != NULL
602
628
  && r->headers_in.content_type->value.len > 0) {