new rubycam version

P

Phil V.

I found that with my recent upgrade to ruby 1.8x, I received errors about
the untaint on ENV attributes. It appears that ENV is frozen, so I have
removed the untaints rather than work-out some high-maintenance comparison
switchy doodad. Anyhoo, I don't have my password for the ruby website
anymore and program far less now. But, here's the version that works with
the new changes. Future changes still at the rubycam home page
(http://www.nekophile.com/~rubycam/). (and yes, the RCS revisions
got screwed-up too, but at least it works - now pull-out your quickcam a
go go go!)




#!/usr/bin/env ruby

########################################################################
## VERSION: $Id: rubycam.rb,v 1.2 2003/10/13 21:05:27 pvoris Exp $
##
## AUTHOR: Phil Voris <rubycam at nekophile.com>
##
## LICENSE: Ruby License - must include this header comment block
## http://www.ruby-lang.org/en/LICENSE.txt
##
## DESCRIPTION:
## This CGI webcam script attempts to conserve resources by not
## creating images more often than the number of seconds indicated by
## the refresh setting. Maximum flexibility is given by allowing the
## administrator to set the image-producing command line. The
## defaults are arranged to use cqcam
## (http://www.cs.duke.edu/~reynolds/cqcam/).
##
## REQUIRES: ruby
## ruby modules: net/smtp (for error reporting), ftools
## rb2html.rb (for viewing source)
## some image-grabber, such as cqcam
## optionally, some image manipulation software
##
## USAGE:
## * Install under cgi-bin or wherever cgi executables are allowed.
## * Configure the global config section below.
## * Configure the default config section below.
## * Optionally create one or more config files to call in the PATH_INFO.
## * Ensure that img_file_web_directory exists and is writable by the
## web server
## * [See end of script for recommendations for config and calling from
## html.]
##
## TO DO:
## It would be nice to add caching. That is, deliver a header
## indicating that the page (the image) hasn't changed until it
## actually does. I attempted this, but found that
## HTTP_IF_MODIFIED_SINCE didn't appear in the environment. I then
## attempted to use a session to track if the use had seen the page
## with the current image - however sessions weren't quite working for
## me - perhaps someone else can resolve this issue.
########################################################################


#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# GLOBAL CONFIGURATION - EDIT HERE
#
# These options must be set
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

## allow options from URL (true / false)
use_config_files = true

## img file directory [relative to DOC_ROOT]
img_file_web_directory = '/img/cam'

## configuration files directory
config_dir = './config'

## directory where rb2html and associated files may be found
## (used for /view)
rb2html_directory = './rb2html-1.0'

## file base-name
lock_filename = 'rubycam.lock'

## maximum age to keep a lock file (seconds, must exceed refresh time)
max_lockfile_age = 500

## shows a little (R) which links to the source. Specify the target
## frame ('_new', '_self', etc) or nil to not display it.
source_link_target = '_new'

#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# END GLOBAL CONFIGURATION
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# PER-CAM CONFIGURATION - SET DEFAULTS HERE
# - MAY MODIFY IN CONFIG FILES
#
# Anything listed in this section may be set - as below - in a
# separate file.
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

## default_cqcam_opts
cmd_line = 'cqcam -r -q 25 -s 1 -j'

## filename for the images
img_filename = 'plain.jpg'

## admin email address
admin_email_address = 'webmaster@localhost'

## page title
title = 'Rubycam'

## background (color)
bgcolor = 'black'

## text (color)
text_color = 'yellow'

## browser refresh length (in seconds)
refresh = 60

## img_background_color (color | nil to disable globally)
img_background_color = nil

## randomize transparency_background_color (true / false)
use_randomize_img_background_color = false

## randomize transparency_background_color (true / false)
use_randomize_text_color = false

## match text and img backgrounds - useful for randomization
## (true / false)
text_color_matches_img_background_color = false

## color for the source link, if it appears (color)
source_link_color = 'darkred'

#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# END PER-CAM CONFIGURATION
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>






##########################################
### PROCESS URL OPTIONS FROM PATH_INFO ###
##########################################
## If the script is called from a URL with path info equal to 'view' or
## 'get' the contents of the script will be displayed. 'get' results
## in text/plain output while view - relying on rb2html - output color-
## coded html output with line numbers.
path_info = ENV['PATH_INFO']

