CGI help

So, I am trying ot read the contents of a file and format the contents
there into a CGI form. At 6PM on A friday hough, I am just not seeing
my errors - appreciate another srt of eyes!

require "cgi"

Filename = 'classification.txt'

EMPTY_STRING = ''
TITLE = 'Vulnerability Classification'
cgi = CGI.new('html4')
output = cgi.html do
   cgi.head { cgi.title { TITLE } } +
   cgi.body { cgi.h1 { TITLE } } +
   cgi.form('post') do
      if File.readable?(Filename) then
          f = File.open(Filename,"r")
          f.each_line { |l| l.chomp
              inputs = l.split(',')
              puts inputs[0].to_s + ": "
              opts = "\"" + inputs[1].to_s + "\""
              2.times { inputs.delete_at(0) }
              until inputs.empty? do
                 opts = opts + "[\"" + inputs[1].to_s + "\",\"" +
inputs[0].to_s + "\"]"
                 2.times { inputs.delete_at(0) }
              end
              cgi.popup_menu(opts) +
              cgi.br +
          }
          f.close
      end
    cgi.submit
   end
end
cgi.out { output.gsub('><', ">\n<") }

···

--
Posted via http://www.ruby-forum.com/.

Jeff Leggett wrote:

So, I am trying ot read the contents of a file and format the contents
there into a CGI form. At 6PM on A friday hough, I am just not seeing
my errors - appreciate another srt of eyes!

Your file may need to start with a shebang line:

#!/usr/local/bin/ruby

or whatever the path to ruby on your system is.

Also, print out the correct headers

http://www.ruby-doc.org/docs/ProgrammingRuby/html/web.html

It helps to get the simplest possible CGI script running first, then adding details, since debugging CGI is a painful.

···

--
James Britt

www.jamesbritt.com - Playing with Better Toys
www.ruby-doc.org - Ruby Help & Documentation
www.rubystuff.com - The Ruby Store for Ruby Stuff
www.neurogami.com - Smart application development

Jeff Leggett wrote:

output = cgi.html do
   cgi.head { cgi.title { TITLE } } +
   cgi.body { cgi.h1 { TITLE } } +

How about getting rid of.........^ ?

···

--
Posted via http://www.ruby-forum.com/\.

James Britt wrote:

Your file may need to start with a shebang line:

#!/usr/local/bin/ruby

Yes, it does - I just left that out of the C&P.

Also, print out the correct headers

Programming Ruby: The Pragmatic Programmer's Guide

