zuk-picnic 0.7.999.20090212

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. data/CHANGELOG.txt +1 -0
  2. data/History.txt +68 -0
  3. data/LICENSE.txt +165 -0
  4. data/Manifest.txt +29 -0
  5. data/README.txt +31 -0
  6. data/Rakefile +62 -0
  7. data/lib/picnic/authentication.rb +218 -0
  8. data/lib/picnic/cli.rb +165 -0
  9. data/lib/picnic/conf.rb +135 -0
  10. data/lib/picnic/controllers.rb +4 -0
  11. data/lib/picnic/logger.rb +41 -0
  12. data/lib/picnic/server.rb +98 -0
  13. data/lib/picnic/service_control.rb +274 -0
  14. data/lib/picnic/version.rb +9 -0
  15. data/lib/picnic.rb +48 -0
  16. data/setup.rb +1585 -0
  17. data/test/picnic_test.rb +11 -0
  18. data/test/test_helper.rb +2 -0
  19. data/vendor/camping-2.0.20090212/CHANGELOG +118 -0
  20. data/vendor/camping-2.0.20090212/COPYING +18 -0
  21. data/vendor/camping-2.0.20090212/README +119 -0
  22. data/vendor/camping-2.0.20090212/Rakefile +174 -0
  23. data/vendor/camping-2.0.20090212/bin/camping +99 -0
  24. data/vendor/camping-2.0.20090212/doc/camping.1.gz +0 -0
  25. data/vendor/camping-2.0.20090212/examples/README +5 -0
  26. data/vendor/camping-2.0.20090212/examples/blog.rb +375 -0
  27. data/vendor/camping-2.0.20090212/examples/campsh.rb +629 -0
  28. data/vendor/camping-2.0.20090212/examples/tepee.rb +242 -0
  29. data/vendor/camping-2.0.20090212/extras/Camping.gif +0 -0
  30. data/vendor/camping-2.0.20090212/extras/flipbook_rdoc.rb +491 -0
  31. data/vendor/camping-2.0.20090212/extras/permalink.gif +0 -0
  32. data/vendor/camping-2.0.20090212/lib/camping/ar/session.rb +132 -0
  33. data/vendor/camping-2.0.20090212/lib/camping/ar.rb +78 -0
  34. data/vendor/camping-2.0.20090212/lib/camping/mab.rb +26 -0
  35. data/vendor/camping-2.0.20090212/lib/camping/reloader.rb +163 -0
  36. data/vendor/camping-2.0.20090212/lib/camping/server.rb +158 -0
  37. data/vendor/camping-2.0.20090212/lib/camping/session.rb +74 -0
  38. data/vendor/camping-2.0.20090212/lib/camping-unabridged.rb +638 -0
  39. data/vendor/camping-2.0.20090212/lib/camping.rb +54 -0
  40. data/vendor/camping-2.0.20090212/setup.rb +1551 -0
  41. data/vendor/camping-2.0.20090212/test/apps/env_debug.rb +65 -0
  42. data/vendor/camping-2.0.20090212/test/apps/forms.rb +95 -0
  43. data/vendor/camping-2.0.20090212/test/apps/misc.rb +86 -0
  44. data/vendor/camping-2.0.20090212/test/apps/sessions.rb +38 -0
  45. data/vendor/camping-2.0.20090212/test/test_camping.rb +54 -0
  46. metadata +128 -0
