The dhttp kit (http://udell.roninhouse.com/examples/dhttp-v2.tar.gz) installs by unzipping into any subdirectory on a Unix or NT box equipped with Perl 5. You’ll need CPAN’s DBI and a DBD datasource driver if you want to run the apps I’ve included with dhttp or try your own database-oriented apps. You’ll also need CPAN’s Net::NNTP for the HelpDesk (hd) app described in Chapter 9.
The dhttp distribution divides into the following three parts.
./dhttp
The main driver; starts the engine and load the apps
./code_synch
Demonstrates code replication
./data_synch
Demonstrates data replication
./lib/dhttp/Engine/Server.pm
The miniature HTTP server
./lib/dhttp/Engine/PubUtils.pm
Methods visible both to web clients and internal methods
./lib/dhttp/Engine/PrivUtils.pm
Methods visible only to internal methods
./lib/dhttp/Engine/edit_ file.htm
A system-level template for the Engine::PubUtils::do_edit_
file( )
method
./lib/dhttp/Apps/sfa.pm
The sfa module
./lib/dhttp/Apps/sfa/bios/.
Subdirectory for bios of contacts
./lib/dhttp/Apps/sfa/sfa_company.htm
Template for the company pane
./lib/dhttp/Apps/sfa/sfa_contacts.htm
Template for the contacts pane
./lib/dhttp/Apps/sfa/sfa_multi_history.htm
Template for the contact-history pane
./lib/dhttp/Apps/sfa/sfa_ave_company.htm
Template for forms to add, edit, or view a company record
./lib/dhttp/Apps/sfa/sfa_add_contact.htm
Template for add-contact form
./lib/dhttp/Apps/sfa/sfa_add_history.htm
Template for add-contact-history form
./lib/dhttp/Apps/hd.pm
The hd module
./lib/dhttp/Apps/hd/ticknums/.
Subdirectory for ticket numbers
./lib/dhttp/Apps/hd/home.htm
Template for home page
./lib/dhttp/Apps/hd/trouble.htm
Template for trouble-ticket form
./lib/dhttp/Apps/hd/trouble.msg
Template for trouble ticket as NNTP message
./lib/dhttp/Apps/hd/close.htm
Template for ticket-closing form
./lib/dhttp/Apps/jobs.pm
The jobs module
./lib/dhttp/Apps/jobs/jobs_ave_ job.htm
Template forms to add, view, or edit job records
The driver script includes commented-out sections for each of the three applications mentioned above: sfa, hd, and jobs:
#$main::sfa_dbh = DBI->connect('DBI:ODBC:SFA','','') # or die ("sfa_dbh: cannot connect"); #use Apps::sfa; #$main::jobs_dbh = DBI->connect('DBI:ODBC:JOBS','','') # or die ("jobs_dbh: cannot connect"); #use Apps::jobs; #$main::hd_dbh = DBI->connect('DBI:ODBC:HD','','') # or die ("hd_dbh: cannot connect"); #use Apps::hd;
You can enable any or all of these applications. In this example, to
enable sfa, you’d uncomment the first
three lines, assuming (on NT) that the ODBC system data-source name
(DSN) SFA corresponds to a working data source, which might simply be
a .MDB
file on the local machine, or else
an SQL server on the local or some other machine.
After unzipping dhttp into a home directory, you start it (on port 9191) like this:
perl -Ilib/dhttp dhttp 9191
To create the tables needed for the sfa plug-in, use a browser to request the URL http://host:port/sfa_makedb. To start the sfa plug-in, request the URL http://host:port/sfa_home. Follow a similar procedure for the jobs plugin: first http://host:port/jobs_makedb, then http://host:port/jobs_home.
The example in Chapter 15, showed how the code_synch
script, which is the root directory of the dhttp
distribution, uses the engine’s
do_update_sub
method to update a method in the
sfa module. To try this, make sure sfa is running,
then adjust the host and port variables in the script and run
code_synch.
If you’re running two or more instances of the
jobs plug-in, you can try the data replication
example shown in Chapter 15. If, for example,
dhttp is running on the hosts
jon_linux
and jon_nt
, each with
a live instance of jobs
, then the
$hosts
structure in data_synch might look like
this:
my $hosts = { jon_nt => { port => 9191, conn => 'DBI:ODBC:JOBS', dbuser => '', dbpw => '', datedelim => '#', }, jon_linux => { port => 9191, conn => $tc->escape('DBI:Solid:tcp 1313'), dbuser => 'dba', dbpw => 'dba', datedelim => ''', }, };
When you run data_synch, it visits each of the hosts mentioned in
$hosts
and synchronizes the tables used by the
jobs plug-in.
This mechanism depends on a special discipline observed by the
jobs
plug-in. Every URL generated by the module
includes three elements: host
,
port
, and user
. We’ll see
why host
and port
are needed in
the next section on proxying and encryption. Here, let’s focus
on why hd requires the user
element.
Suppose you’re running dhttp on the host
your_dhttp
, and I’m running it on
my_dhttp
. That means that to edit my local
database, I’ll do this:
http://my_dhttp:9191/jobs_home?host=my_dhttp&port=9191&user=jon
Likewise, to edit your local database, you’ll do this:
http://your_dhttp:9191/jobs_home?host=your_dhttp&port=9191&user=you
But suppose I need to work, remotely, in your database. In that case, I’ll do this:
http://your_dhttp:9191/jobs_home?host=your_dhttp&port=9191&user=jon
Because jobs
threads user=jon
through all subsequent interactions issuing from this URL, my edits
in your database are stamped with my name and are distinct from your
edits in your database, which are stamped with your name.
Here’s an alternate way for me to edit your jobs database:
http://my_dhttp:9191/jobs_home?host=your_dhttp&port=9191&user=jon
In this case, I point my browser at my instance
of dhttp, not yours. Noticing that the destination
host (your_dhttp
) differs from the source host
(my_dhttp
), the Engine::Server
module switches into proxying and encryption mode. That is,
my_dhttp
uses web-client calls to relay the
browser’s HTTP requests, in encrypted form, to
your_dhttp
, which decrypts the requests.
In this mode, the client instance of dhttp
(proxying for my browser) includes the HTTP header
Remote-Dhttp: my_dhttp:9191
with its requests.
When the server instance notices this header, it encrypts its
responses and sets the variable
$main::other_hostname
.
To support this mode, a dhttp plug-in application
has to observe two rules. First, it has to thread the CGI variables
host
and port
through all of
its methods and HTML/JavaScript templates. Second, it has to call
transmit( )
instead of print(
)
. Here is Engine::PrivUtils::transmit(
)
, which decides whether to send plain-text or encrypted
responses:
sub transmit { my ($output) = @_; if ($main::other_hostname ne '') { my $cipher = dhttp_encrypt($output,length($output)); print escape("DHTTPCIPHER$cipher"); } else { print "$output"; } }
The dhttp distribution includes only a basic, proof-of-concept form of encryption. It reverses strings, as in the following code.
sub dhttp_encrypt { my ($s) = @_; my $rev = reverse($s); return $rev; } sub dhttp_decrypt { my ($s) = @_; my $rev = reverse($s); return $rev; }
As mentioned in Chapter 15, you can instead use any
symmetrical technique; for example, I have tested this scheme using
Blowfish. Even so, the implementation was cryptographically
naive. Because dhttp encrypts requests and
responses a line at a time, it’s quite obvious which requests
contain known strings like HTTP/1.0
and
GET /sfa_home
. And there are no provisions for
secure key exchange.
The encrypting mode of dhttp is really intended only to suggest the possibilities inherent in a model of computing in which HTTP peers are pervasive and act simultaneously as servers and proxies.
18.224.246.203