Ben Morrow said:
I don't quite follow what you are talking about here, but if you mean
busy-waiting that's nearly always a bad idea.
Well, for instance, I send a command to a device which I have connected by
means of a USB port, which may be configured as a CDC Serial COM port or a
Custom device. In either case, there is an expected delay from the time of
sending the command to the time the device responds. And the response may be
a sequence of characters, or a continuous stream of characters which will
continue until a command to stop has been sent. And there may be times that
the command cannot be sent, or the response cannot be received, because the
USB connection is broken for various reasons.
So, I send the command, and then loop while waiting for a response. Other
processes may continue because in my delay loop I ProcessMessages(). I check
the status of the receive buffer and if nothing, or the wrong response, is
received at the end of the timeout I post an error message and break out of
that thread. This is in a single-user environment where the application
resides on a single computer connected to a single hardware device, although
other devices such as printers may be connected, and other applications may
be running. But the main communication is a separate thread which runs
continuously to process input and output.
What does *that* have to do with it? (Anyway, Perl isn't interpreted.
It's semi-compiled, in the same way Java (usually) is. Unlike Java
there's no (supported) way to save the bytecode out to a separate file,
and the language supports (and requires) eval, but the compilation step
is still important.) If you were to say 'Perl is an *imperative*
language' I might see your point.
I'm not sure what you mean. Many lines of the script might be precompiled
into machine language code to speed execution, but something like eval()
must either step through the code line by line or perform another
compilation every time it is encountered unless the code in the eval() has
not changed. I'm not planning to use eval(), and I don't intend to run any
data received from outside the script. Whether it runs as an interpreter on
the text of the script, or as snippets of machine code, it still processes
the script in a sequential manner (unless threads have been started, which
will not be the case unless they are generated by other instructions.)
Memory yes. Files no. We're talking about two consecutively-running
processes modifying the same file, so locking is an issue.
I'm not sure how two consecutively running processes can access the same
file unless they were started within whatever time is involved to create a
file. Otherwise, the existence of the file will notify the sender that the
script is busy.
No, you're not understanding how this works. Any decent web server is
handling many requests at the same time (whether it does so through
multi-processing, multi-threading or an event loop is up to the server
in question: Apache is usually multi-process on Unix systems). When a
request comes in that is handled by a CGI script, it fires off the CGI
but continues to process other requests while it waits for it to finish.
Thus you could well get two (or more) copies of the CGI running at the
same time.
Of course, that is true. And I have simulated that by having two instances
of the HTML form that issues the request in two browser windows, and I sent
them as close as possible to the same time. The first request was processed
normally, but the second request, (which of course used its own memory copy
of the script), encountered the existence of the lock file and sent back a
Busy" message. Using the said:
It does. One of the things it does *not* protect you against is checking
the size of the file (that is, going outside of the database interface)
and then assuming it won't change before you create the table. Read the
docs for the libraries you are using.
The existence of the file is checked first, and that should block an attempt
to read the file size.
Rare or no, you still need to handle it properly. If this is not
something you expect to happen often, it would be better done manually
without bothering the main script with it.
It's only a convenience for now. Doing it manually seems to be more trouble
than just deleting the file and running the script. I guess it depends on
how you define "better".
Err... *what*? What does DB_File have to do with *any* of this? You're
using DBD::SQLite (or, at least, you were in the last bit of code I
saw).
Yes, at one time I planned to use DB_File, but then I found that DBI was
better, and SQLite seemed easiest. I found the locking mechanism in a
document on Perl DBI and MySQL. But it seems to be in the context of
threads, although I think it could be used in the main code which may be
considered a thread.
The problems you are having with security have nothing to do with Perl.
They would be the same regardless of what language you were using. The
most important is that you are simply *not taking this seriously
enough*, and assuming you can learn enough to safely publish a program
on the Internet in a couple of evenings.
Are you still using full names as passwords?
Only temporarily. I plan to check the Email as well as a Password which will
be delivered by the HTML form using a Password type input control. But I
might call it something else so that anyone snooping the CGI vars won't see
"Password" as a variable name. I have even thought of other measures to
increase security, such as adding a generated string based on something like
the now() Date, which should match for the sender as well as the perl
script, as long as the user and server are in the same time zone and their
clocks are reasonably synched. I could also check other information passed
in the HTTP request.
This obsession with security is interesting and important, but I think it is
being overplayed in this case. I think I have mitigated the threat of email
flooding and server tie-up with a flood of requests. Only one in every ten
second time interval will actually be processed, and all others will result
in "busy" messages being returned to the offender (or to wherever s/he has
forged). There is no sensitive data, and in fact we'd be happy for a hacker
to get information about healthy activities with the Sierra Club as an
alternative to goofing off on a computer. If these requests continued for an
hour, there would just be 360 bogus events listed in an HTML file, or (when
I implement the Delete function), one or more events might be deleted. I can
just download copies every day or so as backup. And the delete request would
involve a dialog of some sort which may even request reentry of a password,
or a special password only for deleting.
Please tell me where I'm wrong. Your security concerns are valid in the
context of a truly public web page that may attract many users, and/or when
sensitive information, such as CC numbers, SSNs, and missile launch codes
are being accessed. This is a simple utility which is intended for easy and
well-organized entry of events, outings, and news items, to be displayed on
the website of a local group with several thousand members but only a dozen
or so who will be authorized to post new items. This should be pretty boring
to a hacker when there are so many other ripe opportunities for genuine
mayhem or useful information.
I have added more of an outline to my Perl script which defines what I
intend to do:
#!/usr/bin/perl -T
#
# EventProcessor.pl-- A program to:
# (1) Receive data from an HTML form EventSubmit.htm
# (2) Bounce multiple requests (10 second sleep)
# (3) Process the following data:
# (a) Full_Name
# (b) Email (sender's email address)
# (c) Password (6 or more characters)
# (d) Request_Code (Add or Replace or Delete)
# (e) Event_Title (text only)
# (f) Event_URL (optional web address to be displayed)
# (g) Event_DT (Date and Time in yyyy-mm-ddThh:mm:ss format)
# (h) Event_Description (Text with optional HTML tags)
# (4) Check for authorized user Email and Full_Name and Password
# (5) Check other data for reasonable content
# (6) Perform database request (SCGBG_Events.htm)
# (a) Add record to database, sorted by DateTime (non-primary key)
# (b) Replace record with matching DateTime and Title
# (c) Delete record with matching DateTime and Title
# (7) Send Event_ data back to sender (Failure or success)
# (8) Mail form data to my email address as notification (Failure or
success)
#
# From a script written in 1997 by James Marshall, (e-mail address removed)
# For the latest, see
http://www.jmarshall.com/easy/cgi/
#
# Modified in September 2010 by Paul E. Schoen
# This version for use on Dreamhost
use warnings;
use strict;
use CGI 'Vars';
use DBI;
use Fcntl;
use DateTime;
Thanks,
Paul