Project

General

Profile

Upgrading Redmine 1.3.1 to 1.4.5 » cgi.rb

Ruby187\lib\ruby\gems\1.8\gems\mongrel-1.1.5-x86-mingw32\lib\mongrel\cgi.rb - Vincent Lizzi, 2012-11-19 06:48

 
1
# Copyright (c) 2005 Zed A. Shaw 
2
# You can redistribute it and/or modify it under the same terms as Ruby.
3
#
4
# Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html 
5
# for more information.
6

    
7
require 'cgi'
8

    
9
module Mongrel
10
  # The beginning of a complete wrapper around Mongrel's internal HTTP processing
11
  # system but maintaining the original Ruby CGI module.  Use this only as a crutch
12
  # to get existing CGI based systems working.  It should handle everything, but please
13
  # notify me if you see special warnings.  This work is still very alpha so I need 
14
  # testers to help work out the various corner cases.
15
  #
16
  # The CGIWrapper.handler attribute is normally not set and is available for 
17
  # frameworks that need to get back to the handler.  Rails uses this to give
18
  # people access to the RailsHandler#files (DirHandler really) so they can
19
  # look-up paths and do other things with the files managed there.
20
  #
21
  # In Rails you can get the real file for a request with:
22
  #
23
  #  path = @request.cgi.handler.files.can_serve(@request['PATH_INFO'])
24
  #
25
  # Which is ugly but does the job.  Feel free to write a Rails helper for that.
26
  # Refer to DirHandler#can_serve for more information on this.
27
  class CGIWrapper < ::CGI
28
    public :env_table
29
    attr_reader :options
30
    attr_accessor :handler
31
    # Set this to false if you want calls to CGIWrapper.out to not actually send
32
    # the response until you force it.
33
    attr_accessor :default_really_final
34

    
35
    # these are stripped out of any keys passed to CGIWrapper.header function
36
    REMOVED_KEYS = [ "nph","status","server","connection","type",
37
                     "charset","length","language","expires"]
38

    
39
    # Takes an HttpRequest and HttpResponse object, plus any additional arguments
40
    # normally passed to CGI.  These are used internally to create a wrapper around
41
    # the real CGI while maintaining Mongrel's view of the world.
42
    def initialize(request, response, *args)
43
      @request = request
44
      @response = response
45
      @args = *args
46
      @input = request.body
47
      @head = {}
48
      @out_called = false
49
      @default_really_final=true
50
      super(*args)
51
    end
52
    
53
    # The header is typically called to send back the header.  In our case we
54
    # collect it into a hash for later usage.
55
    #
56
    # nph -- Mostly ignored.  It'll output the date.
57
    # connection -- Completely ignored.  Why is CGI doing this?
58
    # length -- Ignored since Mongrel figures this out from what you write to output.
59
    # 
60
    def header(options = "text/html")
61
      # if they pass in a string then just write the Content-Type
62
      if options.class == String
63
        @head['Content-Type'] = options unless @head['Content-Type']
64
      else
65
        # convert the given options into what Mongrel wants
66
        @head['Content-Type'] = options['type'] || "text/html"
67
        @head['Content-Type'] += "; charset=" + options['charset'] if options.has_key? "charset" if options['charset']
68
        
69
        # setup date only if they use nph
70
        @head['Date'] = CGI::rfc1123_date(Time.now) if options['nph']
71

    
72
        # setup the server to use the default or what they set
73
        @head['Server'] = options['server'] || env_table['SERVER_SOFTWARE']
74

    
75
        # remaining possible options they can give
76
        @head['Status'] = options['status'] if options['status']
77
        @head['Content-Language'] = options['language'] if options['language']
78
        @head['Expires'] = options['expires'] if options['expires']
79

    
80
        # drop the keys we don't want anymore
81
		# these two lines added based on https://rails.lighthouseapp.com/projects/8994/tickets/4690
82
        @head['cookie'] = options['cookie'] if options['cookie']
83
        options.delete('cookie')
84
        REMOVED_KEYS.each {|k| options.delete(k) }
85

    
86
        # finally just convert the rest raw (which puts 'cookie' directly)
87
        # 'cookie' is translated later as we write the header out
88
        options.each{|k,v| @head[k] = v}
89
      end
90

    
91
      # doing this fakes out the cgi library to think the headers are empty
92
      # we then do the real headers in the out function call later
93
      ""
94
    end
95

    
96
    # Takes any 'cookie' setting and sends it over the Mongrel header,
97
    # then removes the setting from the options. If cookie is an 
98
    # Array or Hash then it sends those on with .to_s, otherwise
99
    # it just calls .to_s on it and hopefully your "cookie" can
100
    # write itself correctly.
101
    def send_cookies(to)
102
      # convert the cookies based on the myriad of possible ways to set a cookie
103
      if @head['cookie']
104
        cookie = @head['cookie']
105
        case cookie
106
        when Array
107
          cookie.each {|c| to['Set-Cookie'] = c.to_s }
108
        when Hash
109
          cookie.each_value {|c| to['Set-Cookie'] = c.to_s}
110
        else
111
          to['Set-Cookie'] = options['cookie'].to_s
112
        end
113
        
114
        @head.delete('cookie')
115
      end
116
      
117
      # @output_cookies seems to never be used, but we'll process it just in case
118
      @output_cookies.each {|c| to['Set-Cookie'] = c.to_s } if @output_cookies
119
    end
120
    
121
    # The dumb thing is people can call header or this or both and in any order.
122
    # So, we just reuse header and then finalize the HttpResponse the right way.
123
    # Status is taken from the various options and converted to what Mongrel needs
124
    # via the CGIWrapper.status function.
125
    #
126
    # We also prevent Rails from actually doing the final send by adding a
127
    # second parameter "really_final".  Only Mongrel calls this after Rails
128
    # is done.  Since this will break other frameworks, it defaults to 
129
    # a different setting for rails (false) and (true) for others.
130
    def out(options = "text/html", really_final=@default_really_final)
131
      if @out_called || !really_final
132
        # don't do it more than once or if it's not the really final call
133
        return
134
      end
135

    
136
      header(options)
137

    
138
      @response.start status do |head, body|
139
        send_cookies(head)
140
        
141
        @head.each {|k,v| head[k] = v}
142
        body.write(yield || "")
143
      end
144

    
145
      @out_called = true
146
    end
147
    
148
    # Computes the status once, but lazily so that people who call header twice
149
    # don't get penalized.  Because CGI insists on including the options status 
150
    # message in the status we have to do a bit of parsing.
151
    def status
152
      if not @status
153
        stat = @head["Status"]
154
        stat = stat.split(' ')[0] if stat
155

    
156
        @status = stat || "200"
157
      end
158

    
159
      @status
160
    end
161

    
162
    # Used to wrap the normal args variable used inside CGI.
163
    def args
164
      @args
165
    end
166
    
167
    # Used to wrap the normal env_table variable used inside CGI.
168
    def env_table
169
      @request.params
170
    end
171
    
172
    # Used to wrap the normal stdinput variable used inside CGI.
173
    def stdinput
174
      @input
175
    end
176
    
177
    # The stdoutput should be completely bypassed but we'll drop a warning just in case
178
    def stdoutput
179
      STDERR.puts "WARNING: Your program is doing something not expected.  Please tell Zed that stdoutput was used and what software you are running.  Thanks."
180
      @response.body
181
    end    
182

    
183
  end
184
end
(2-2/2)