if path_info == '/get'
## Print source
puts( "Content-type: text/plain\n\n" )
IO::foreach( ENV['SCRIPT_FILENAME'] ) { |l|
puts l
}
exit
elsif path_info == '/view'
## Print formatted source
puts( "Content-type: text/html\n\n" )
rb2html_executable = rb2html_directory + '/rb2html.rb'
if File::file?( rb2html_executable )
begin
htmlpipe = IO::popen( 'ruby ' + rb2html_executable + ' ' +
ENV['SCRIPT_FILENAME'] )
puts( htmlpipe.readlines() )
rescue SystemCallError
## Mail admin if any errors - if you don't want mail, change
## the admin address.
require 'net/smtp'
smtp = Net::SMTP::new( "localhost" )
smtp.start
body = "Error:\nruby " + rb2html_executable + ' ' +
ENV['SCRIPT_FILENAME']
smtp.sendmail( body, 'rubycam_user@localhost', admin_email_address )
smtp.finish
end
exit
else
puts( "Content-type: text/plain\n\n" )
puts( "Error: cannot execute " + rb2html_executable )
exit
end
elsif path_info != nil
if not File::file?( config_dir + path_info )
## Print error
puts( "Content-type: text/plain\n\n" )
puts( "Error: invalid config file: '" + config_dir + path_info + "'\n" +
"Set the PATH_INFO (in the url) to a valid config file name." )
exit
elsif path_info.index( '../' ) != nil
## Print error
puts( "Content-type: text/plain\n\n" )
puts( "Error: invalid config file: '" + config_dir + path_info + "'\n" +
"'../' not permitted in config file pathname." )
exit
elsif not File::readable?( config_dir + path_info )
## Print error
puts( "Content-type: text/plain\n\n" )
puts( "Error: unreadable config file: '" + config_dir + path_info + "'" )
exit
else
## Process config file
config_file_string = ''
File::eek:pen( config_dir + path_info ).readlines.each do |line|
config_file_string.concat( line )
end
eval config_file_string
end
end


###########################
### DETERMINE FILE INFO ###
###########################

## First, we determine the colors to be used for text (the image time)
## and for the background of the image (not the page bgcolor).
color_hash = {
0 => 'white',
1 => 'red',
2 => 'orange',
3 => 'yellow',
4 => 'green',
5 => 'blue',
6 => 'purple',
7 => 'lightgreen',
8 => 'pink',
9 => 'lightyellow',
10 => 'lightblue',
11 => 'lightgray',
12 => 'gray'
}

## If img_background_color is set to nil, then no image background
## color options will apply.
if img_background_color != nil and
use_randomize_img_background_color
img_background_color = color_hash[rand(13)]
end

## If randomization is used for text and image, then the image
## background color is used for both.
if use_randomize_text_color and
not text_color_matches_img_background_color
text_color = color_hash[rand(13)]
elsif ( img_background_color != nil ) and
text_color_matches_img_background_color
text_color = img_background_color
end

img_file_webpath = img_file_web_directory + '/' + img_filename
img_file_pathname = ENV['DOCUMENT_ROOT'] + img_file_webpath
img_file_tmp_pathname = img_file_pathname + '.tmp'

## Time
time_now = Time::now

## Mtime
if File::exist?( img_file_pathname )
img_file_mtime = File::mtime( img_file_pathname )
img_file_mtime_int = img_file_mtime.to_i
img_file_mtime_string = img_file_mtime.to_s
img_file_age = time_now.to_i - img_file_mtime_int
end

###########################
### LOCKFILE CODE ###
###########################

## Lock file name is global - there is only one camera and it can take
## only one picture at a time. The lockfile is set during this process.
lock_file_pathname = ENV['DOCUMENT_ROOT'] + img_file_web_directory + '/' +
lock_filename

## If the lockfile somehow gets stale, it will be removed.
locked = false
if File::exist?( lock_file_pathname )
if ( File::mtime( lock_file_pathname ) < ( time_now - ( max_lockfile_age ) ) )
File::unlink( lock_file_pathname )
else
locked = true
end
end

###########################
### EXECUTE ###
###########################