The CGI does all that for you... My problem is if I take out the inner
loop (starting with "if File.readable?(Filename) then" it works fine. I
just can't for the life of me see the syntax errors.

[jleggett@binford cgi-bin]$ ./vuln.rb
./vuln.rb:27: syntax error
./vuln.rb:29: syntax error
      end
         ^
./vuln.rb:31: syntax error
   end
      ^
./vuln.rb:37: syntax error
[jleggett@binford cgi-bin]$

···

--
Posted via http://www.ruby-forum.com/\.

7stud -- wrote:

Jeff Leggett wrote:

output = cgi.html do
   cgi.head { cgi.title { TITLE } } +
   cgi.body { cgi.h1 { TITLE } } +

How about getting rid of.........^ ?

I changed it like that, EXACT same errors. I have matched up the 'ends'
and bracket more times than I can count now, even slept on it, thinking
my tired brain would see it right off this morning, but no... Thanks for
your help though guys...

#!/usr/bin/ruby

require "cgi"

Filename = 'classification.txt'

EMPTY_STRING = ''
TITLE = 'Vulnerability Classification'
cgi = CGI.new('html4')
output = cgi.html do
   cgi.head { cgi.title { TITLE } } +
   cgi.body { cgi.h1 { TITLE } +
   cgi.form('post') do
      if File.readable?(Filename) then
          f = File.open(Filename,"r")
          f.each_line { |l| l.chomp
              inputs = l.split(',')
              puts inputs[0].to_s + ": "
              opts = "\"" + inputs[1].to_s + "\""
              2.times { inputs.delete_at(0) }
              until inputs.empty? do
                 opts = opts + "[\"" + inputs[1].to_s + "\",\"" +
inputs[0].to_s + "\"]"
                 2.times { inputs.delete_at(0) }
              end
              cgi.popup_menu(opts) +
              cgi.br +
          }
          f.close
      end
    cgi.submit
   end
   }
end
cgi.out { output.gsub('><', ">\n<") }

[jleggett@binford cgi-bin]$ ./vuln.rb
./vuln.rb:27: syntax error
./vuln.rb:29: syntax error
      end
         ^
./vuln.rb:31: syntax error
   end
      ^
./vuln.rb:38: syntax error
[jleggett@binford cgi-bin]$

···

--
Posted via http://www.ruby-forum.com/\.

             cgi.popup_menu(opts) +
             cgi.br +

You have an extraneous '+' at the end of that last line. Remove it and your
script should start working.

Cheers,
Doug Seifert

Jeff Leggett wrote:

7stud -- wrote:

Jeff Leggett wrote:

output = cgi.html do
   cgi.head { cgi.title { TITLE } } +
   cgi.body { cgi.h1 { TITLE } } +

How about getting rid of.........^ ?

I changed it like that, EXACT same errors. I have matched up the 'ends'
and bracket more times than I can count now, even slept on it, thinking
my tired brain would see it right off this morning, but no... Thanks for
your help though guys...

#!/usr/bin/ruby

require "cgi"

Filename = 'classification.txt'

EMPTY_STRING = ''
TITLE = 'Vulnerability Classification'
cgi = CGI.new('html4')
output = cgi.html do
   cgi.head { cgi.title { TITLE } } +
   cgi.body { cgi.h1 { TITLE } +
   cgi.form('post') do
      if File.readable?(Filename) then
          f = File.open(Filename,"r")
          f.each_line { |l| l.chomp
              inputs = l.split(',')
              puts inputs[0].to_s + ": "
              opts = "\"" + inputs[1].to_s + "\""
              2.times { inputs.delete_at(0) }
              until inputs.empty? do
                 opts = opts + "[\"" + inputs[1].to_s + "\",\"" +
inputs[0].to_s + "\"]"
                 2.times { inputs.delete_at(0) }
              end
              cgi.popup_menu(opts) +
              cgi.br +
          }
          f.close
      end
    cgi.submit
   end
   }
end
cgi.out { output.gsub('><', ">\n<") }

[jleggett@binford cgi-bin]$ ./vuln.rb
./vuln.rb:27: syntax error
./vuln.rb:29: syntax error
      end
         ^
./vuln.rb:31: syntax error
   end
      ^
./vuln.rb:38: syntax error
[jleggett@binford cgi-bin]$

Putting these lines:

cgi.popup_menu(opts) +
cgi.br +

inside the if statement doesn't work for me: I get a bunch of kEND
errors. If I move those lines outside the if statement, then no errors:

cgi = CGI.new('html4')
output = cgi.html {
  cgi.head { cgi.title { TITLE } } +
  cgi.body { cgi.h1 { TITLE } +
    cgi.form('post') {
      if File.readable?(Filename)
        f = File.open(Filename,"r")
        opts = ""

        f.each_line do |l|
          l.chomp #does nothing
          inputs = l.split(',')
          puts inputs[0].to_s + ": "
          opts << "\"" + inputs[1].to_s + "\""
          2.times { inputs.delete_at(0) }
          until inputs.empty?
            opts << "[\"" + inputs[1].to_s + "\",\"" + inputs[0].to_s +
"\"]"
            2.times { inputs.delete_at(0) }
          end
        end #each_line

        f.close
      end #if

      cgi.popup_menu(opts) +
      cgi.br +
      cgi.submit
    } #form

  } #cgi.body
} #cgi.html

cgi.out { output.gsub('><', ">\n<") }

I have no idea why that is the case.

···

--
Posted via http://www.ruby-forum.com/\.

Douglas Seifert wrote:

             cgi.popup_menu(opts) +
             cgi.br +

You have an extraneous '+' at the end of that last line. Remove it and
your
script should start working.

Cheers,
Doug Seifert

*SIGH* Sure enough that fixed the syntax errors... Darn thing still
doesn't work though :frowning: Writes the h1 TITLE, and the submit, nothing in
between...

My own fault trying to learn a new language - done it in perl I'd been
done yesterday at lunch LOL

Thanks for helping the n00b guys.

···

--
Posted via http://www.ruby-forum.com/\.

7stud -- wrote:

I have no idea why that is the case.

Here is a simplification of the issue if anyone wants to offer some
advice. The following code produces no errors:

#!/usr/bin/ruby

require "cgi"

cgi = CGI.new('html4')
output = cgi.html {
  cgi.head { cgi.title { "Test" } } +
  cgi.body {
    cgi.form('post') {
      cgi.textarea() +
      cgi.submit
    } #form
  } #cgi.body
} #cgi.html

This code produces kEND errors:

#!/usr/bin/ruby

require "cgi"

cgi = CGI.new('html4')
output = cgi.html {
  cgi.head { cgi.title { "Test" } } +
  cgi.body {
    cgi.form('post') {
      if true
        cgi.textarea() +
      end
      cgi.submit
    } #form
  } #cgi.body
} #cgi.html

···

--
Posted via http://www.ruby-forum.com/\.

*SIGH* Sure enough that fixed the syntax errors... Darn thing still
doesn't work though :frowning: Writes the h1 TITLE, and the submit, nothing in
between...

Can you post the contents of classification.txt? Some sample data would
help. Is the file readable by the web server process? Are you sure that
the working directory when the cgi is run is such that opening
classification.txt with no other path info will work ( puts Dir.pwd ) ...?

-Doug Seifert

7stud -- wrote:

This code produces kEND errors:

#!/usr/bin/ruby

require "cgi"

cgi = CGI.new('html4')
output = cgi.html {
  cgi.head { cgi.title { "Test" } } +
  cgi.body {
    cgi.form('post') {
      if true
        cgi.textarea() +
      end
      cgi.submit
    } #form
  } #cgi.body
} #cgi.html

So does this:

#!/usr/bin/ruby

require "cgi"

cgi = CGI.new('html4')
output = cgi.html {
  cgi.head { cgi.title { "Test" } } +
  cgi.body {
    cgi.form('post') {
      if true
        cgi.textarea() +
      else
        cgi.textarea() +
      end

      cgi.submit
    } #form
  } #cgi.body
} #cgi.html

···

--
Posted via http://www.ruby-forum.com/\.

Douglas Seifert wrote:

*SIGH* Sure enough that fixed the syntax errors... Darn thing still
doesn't work though :frowning: Writes the h1 TITLE, and the submit, nothing in
between...

Can you post the contents of classification.txt? Some sample data would
help. Is the file readable by the web server process? Are you sure
that
the working directory when the cgi is run is such that opening
classification.txt with no other path info will work ( puts Dir.pwd )
...?

-Doug Seifert

[jleggett@binford cgi-bin]$ cat classification.txt
Access Control,access,High,0,Medium,5,Low,10
Authentication,auth,High,0,Medium,5,Low,10
Confidentiality Impact,confi,High,10,Medium,5,Low,0
Confidentiality modifier,confm,Employee Data,30,Customer
Data,20,System/network Data,10,application metadata,5,N/A,0
integrity impact,integi,High,10,Medium,5,Low,0
integrity modifier,integm,System/Application,30,Customer
Information,20,Employee Info,30,Individual Info,10,N/A,0
Availability Impact,avail,High,10,medium,5,Low,0
[jleggett@binford cgi-bin]$

Yeah I added an else to the File.readable link to make sure it's
there... it's there... the problem seems to be now it's not building the
CGI all up... I get errors again.

  1 #!/usr/bin/ruby

     2 require "cgi"

     3 Filename = 'classification.txt'

     4 EMPTY_STRING = ''
     5 TITLE = 'Vulnerability Classification'
     6 cgi = CGI.new('html4')
     7 output = cgi.html do
     8 cgi.head { cgi.title { TITLE } } +
     9 cgi.body { cgi.h1 { TITLE } +
    10 cgi.form('post', 'http://binford.x.com/cgi-bin/vulnclass.rb&#39;\)
do
    11 if File.readable?(Filename) then
    12 f = File.open(Filename,"r")
    13 f.each_line { |l| l.chomp
    14 inputs = l.split(',')
    15 cgi.p { inputs[0].to_s + ": " } +
    16 #opts = "\"" + inputs[1].to_s + "\""
    17 2.times { inputs.delete_at(0) }
    18 until inputs.empty? do
    19 opts = opts + "[\"" + inputs[1].to_s + "\",\""
+ inputs[0].to_s + "\"]"
    20 2.times { inputs.delete_at(0) }
    21 end
    22 # puts opts
    23 cgi.popup_menu(opts) +
    24 cgi.br
    25 }
    26 f.close
    27 else
    28 puts "File not read-able!\n"
    29 end
    30 cgi.submit
    31 end
    32 }
    33 end
    34 cgi.out { output.gsub('><', ">\n<") }

Produces:

[jleggett@binford cgi-bin]$ ./vuln.rb
(offline mode: enter name=value pairs on standard input)
./vuln.rb:20:in `+': can't convert Fixnum into String (TypeError)
        from ./vuln.rb:20
        from ./vuln.rb:16:in `each_line'
        from ./vuln.rb:16
        from /usr/lib/ruby/1.8/cgi.rb:1557:in `form'
        from ./vuln.rb:13
        from (eval):1022:in `body'
        from ./vuln.rb:12
        from /usr/lib/ruby/1.8/cgi.rb:1657:in `html'
        from (eval):1006:in `html'
        from /usr/lib/ruby/1.8/cgi.rb:1657:in `html'
        from ./vuln.rb:10
[jleggett@binford cgi-bin]$

···

--
Posted via http://www.ruby-forum.com/\.

> cgi.textarea() +

You have a trailing + and have not provided the second argument in all the
examples that fail.

[jleggett@binford cgi-bin]$ cat classification.txt
Access Control,access,High,0,Medium,5,Low,10
Authentication,auth,High,0,Medium,5,Low,10
Confidentiality Impact,confi,High,10,Medium,5,Low,0
Confidentiality modifier,confm,Employee Data,30,Customer
Data,20,System/network Data,10,application metadata,5,N/A,0
integrity impact,integi,High,10,Medium,5,Low,0
integrity modifier,integm,System/Application,30,Customer
Information,20,Employee Info,30,Individual Info,10,N/A,0
Availability Impact,avail,High,10,medium,5,Low,0
[jleggett@binford cgi-bin]$

OK, after figuring out how CGI works in ruby ... there are some problems
with your original code:

1) cgi.body { cgi.h1 { TITLE } }

The above will generate a body tag with a h1 tag and then close the body. I
think you wanted to defer that closing brace until after the form was
generated.

2) The block passed to the form method must evaluate to a string which will
be the form's contents. Your block will evaluate to the return value of
File.close (because this is the last statement executed by the block). close
returns nil, which when coerced to a string would be "" (the empty string).
Thus, your form will have no content.

3) popup_menu takes a String as the first argument which is the name of the
select tag and then an arbitrary number of arguments representing the
options. I think you want to use Arrays as the arguments because you want
to specify an option value and option name. The code you wrote does not do
that. It just passes a big string to popup_menu as a single argument.

4) You are mixing puts with generating strings inside the CGI tag method
blocks. You need to make sure you don't use puts as it will corrupt the
HTML generated by the script by outputting stuff you don't want output.

I took a stab at correcting all these problems, and changed some minor
things, but didn't really try to rubyfy the code:

require "cgi"

Filename = 'classification.txt'

EMPTY_STRING = ''
TITLE = 'Vulnerability Classification'
cgi = CGI.new('html4')
output = cgi.html do
  cgi.head { cgi.title { TITLE } } +
  cgi.body do
    cgi.h1 { TITLE } +
    cgi.form('post') do
      form_contents = ""
      if File.readable?(Filename) then
        # Use the version of File#open that takes a block. That
        # way you don't have to worry about closing the file after
        # you are done with it -- it will happen automatically when
        # the block is done executing
        File.open(Filename,"r") do |f|
          f.each_line do |l|
            # Need to use chomp! instead of plain chomp to
            # ensure l is actually changed. Otherwise, we just
            # create and throw away a new string
            l.chomp!
            inputs = l.split(',')
            form_contents << inputs[0] + ": "
            select_name = inputs[1]
            select_opts =
            2.times { inputs.delete_at(0) }
            until inputs.empty? do
               select_opts << [inputs[1], inputs[0]]
               2.times { inputs.delete_at(0) }
            end
            form_contents << cgi.popup_menu(select_name, *select_opts) +
cgi.br
          end
        end
      end
      form_contents + cgi.submit
    end
  end
end

Douglas Seifert wrote:

> cgi.textarea() +

You have a trailing + and have not provided the second argument in all
the
examples that fail.

The second argument to +? What about cgi.submit? This works:

cgi.form('post') {
      cgi.textarea() +
      cgi.submit
    }

This produces kEND errors:

cgi.form('post') {
      if true
        cgi.textarea() +
      else
        cgi.textarea() +

      cgi.submit
    }

You can't do this in plain ruby:

str = "hello" +
" goodbye"

But the cgi syntax allows you to add things together like that.

···

--
Posted via http://www.ruby-forum.com/\.

Douglas Seifert wrote:

OK, after figuring out how CGI works in ruby ... there are some problems
with your original code:

WOW, thanks Doug! That was it totally... I had read use of the
destructive method (!) but didn't grok till I saw it... And the rest of
the way now makes prefect sense.

I appreciate all of yours help. I decided my perl only skills were
getting long in the tooth and decided I needed to pick up a truly OO
language, and learn it... but seems a lot harder than when learning new
languages did 20+ years ago.

···

--
Posted via http://www.ruby-forum.com/\.

cgi.form('post') {
     cgi.textarea() +
     cgi.submit
   }

The above works because the interpreter finds something on the next line to
add to the result of cgi.textarea().

This produces kEND errors:

cgi.form('post') {
     if true
       cgi.textarea() +
     else
       cgi.textarea() +

      cgi.submit
   }

The interpreter sees that + at the end of the line in the first branch of
the if statement and gets confused looking for something to add it to. It
would be nice if it could figure out that you wanted to add it to the result
of the statement that comes after the if statement, but that is not how it
works. You would need to do something like like this to get it to work:

(condition ? cgi.textarea() : cgi.textarea()) +
cgi.submit

You can't do this in plain ruby:

str = "hello" +
" goodbye"

The above works just fine. You end up with str being a reference to "hello
goodby".

But the cgi syntax allows you to add things together like that.

There is nothing magical about the cgi syntax. All that is happening is
that String objects are getting added together. To get it to work, you have
to ensure that the blocks passed to the various cgi methods end up
evaluating to the string you want the tag created by the block's method to
contain. You do that by making the last statement evaluated in the block be
the string you want as content.

-Doug Seifert

Douglas Seifert wrote:

You can't do this in plain ruby:

str = "hello" +
" goodbye"

The above works just fine. You end up with str being a reference to
"hello
goodby".

Hmmm...I must have done something wrong when I was testing that--because
now it works. In that case. the op's problem makes perfect sense. His
code was trying to do this:

str = "form element1 " +

if true
  "form element2 " +
end

"submit button"

which gives the kEND errors the op was seeing:

r1test.rb:5: syntax error, unexpected kEND
r1test.rb:10: syntax error, unexpected $end, expecting kEND

···

--
Posted via http://www.ruby-forum.com/\.

Douglas Seifert wrote:

The interpreter sees that + at the end of the line in the first branch
of
the if statement and gets confused looking for something to add it to.
It
would be nice if it could figure out that you wanted to add it to the
result
of the statement that comes after the if statement, but that is not how
it
works. You would need to do something like like this to get it to work:

(condition ? cgi.textarea() : cgi.textarea()) +
cgi.submit

You can just use 'if' that way too, as it returns a value, although its
low precedence means you'll need brackets:

  (
    if condition
      foo
    else
      bar
    end
  ) +
  baz

Personally I wouldn't try to write it this way; it's too error-prone as
has been demonstrated already. I think it would be clearer to append to
a target string in stages:

  str = ""
  if condition
    str << foo
  else
    str << baz
  end
  str << baz

Here, each line stands by itself.

But for any complex output it's probably better to forget about using
CGI methods to generate HTML, and use some sort of template (e.g. ERB or
HAML).

Admittedly, in a one-shot CGI environment, there's a bigger startup
overhead both in reading the template library and parsing the template,
for every request. But if performance is a concern, then you shouldn't
be using CGI anyway.

If you write your app using a simple framework like Sinatra, then you
can run it both as CGI and in a number of other environments, without
changing the app.

···

--
Posted via http://www.ruby-forum.com/\.