data/lib/picnic/cli.rb ADDED
@@ -0,0 +1,165 @@
1
+ require 'optparse'
2
+
3
+ require 'picnic'
4
+ require 'picnic/conf'
5
+ require 'picnic/server'
6
+
7
+ module Picnic
8
+ # Provides a command-line interface for your app.
9
+ # This is useful for creating a 'bin' file for launching your application.
10
+ #
11
+ # Usage example (put this in a file called 'foo'):
12
+ #
13
+ # #!/usr/bin/env ruby
14
+ #
15
+ # require 'rubygems'
16
+ # require 'picnic'
17
+ #
18
+ # require 'picnic/cli'
19
+ #
20
+ # cli = Picnic::Cli.new(
21
+ # 'foo',
22
+ # :app_path => "/path/to/foo.br"
23
+ # )
24
+ #
25
+ # cli.handle_cli_input
26
+ #
27
+ # Also see the ServiceControl class for info on how to use your cli script
28
+ # as a service.
29
+ class Cli
30
+ attr_accessor :app, :options
31
+
32
+ # Creates a new command-line interface handler.
33
+ #
34
+ # +app+:: The name of the application. This should match the name of the
35
+ # binary, which by default is expected to be in the same directory
36
+ # as the service control script.
37
+ # +options+:: A hash overriding default options. The options are:
38
+ # +app_file+:: The path to your application's main Ruby file.
39
+ # By default this is expected to be <tt>../lib/<app>.rb</tt>
40
+ # +pid_file+:: Where the app's PID file (containing the app's
41
+ # process ID) should be placed. By default this is
42
+ # <tt>/etc/<app>/<app>.pid</tt>
43
+ def initialize(app, options = {})
44
+ @app = app
45
+
46
+ @options = options || {}
47
+ @options[:app_file] ||= File.expand_path(File.dirname(File.expand_path($0))+"/../lib/#{app}.rb")
48
+ @options[:app_name] ||= app
49
+ @options[:app_module] ||= app.capitalize
50
+ @options[:pid_file] ||= "/etc/#{app}/#{app}.pid"
51
+ @options[:conf_file] ||= nil
52
+ end
53
+
54
+ # Parses command line options given to the script.
55
+ def handle_cli_input
56
+ if File.exists? options[:app_file]
57
+ # try to use given app base path
58
+ $APP_ROOT = File.dirname(options[:app_file]).gsub(/\/(lib|bin)\/?$/, '')
59
+ else
60
+ require 'rubygems'
61
+
62
+ # fall back to using gem installation
63
+ matches = Gem::source_index.find_name(app)
64
+ raise LoadError, "#{app} gem doesn't appear to be installed!" if matches.empty?
65
+
66
+ gem_spec = matches.last
67
+ $APP_ROOT = gem_spec.full_gem_path
68
+
69
+ gem(app)
70
+ end
71
+
72
+ $: << $APP_ROOT+"/lib"
73
+
74
+ $PID_FILE = @options[:pid_file]
75
+ $CONFIG_FILE = @options[:conf_file]
76
+ $VERBOSE = @options[:verbose]
77
+
78
+ opts = OptionParser.new do |opts|
79
+ opts.banner = "Usage: #{File.basename($0)} app.rb"
80
+ opts.define_head "#{File.basename($0)}, the microframework ON-button for ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
81
+ opts.separator ""
82
+ opts.separator "Application options:"
83
+
84
+ opts.on("-d", "--daemonize", "Run daemonized in the background") do
85
+ $DAEMONIZE = true
86
+ end
87
+ opts.on("-c", "--config FILE", "Use this config file (default is /etc/<app>/config.yml)") do |c|
88
+ puts "Using config file #{c.inspect}"
89
+ $CONFIG_FILE = c
90
+ end
91
+ opts.on("-P", "--pid_file FILE", "Path to pid file (used only when running daemonized; default is /etc/<app>/<app>.pid)") do |p|
92
+ if $DAEMONIZE && !File.exists?(p)
93
+ puts "Using pid file #{p.inspect}"
94
+ $PID_FILE = p
95
+ elsif File.exists?(p)
96
+ puts "The pid file already exists. Is #{app} running?\n" +
97
+ "You will have to first manually remove the pid file at '#{p}' to start the server as a daemon."
98
+ exit 1
99
+ else
100
+ puts "Not running as daemon. Ignoring pid option"
101
+ end
102
+ end
103
+
104
+ # optoinal block with additonal opts.on() calls specific to your application
105
+ if @options[:extra_cli_options]
106
+ @options[:extra_cli_options].call(opts)
107
+ end
108
+
109
+ opts.separator ""
110
+ opts.separator "Picnic options:"
111
+
112
+ # No argument, shows at tail. This will print an options summary.
113
+ # Try it and see!
114
+ opts.on_tail("-h", "--help", "Show this message") do
115
+ puts opts
116
+ exit
117
+ end
118
+
119
+ opts.on_tail("-v", "--version", "Show the application's version number") do
120
+ require "#{$APP_ROOT}/lib/#{app}/version.rb"
121
+ app_mod = Object.const_get(@options[:app_module])
122
+ puts "#{app}-#{app_mod::VERSION::STRING}"
123
+ exit
124
+ end
125
+ end
126
+
127
+ begin
128
+ opts.parse! ARGV
129
+ rescue OptionParser::ParseError => ex
130
+ STDERR.puts "!! #{ex.message}"
131
+ puts "** use `#{File.basename($0)} --help` for more details..."
132
+ exit 1
133
+ end
134
+
135
+
136
+ $CONF = Picnic::Conf.new
137
+ $CONF.load_from_file(app, $APP_ROOT, $CONF_FILE)
138
+
139
+ if $DAEMONIZE
140
+ # TODO: use Process.daemon when RUBY_VERSION >= 1.9
141
+
142
+ exit if fork
143
+ Process.setsid
144
+ exit if fork
145
+
146
+ Dir.chdir $APP_ROOT
147
+ File.umask 0000
148
+
149
+ STDIN.reopen "/dev/null"
150
+ STDOUT.reopen "/dev/null", "a"
151
+ STDERR.reopen "/dev/null", "a"
152
+
153
+ if $PID_FILE
154
+ File.open($PID_FILE, 'w'){ |f| f.write("#{Process.pid}") }
155
+ at_exit { File.delete($PID_FILE) if File.exist?($PID_FILE) }
156
+ end
157
+ end
158
+
159
+ server = Picnic::Server::Base.new($CONF, [options[:app_file]])
160
+ server.start
161
+ end
162
+ end
163
+ end
164
+
165
+
@@ -0,0 +1,135 @@
1
+ require 'active_support'
2
+
3
+ module Picnic
4
+ # Provides an interface for accessing your Picnic app's configuration file.
5
+ #
6
+ # Usage example:
7
+ #
8
+ # # Load the configuration from /etc/foo/config.yml
9
+ # Conf.load('foo')
10
+ #
11
+ # # The contents of config.yml is now available as follows:
12
+ # puts Conf[:server]
13
+ # puts Conf[:authentication][:username]
14
+ # # ... etc.
15
+ class Conf
16
+ def initialize(from_hash = {})
17
+ @conf = HashWithIndifferentAccess.new(from_hash)
18
+
19
+ @conf[:log] ||= HashWithIndifferentAccess.new
20
+ @conf[:log].merge!(:file => STDOUT, :level => 'DEBUG')
21
+
22
+ @conf[:uri_path] ||= "/"
23
+ end
24
+
25
+ # Read a configuration option.
26
+ #
27
+ # For example:
28
+ # puts Conf[:server]
29
+ def [](key)
30
+ @conf[key]
31
+ end
32
+
33
+ # Another way of reading a configuration option.
34
+ #
35
+ # The following statements are equivalent:
36
+ # puts Conf[:server]
37
+ # puts Conf.server
38
+ def method_missing(method, *args)
39
+ self[method]
40
+ end
41
+
42
+ # Needs to be defined when we have a custom method_missing().
43
+ def respond_to?(method)
44
+ (@conf.stringify_keys.keys).include?(method.to_s) || super
45
+ end
46
+
47
+ # Returns the path to your application's example config file.
48
+ #
49
+ # The example config file should be in the root directory of
50
+ # your application's distribution package and should be called
51
+ # <tt>config.example.yml</tt>. This file is used as a template
52
+ # for your app's configuration, to be customized by the end
53
+ # user.
54
+ def example_config_file_path(app_root)
55
+ "#{app_root}/config.example.yml"
56
+ end
57
+
58
+ # Copies the example config file into the appropriate
59
+ # configuration directory.
60
+ #
61
+ # +app_name+:: The name of your application. For example: <tt>foo</tt>
62
+ # +app_root+:: The path to your application's root directory. For example: <tt>/srv/www/camping/foo/</tt>
63
+ # +dest_conf_file:: The path where the example conf file should be copied to.
64
+ # For example: <tt>/etc/foo/config.yml</tt>
65
+ def copy_example_config_file(app_name, app_root, dest_conf_file)
66
+ require 'fileutils'
67
+
68
+ example_conf_file = example_config_file_path(app_root)
69
+
70
+ puts "\n#{app_name.to_s.upcase} SERVER HAS NOT YET BEEN CONFIGURED!!!\n"
71
+ puts "\nAttempting to copy sample configuration from '#{example_conf_file}' to '#{dest_conf_file}'...\n"
72
+
73
+ unless File.exists? example_conf_file
74
+ puts "\nThe example conf file does not exist! The author of #{app_name} may have forgotten to include it. You'll have to create the config file manually.\n"
75
+ exit 2
76
+ end
77
+
78
+ begin
79
+ dest_conf_file_dir = File.dirname(dest_conf_file)
80
+ FileUtils.mkpath(dest_conf_file_dir) unless File.exists? dest_conf_file_dir
81
+ FileUtils.cp(example_conf_file, dest_conf_file)
82
+ rescue Errno::EACCES
83
+ puts "\nIt appears that you do not have permissions to create the '#{dest_conf_file}' file. Try running this command using sudo (as root).\n"
84
+ exit 2
85
+ rescue => e
86
+ puts "\nFor some reason the '#{dest_conf_file}' file could not be created (#{e})."
87
+ puts "You'll have to copy the file manually. Use '#{example_conf_file}' as a template.\n"
88
+ exit 2
89
+ end
90
+
91
+ puts "\nA sample configuration has been created for you in '#{dest_conf_file}'. Please edit this file to" +
92
+ " suit your needs and then run #{app_name} again.\n"
93
+ exit 1
94
+ end
95
+
96
+ # Loads the configuration from the YAML file for the given app.
97
+ #
98
+ # <tt>app_name</tt> should be the name of your app; for example: <tt>foo</tt>
99
+ # <tt>app_root</tt> should be the path to your application's root directory; for example:: <tt>/srv/www/camping/foo/</tt>
100
+ # [<tt>config_file</tt>] can be the path to an alternate location for the config file to load
101
+ #
102
+ # By default, the configuration will be loaded from <tt>/etc/<app_name>/config.yml</tt>.
103
+ def load_from_file(app_name, app_root, config_file = nil)
104
+ conf_file = config_file || "/etc/#{app_name.to_s.downcase}/config.yml"
105
+
106
+ puts "Loading configuration for #{app_name.inspect} from #{conf_file.inspect}..."
107
+
108
+ begin
109
+ conf_file = etc_conf = conf_file
110
+ unless File.exists? conf_file
111
+ # can use local config.yml file in case we're running non-gem installation
112
+ conf_file = "#{app_root}/config.yml"
113
+ end
114
+
115
+ unless File.exists? conf_file
116
+ copy_example_config_file(app_name, app_root, etc_conf)
117
+ end
118
+
119
+ loaded_conf = HashWithIndifferentAccess.new(YAML.load_file(conf_file))
120
+
121
+ @conf.merge!(loaded_conf)
122
+
123
+ rescue => e
124
+ raise "Your #{app_name} configuration may be invalid."+
125
+ " Please double-check check your config.yml file."+
126
+ " Make sure that you are using spaces instead of tabs for your indentation!!" +
127
+ "\n\nTHE UNDERLYING ERROR WAS:\n#{e.inspect}"
128
+ end
129
+ end
130
+
131
+ def merge_defaults(defaults)
132
+ @conf = HashWithIndifferentAccess.new(HashWithIndifferentAccess.new(defaults).merge(@conf))
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,4 @@
1
+ module Picnic
2
+ module Controllers
3
+ end
4
+ end
@@ -0,0 +1,41 @@
1
+ require 'logger'
2
+
3
+ module Picnic
4
+ module Logger
5
+
6
+ # Makes available a Logger instance under the global $LOG variable.
7
+ def init_global_logger!
8
+ logdev = ($CONF && $CONF.log[:file]) || STDOUT
9
+ $LOG = Picnic::Logger::Base.new(logdev)
10
+ $LOG.level = Picnic::Logger::Base.const_get(($CONF && $CONF.log[:level]) || 'DEBUG')
11
+
12
+ puts "Initialized global logger to #{logdev.inspect}."
13
+ end
14
+ module_function :init_global_logger!
15
+
16
+ class Base < ::Logger
17
+ def initialize(logdev, shift_age = 0, shift_size = 1048576)
18
+ begin
19
+ super
20
+ rescue Exception
21
+ puts "WARNING: Couldn't create Logger with output '#{logdev}'. Logger output will be redirected to STDOUT."
22
+ super(STDOUT, shift_age, shift_size)
23
+ end
24
+ end
25
+
26
+ def format_message(severity, datetime, progrname, msg)
27
+ (@formatter || @default_formatter).call(severity, datetime, progname, msg)
28
+ end
29
+ end
30
+
31
+ # Custom log formatter used by the Picnic Logger.
32
+ class Formatter < ::Logger::Formatter
33
+ Format = "[%s#%d] %5s -- %s: %s\n"
34
+
35
+ def call(severity, time, progname, msg)
36
+ Format % [format_datetime(time), $$, severity, progname,
37
+ msg2str(msg)]
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,98 @@
1
+ require 'camping/server'
2
+
3
+ module Picnic::Server
4
+ class Base < Camping::Server::Base
5
+ def start
6
+ handler, conf = case @conf.server
7
+ when "console"
8
+ ARGV.clear
9
+ IRB.start
10
+ exit
11
+ when "mongrel"
12
+ prep_mongrel
13
+ when "webrick"
14
+ prep_webrick
15
+ end
16
+
17
+ rapp = apps.first
18
+
19
+ if @conf.uri_path
20
+ rapp = Rack::URLMap.new(@conf.uri_path => rapp)
21
+ end
22
+
23
+ rapp = Rack::ContentLength.new(rapp)
24
+ rapp = FixContentLength.new(rapp)
25
+ rapp = Rack::Lint.new(rapp)
26
+ rapp = Camping::Server::XSendfile.new(rapp)
27
+ rapp = Rack::ShowExceptions.new(rapp)
28
+
29
+ handler.run(rapp, conf)
30
+ end
31
+
32
+
33
+ private
34
+
35
+ def prep_webrick
36
+ handler = Rack::Handler::WEBrick
37
+ options = {
38
+ :BindAddress => @conf.bind_address || "0.0.0.0",
39
+ :Port => @conf.port
40
+ }
41
+
42
+ cert_path = @conf.ssl_cert
43
+ key_path = @conf.ssl_key || @conf.ssl_cert
44
+ # look for the key in the ssl_cert if no ssl_key is specified
45
+
46
+ unless cert_path.nil? && key_path.nil?
47
+ raise "The specified certificate file #{cert_path.inspect} does not exist or is not readable. " +
48
+ " Your 'ssl_cert' configuration setting must be a path to a valid " +
49
+ " ssl certificate." unless
50
+ File.exists? cert_path
51
+
52
+ raise "The specified key file #{key_path.inspect} does not exist or is not readable. " +
53
+ " Your 'ssl_key' configuration setting must be a path to a valid " +
54
+ " ssl private key." unless
55
+ File.exists? key_path
56
+
57
+ require 'openssl'
58
+ require 'webrick/https'
59
+
60
+ cert = OpenSSL::X509::Certificate.new(File.read(cert_path))
61
+ key = OpenSSL::PKey::RSA.new(File.read(key_path))
62
+
63
+ options[:SSLEnable] = true
64
+ options[:SSLVerifyClient] = ::OpenSSL::SSL::VERIFY_NONE
65
+ options[:SSLCertificate] = cert
66
+ options[:SSLPrivateKey] = key
67
+ end
68
+
69
+ return handler, options
70
+ end
71
+
72
+
73
+ def prep_mongrel
74
+ handler = Rack::Handler::Mongrel
75
+ options = {
76
+ :Host => @conf.bind_address || "0.0.0.0",
77
+ :Port => @conf.port
78
+ }
79
+
80
+ return handler, options
81
+ end
82
+
83
+ end
84
+
85
+ class FixContentLength
86
+ def initialize(app)
87
+ @app = app
88
+ end
89
+
90
+ def call(env)
91
+ status, headers, body = @app.call(env)
92
+ if headers.has_key?('Content-Length') && headers['Content-Length'].to_i == 0
93
+ headers['Content-Length'] = body.body.length.to_s
94
+ end
95
+ [status, headers, body]
96
+ end
97
+ end
98
+ end