## If there's no image, or it's an old one, and the camera is free,
## then we take a new picture.
if ( ( not File::exist?( img_file_pathname ) ) or
( img_file_age >= refresh ) ) and
( not locked )

lockfile = File::new( lock_file_pathname, mode='w' )

begin
## Execute
img_file = File::eek:pen( img_file_tmp_pathname, mode='w').write( IO::popen( cmd_line ).read() )
require 'ftools'
File::mv( img_file_tmp_pathname, img_file_pathname )
File::unlink( lock_file_pathname )
img_file_mtime = Time::now
img_file_mtime_string = img_file_mtime.to_s
rescue SystemCallError
## Mail admin if any errors - if you don't want mail, change
## the admin address.
require 'net/smtp'
smtp = Net::SMTP::new( "localhost" )
smtp.start
body = "Subject: Error with rubycam\n" +
"Failed to execute:\n" + cmd_line + "\n\nSee logs for details."
smtp.sendmail( body, 'rubycam_user@localhost', admin_email_address )
smtp.finish
File::unlink( lock_file_pathname )
end

end

###########################
### HTML ###
###########################

puts( "Content-type: text/html\n" +
'Last-Modified: ' + img_file_mtime_string + "\n" +
'Expires: ' + ( img_file_mtime + refresh ).to_s +
"\n\n" )

puts( '<head><title>' + title + '</title>' +
'<META HTTP-EQUIV="Refresh" CONTENT="' + refresh.to_s + '"></head>' )

puts( '<body bgcolor="' + bgcolor + '" text="' + text_color + '">' )

puts( '<center><table><tr><td' )

if img_background_color != nil
puts( ' bgcolor="' + img_background_color + '"' )
end

puts( '><img src="' + img_file_webpath + '"></td></tr></table><p>' )

puts( '<p><b>' + img_file_mtime_string + '</b>' )

if source_link_target != nil
puts( ' <small><a href="' + ENV['SCRIPT_NAME'] + '/get" target="' + source_link_target + '"><font color="' + source_link_color + '">&reg;</font></a></small>' )
end

puts( '</center></body></html>' )



###########################
### CALLING FROM HTML ###
###########################
##
## Include the following in your page head:
##
## <script language=javascript>
## function openwin(url){
## var hWnd =
## window.open(url,"","width=350,height=300,resizable=yes,scrollbars=yes");
## if (!hWnd.opener) hWnd.opener = self;
## }
## function openminiwin(url){
## var hWnd =
## window.open(url,"","width=180,height=140,resizable=yes,scrollbars=yes");
## if (!hWnd.opener) hWnd.opener = self;
## }
## </script>
##
## Call within body of page as:
##
## <ul>
## <li><a href="Javascript:eek:penwin('/cgi-bin/webcam/rubycam.rb');">Webcam</a>
## <li><a href="Javascript:eek:penwin('/cgi-bin/webcam/rubycam.rb/transgif.conf');">Psychedelicam</a>
## <li><a href="Javascript:eek:penwin('/cgi-bin/webcam/rubycam.rb/greyjpeg.conf');">Greycam</a>
##
##
## <li><a href="/cgi-bin/webcam/rubycam.rb/view">Formatted Source</a>
## <li><a href="/cgi-bin/webcam/rubycam.rb/get">Source</a>
## </ul>
##

###########################
### CONFIG FILE # 1 ###
###########################
## greyjpeg.conf - produces a grey jpeg
# cmd_line = 'cqcam -s 1 | ppmtojpeg --progressive --greyscale --optimize --quality=33 --comment="Made with Rubycam"'
# img_filename = 'grey.jpg'
# title = 'Greycam'
# refresh = 60

###########################
### CONFIG FILE # 2 ###
###########################
## transgif.conf - produces a transparent gif with weird effects
# cmd_line = 'cqcam -s 1 | ppmquant 2 | ppmtogif -transparent grey -interlace -sort -comment="Made with Rubycam"'
# img_filename = 'transparent.gif'
# title = 'Psychedelicam'
# refresh = 60
# img_background_color = 'red'
# use_randomize_img_background_color = true
# use_randomize_text_color = true
# text_color_matches_img_background_color = true


## EOF
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top