I don’t want to mess with Sourceforge, so consider this my form of
dissemination in case the server disappears some time. Please forward
mods to the email address listed under AUTHOR below. PS: New to ruby
when I wrote it - now have RSI - probably not going to make it very
slick.
···
#!/usr/bin/env ruby
########################################################################
VERSION: $Id: rubycam.rb,v 1.7 2002/03/22 20:08:52 rubycam Exp $
AUTHOR: Phil Voris
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 ® 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’].untaint
if path_info == ‘/get’
Print source
puts( “Content-type: text/plain\n\n” )
IO::foreach( ENV[‘SCRIPT_FILENAME’].untaint ) { |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’].untaint )
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’].untaint
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::open( 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_pathname.untaint
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
lock_file_pathname.untaint
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::open( 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( ‘’ + title + ‘’ +
’’ )
puts( ‘’ )
puts( ‘
’ )
puts( ‘
’ + img_file_mtime_string + ‘’ )
if source_link_target != nil
puts( ’ ®’ )
end
puts( ‘’ )
###########################
CALLING FROM HTML
###########################
Include the following in your page head:
Call within body of page as:
href=“Javascript:openwin(’/cgi-bin/webcam/rubycam.rb’);”>Webcam
href=“Javascript:openwin(’/cgi-bin/webcam/rubycam.rb/transgif.conf’);”>Psychedelicam
href=“Javascript:openwin(’/cgi-bin/webcam/rubycam.rb/greyjpeg.conf’);”>Greycam
Source
###########################
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
#!/usr/bin/env ruby
########################################################################
VERSION: $Id: rubycam.rb,v 1.7 2002/03/22 20:08:52 pvoris Exp $
AUTHOR: Phil Voris rubycam@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 ® 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’].untaint
if path_info == ‘/get’
Print source
puts( “Content-type: text/plain\n\n” )
IO::foreach( ENV[‘SCRIPT_FILENAME’].untaint ) { |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’].untaint )
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’].untaint
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::open( 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_pathname.untaint
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
lock_file_pathname.untaint
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::open( 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( ‘’ + title + ‘’ +
’’ )
puts( ‘’ )
puts( ‘
’ )
puts( ‘
’ + img_file_mtime_string + ‘’ )
if source_link_target != nil
puts( ’ ®’ )
end
puts( ‘’ )
###########################
CALLING FROM HTML
###########################
Include the following in your page head:
Call within body of page as:
href=“Javascript:openwin(’/cgi-bin/webcam/rubycam.rb’);”>Webcam
href=“Javascript:openwin(’/cgi-bin/webcam/rubycam.rb/transgif.conf’);”>Psychedelicam
href=“Javascript:openwin(’/cgi-bin/webcam/rubycam.rb/greyjpeg.conf’);”>Greycam
Source
###########################
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
#!/usr/bin/env ruby
########################################################################
VERSION: $Id: rubycam.rb,v 1.7 2002/03/22 20:08:52 pvoris Exp $
AUTHOR: Phil Voris rubycam@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 ® 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’].untaint
if path_info == ‘/get’
Print source
puts( “Content-type: text/plain\n\n” )
IO::foreach( ENV[‘SCRIPT_FILENAME’].untaint ) { |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’].untaint )
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’].untaint
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::open( 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_pathname.untaint
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
lock_file_pathname.untaint
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::open( 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( ‘’ + title + ‘’ +
’’ )
puts( ‘’ )
puts( ‘
’ )
puts( ‘
’ + img_file_mtime_string + ‘’ )
if source_link_target != nil
puts( ’ ®’ )
end
puts( ‘’ )
###########################
CALLING FROM HTML
###########################
Include the following in your page head:
Call within body of page as:
href=“Javascript:openwin(’/cgi-bin/webcam/rubycam.rb’);”>Webcam
href=“Javascript:openwin(’/cgi-bin/webcam/rubycam.rb/transgif.conf’);”>Psychedelicam
href=“Javascript:openwin(’/cgi-bin/webcam/rubycam.rb/greyjpeg.conf’);”>Greycam
Source
###########################
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”’