MiniVend 4.04 master github/master minivend-4.04
Mike Heins [Sun, 16 Apr 2000 05:00:00 +0000 (00:00 -0500)]
32 files changed:
MANIFEST
Makefile.PL
README
WHATSNEW
dist/simple/catalog.cfg
dist/simple/config/blue1/logobar
dist/simple/config/blue1/only_logo
dist/simple/config/brown1/logobar
dist/simple/config/brown1/only_logo
dist/simple/config/yellow1/logobar
dist/simple/config/yellow1/only_logo
dist/simple/html/index.html
dist/simple/pages/action/get_password.html
dist/simple/pages/login.html
dist/src/tlink.pl
dist/usertag/db_date
hints.pl [new file with mode: 0644]
lib/Vend/Config.pm
lib/Vend/Data.pm
lib/Vend/Error.pm
lib/Vend/Interpolate.pm
lib/Vend/Misc/Static.pm
lib/Vend/Order.pm
lib/Vend/Server.pm
lib/Vend/Session.pm
lib/Vend/SessionFile.pm
lib/Vend/UserDB.pm
lib/Vend/Util.pm
pod/mvdocs.pod
pod/mvfaq.pod
scripts/makecat.PL
scripts/minivend.PL

index a24492d..984b2bb 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -418,6 +418,7 @@ extra/File/Spec/Win32.pm
 extra/HTML/Entities.pm
 extra/IniConf.pm
 extra/URI/URL.pm
+hints.pl
 lib/Vend/Cart.pm
 lib/Vend/Config.pm
 lib/Vend/Control.pm
index a956f49..eb7b56c 100644 (file)
@@ -13,6 +13,7 @@ use Config;
 use File::Copy;
 use File::Path;
 use File::Basename;
+use File::Find;
 use Data::Dumper;
 use Cwd;
 require 5.005;
@@ -26,7 +27,7 @@ my $Prompt_sub;
 my @mods_to_get;
 my $Lock_troubles;
 
-$VERSION = '4.03';
+$VERSION = '4.04';
 
 # See if we have the CPAN module
 my $Cpan = 0;
@@ -45,8 +46,13 @@ unless($@) {
        $Cpan = 1;
 }
 
-my @extra_lib_dirs;
-my @extra_lib_files;
+my @os_hints;
+eval {
+       # gets package 'mvhints'
+       require 'hints.pl';
+       @os_hints = mvhints::get_hints();
+};
+
 my @chown_files = qw/
                                                error.log
                                                etc
@@ -84,9 +90,7 @@ if($TermRead) {
        };
 }
 
-if($^O =~ /win32/i) {
-       die "Windows is only supported for a binary distribution.\n";
-}
+my $Windows = $^O =~ /win32/i ? 1 : 0;
 
 sub compare_file {
        my($first,$second) = @_;
@@ -224,6 +228,117 @@ EOF
        return CPAN::install($module);
 }
 
+sub extra_libs {
+
+       my ($realdir) = @_;
+       # Do the extra library checks
+
+       my @extra_lib_dirs;
+       my @extra_lib_files;
+       # We will use our own version of File::CounterFile always
+       push @extra_lib_dirs, 'File';
+       push @extra_lib_files, 'File/CounterFile.pm';
+
+       eval {
+               require IniConf;
+       };
+       if ($@) {
+               push @extra_lib_files, 'IniConf.pm';
+       }
+
+
+       eval {
+               require HTML::Entities;
+       };
+       if ($@) {
+               push @extra_lib_dirs, 'HTML';
+               push @extra_lib_files, 'HTML/Entities.pm';
+       }
+
+       eval {
+               require Business::UPS;
+       };
+       if ($@) {
+               push @extra_lib_dirs, 'Business';
+               push @extra_lib_files, 'Business/UPS.pm';
+       }
+
+       eval {
+               require Storable;
+       };
+       unless ($@) {
+                               my $def = 'y';
+                       print <<EOF;
+
+You appear to have Raphael Manfredi's Storable module installed.
+
+This module will significantly improve your DBM storage and
+fetch times.
+
+You can reply one of:
+
+               n -- Don't use Storable
+               s -- Use for sessions only, won't break existing databases
+               y -- Use for both sessions and databases
+
+It is recommended that new installations reply YES, and that
+existing installations reply S unless there is a need for
+improved performance. Replying S will mean you have to delete all
+of your session files.
+
+If you reply YES and you use any GDBM or DB_File databases
+they will NEED TO BE REMADE for ALL CATALOGS using this
+MiniVend server instance.
+EOF
+
+               if($ENV{MINIVEND_STORABLE_DB} || -f "$realdir/_db_storable" || -f "_db_storable") {
+                       $def = 'y';
+               }
+               elsif($ENV{MINIVEND_STORABLE} || -f "$realdir/_session_storable" || -f "_session_storable") {
+                       $def = 's';
+               }
+               my $ask = my_prompt("Use Storable module? (y/n/s) ", $def);
+               if ($ask =~ /^\s*(y|d)/i) {
+                       open(TSTORABLE, ">_db_storable")
+                               or die "creat _db_storable: $!\n";
+                       print TSTORABLE "REMOVE THIS FILE TO STOP USING Storable\n";
+                       close TSTORABLE;
+               }
+               if ($ask =~ /^\s*(y|s)/i) {
+                       open(TSTORABLE, ">_session_storable")
+                               or die "creat _session_storable: $!\n";
+                       print TSTORABLE "REMOVE THIS FILE TO STOP USING Storable\n";
+                       close TSTORABLE;
+               }
+       }
+
+       COPYEXTRA: {
+               my $cpdir = '.';
+               mkdir $cpdir, 0777 unless -d $cpdir;
+               mkdir "$cpdir/lib", 0777 unless -d "$cpdir/lib";
+               for(@extra_lib_dirs) {
+                       next if -d "$cpdir/lib/$_";
+                       mkdir "$cpdir/lib/$_", 0777 or die "mkdir $cpdir/lib/$_: $!\n";
+               }
+               for(@extra_lib_files) {
+                       File::Copy::copy ("extra/$_", "lib/$_")
+                               or die "Couldn't copy $_: $!\n";
+               }
+       }
+}
+
+sub mk_initp {
+       my ($ref) = @_;
+       local($Data::Dumper::Terse);
+       $Data::Dumper::Terse = 1;
+       open (INITP, ">scripts/initp.pl")
+               or die "Can't write initp.pl: $!\n";
+       print INITP '$MV::Self = ';
+       print INITP Dumper($ref);
+       print INITP ";\n1;";
+       close INITP;
+}
+
 sub initialize {
     my %X;
     $X{INSTALLDIRS}     = "perl";
@@ -268,8 +383,11 @@ sub initialize {
                $X{RPMBUILDDIR} = $MV::Default{rpmbuilddir} || $MV::Default{RPMBUILDDIR};
                $MV::Default{RPMBUILDDIR} = $X{RPMBUILDDIR};
        }
+
+       return %X if $MV::Default{nocopy};
+
        my $uid;
-       if($> == 0 and ! $MV::Default{MINIVEND_USER}) {
+       if($> == 0 and ! $MV::Default{MINIVEND_USER} and ! $Windows) {
                $uid = my_prompt(
                        qq{MiniVend cannot be run as root. Which user should run MiniVend? },
                        'minivend',
@@ -279,12 +397,12 @@ sub initialize {
                print UID "$uid";
                close UID;
        }
-       else {
+       elsif (! $Windows) {
                eval {
                        $uid = scalar getpwuid($>);
                };
        }
-       return %X if $MV::Default{nocopy};
+
        if($uid) {
                open(UID, ">_uid")
                        or die "Can't write uid file: $!\n";
@@ -318,6 +436,7 @@ sub initialize {
                                                                );
                print "\n";
                $realdir =~ s:[\\/]\s*$::;
+               $MV::Default{final} = $realdir if $Windows;
        }
        else {
                $realdir = $MV::Default{final};
@@ -348,6 +467,43 @@ sub initialize {
                                                ../pod/mvfaq.pod simple/download/mvfaq.pod
                                                );
 
+       if($Windows) {
+               mk_initp(\%X);
+               my ($in, $out);
+               my $ref = delete $X{PL_FILES};
+               if(! -d 'bin') {
+                       File::Path::mkpath('bin');
+               }
+               my (@f);
+               while ( ($in, $out) = each %$ref) {
+                       system "$^X $in";
+                       if($?) {
+                               die "Error making $in into $out: $!\n";
+                       }
+                       my $targ = $out;
+                       $targ =~ s:.*/::;
+                       File::Copy::copy($out, 'bin');
+                       push @f, "bin/$targ";
+                       system "pl2bat.bat $out";
+                       if($?) {
+                               warn "PL2BAT did not succeed for $out.\n";
+                       }
+                       else {
+                               File::Copy::copy("$out.bat", 'bin');
+                               push @f, "bin/$targ.bat";
+                       }
+               }
+               # Check for extra needed libraries
+               extra_libs($realdir);
+               my $wanted = sub {
+                               return unless -f $_;
+                               push @f, $File::Find::name;
+               };
+               File::Find::find($wanted, 'lib');
+               for (@f) {
+                       install_file('.', $realdir, $_);
+               }
+       }
        if($MV::Default{final}) {
                $\17 = 0;
                for(glob "_*") {
@@ -375,6 +531,26 @@ sub initialize {
                for (@files) {
                        install_file('.', $realdir, $_);
                }
+               for(@os_hints) {
+                       my ($condition, $routine) = @$_;
+                       unless (ref($condition) =~ /CODE/ and ref($routine) =~ /CODE/) {
+                               warn <<EOF;
+OS hint condititon and routine must be code reference, is
+
+       condition: $condition
+       routine:   $routine
+
+Skipping.
+EOF
+                               next;
+                       }
+                       next unless $condition->();
+                       my $odir = cwd();
+                       chdir $realdir
+                               or die "Cannot chdir to $realdir: $!\n";
+                       $routine->();
+
+               }
                if(-f "$realdir/_uid" and $> == 0) {
                        open(UID, "$realdir/_uid")
                                or die "Can't open uid file: $!\n";
@@ -393,97 +569,21 @@ sub initialize {
        }
 
 
-       # Do the extra library checks
-
-       # We will use our own version of File::CounterFile always
-       push @extra_lib_dirs, 'File';
-       push @extra_lib_files, 'File/CounterFile.pm';
-
-       eval {
-               require IniConf;
-       };
-       if ($@) {
-               push @extra_lib_files, 'IniConf.pm';
-       }
-
-
-       eval {
-               require HTML::Entities;
-       };
-       if ($@) {
-               push @extra_lib_dirs, 'HTML';
-               push @extra_lib_files, 'HTML/Entities.pm';
-       }
-
-       eval {
-               require Business::UPS;
-       };
-       if ($@) {
-               push @extra_lib_dirs, 'Business';
-               push @extra_lib_files, 'Business/UPS.pm';
-       }
-
-       eval {
-               require Storable;
-       };
-       unless ($@) {
-                               my $def = 'y';
-                       print <<EOF;
-
-You appear to have Raphael Manfredi's Storable module installed.
-
-This module will significantly improve your DBM storage and
-fetch times.
-
-You can reply one of:
-
-               n -- Don't use Storable
-               s -- Use for sessions only, won't break existing databases
-               y -- Use for both sessions and databases
-
-It is recommended that new installations reply YES, and that
-existing installations reply S unless there is a need for
-improved performance. Replying S will mean you have to delete all
-of your session files.
-
-If you reply YES and you use any GDBM or DB_File databases
-they will NEED TO BE REMADE for ALL CATALOGS using this
-MiniVend server instance.
-EOF
-
-               if($ENV{MINIVEND_STORABLE_DB} || -f "$realdir/_db_storable" || -f "_db_storable") {
-                       $def = 'y';
-               }
-               elsif($ENV{MINIVEND_STORABLE} || -f "$realdir/_session_storable" || -f "_session_storable") {
-                       $def = 's';
-               }
-               my $ask = my_prompt("Use Storable module? (y/n/s) ", $def);
-               if ($ask =~ /^\s*(y|d)/i) {
-                       open(TSTORABLE, ">_db_storable")
-                               or die "creat _db_storable: $!\n";
-                       print TSTORABLE "REMOVE THIS FILE TO STOP USING Storable\n";
-                       close TSTORABLE;
-               }
-               if ($ask =~ /^\s*(y|s)/i) {
-                       open(TSTORABLE, ">_session_storable")
-                               or die "creat _session_storable: $!\n";
-                       print TSTORABLE "REMOVE THIS FILE TO STOP USING Storable\n";
-                       close TSTORABLE;
-               }
-       }
-
        MODCHECK: {
-
                last MODCHECK unless $Cpan;
                eval {
-                               require MD5;
+                               require Digest::MD5;
                        };
-               push(@mods_to_get, 'MD5') if $@ and $Cpan;
+               push(@mods_to_get, 'Digest::MD5') if $@ and $Cpan;
                eval {
                                require SQL::Statement;
                        };
                push(@mods_to_get, 'SQL::Statement') if $@ and $Cpan;
                eval {
+                               require Safe::Hole;
+                       };
+               push(@mods_to_get, 'Safe::Hole') if $@ and $Cpan;
+               eval {
                                require MIME::Base64;
                        };
                push(@mods_to_get, 'MIME::Base64') if $@ and $Cpan;
@@ -491,23 +591,9 @@ EOF
                                require URI::URL;
                        };
                push(@mods_to_get, 'URI::URL') if $@ and $Cpan;
-
-       }
-
-       COPYEXTRA: {
-               my $cpdir = '.';
-               mkdir $cpdir, 0777 unless -d $cpdir;
-               mkdir "$cpdir/lib", 0777 unless -d "$cpdir/lib";
-               for(@extra_lib_dirs) {
-                       next if -d "$cpdir/lib/$_";
-                       mkdir "$cpdir/lib/$_", 0777 or die "mkdir $cpdir/lib/$_: $!\n";
-               }
-               for(@extra_lib_files) {
-                       File::Copy::copy ("extra/$_", "lib/$_")
-                               or die "Couldn't copy $_: $!\n";
-               }
        }
 
+       local($\17);
        $\17 = 0;
 
        MODGET: {
@@ -534,13 +620,10 @@ EOF
                        or die "Couldn't return to original dir $odir: $!\n";
        }
 
-       $Data::Dumper::Terse = 1;
-       open (INITP, ">scripts/initp.pl")
-               or die "Can't write initp.pl: $!\n";
-       print INITP '$MV::Self = ';
-       print INITP Dumper(\%X);
-       print INITP ";\n1;";
-       close INITP;
+       # Check for extra needed libraries
+       extra_libs($realdir);
+
+       mk_initp(\%X);
        delete $X{RPMBUILDDIR};
     return \%X;
 }
@@ -624,26 +707,31 @@ EOF
 #      print "OPT: " . Dumper(\%MV::Default);
        @ARGV = grep ! $delete{$_}, @saveargs;
 
-WriteMakefile(
-       NAME       => "MiniVend",
-       MAN3PODS => {
-                                       'pod/mvdocs.pod' => 'blib/man3/mvdocs.8',
-                                       'pod/mvtags.pod' => 'blib/man3/mvtags.8',
-                                       'pod/mvfaq.pod' => 'blib/man3/mvfaq.8',
+if($Windows) {
+       &initialize;
+}
+else {
+       WriteMakefile(
+               NAME       => "MiniVend",
+               MAN3PODS => {
+                                               'pod/mvdocs.pod' => 'blib/man3/mvdocs.8',
+                                               'pod/mvtags.pod' => 'blib/man3/mvtags.8',
+                                               'pod/mvfaq.pod' => 'blib/man3/mvfaq.8',
+                                               },
+               DISTNAME => "minivend",
+               clean    => {
+                                       FILES=> "lib/IniConf.pm _uid _db_storable _session_storable lib/File/CounterFile.pm scripts/initp.pl scripts/compile_link scripts/config_prog scripts/configdump scripts/dump scripts/expire scripts/localize scripts/expireall scripts/makecat scripts/minivend scripts/offline scripts/restart scripts/update dist/simple/download/mvdocs.pod dist/simple/download/mvtags.pod dist/simple/download/mvfaq.pod pod/mvtags.pod",
+                                  },
+
+               dist     => {
+                                               CI => "ci -l -t-Initial",
+                                               SUFFIX   => ".gz",
+                                               DIST_DEFAULT => 'all tardist',
+                                               COMPRESS => "gzip -9f",
+                                               ZIP_FLAGS => '-pr9',
                                        },
-       DISTNAME => "minivend",
-       clean    => {
-                   FILES=> "lib/IniConf.pm _uid _db_storable _session_storable lib/File/CounterFile.pm scripts/initp.pl scripts/compile_link scripts/config_prog scripts/configdump scripts/dump scripts/expire scripts/localize scripts/expireall scripts/makecat scripts/minivend scripts/offline scripts/restart scripts/update dist/simple/download/mvdocs.pod dist/simple/download/mvtags.pod dist/simple/download/mvfaq.pod pod/mvtags.pod",
-                  },
-
-       dist     => {
-                                       CI => "ci -l -t-Initial",
-                                       SUFFIX   => ".gz",
-                                       DIST_DEFAULT => 'all tardist',
-                                       COMPRESS => "gzip -9f",
-                                       ZIP_FLAGS => '-pr9',
-                               },
-       VERSION_FROM => "scripts/minivend.PL",
-       EXE_FILES  => [],
-       CONFIGURE  => \&initialize,
-);
+               VERSION_FROM => "scripts/minivend.PL",
+               EXE_FILES  => [],
+               CONFIGURE  => \&initialize,
+       );
+}
diff --git a/README b/README
index 3d7b25c..5e29421 100644 (file)
--- a/README
+++ b/README
@@ -30,6 +30,18 @@ or comments, but does not have time to offer free individual support
 in most cases. See the Minivend website at http://www.minivend.com/
 for more information.
 
+--------------------------------------------------------------
+
+                        M I N I V E N D
+                                       
+   Minivend is a full-featured electronic catalog system (commonly known
+   as a shopping cart) with online ordering capability. It is a high-end
+   database access and retrieval system with SQL support via the Perl DBI.
+
+   A full list of its features is available at:
+
+        http://www.minivend.com/
 IMPORTANT NOTE:  Minivend 4.0 requires, repeat REQUIRES, Perl 5.005 or Perl 5.6.
 
 The information you need is in the following files:
@@ -70,111 +82,15 @@ Major files/directories in the distribution:
     test.pl     The installation test script.
 
     win/        Windows-specific files
-            
---------------------------------------------------------------
-
-                        M I N I V E N D
-                                       
-   Minivend is a full-featured electronic catalog system (commonly known
-   as a shopping cart) with online ordering capability. It is a high-end
-   database access and retrieval system with SQL support via the Perl DBI.
-   
-   Minivend is freely-redistributable under the GNU General Public
-   License -- you can download it via FTP.
-
-    Minivend 4.0 Features
-
-       * Users maintain a "shopping cart" for ordered items
-       * Multiple independent or shared catalogs allow one server
-         to run many storefronts or a "mall"
-       * SSL support means secure and practical credit card ordering
-       * PGP and GPG support for secure off-site mailing of orders
-       * Complete addressable database support with virtually
-         unlimited rows and columns
-       * Complete SQL support via DBI
-       * Catalogs can be of almost unlimited size with excellent
-         performance
-       * Multi-server mode for very high capacity on systems with
-         sufficient memory
-       * Cookie support allows browsers to leave catalog and come
-         back without losing session state
-       * Minimate web administration interface allows complete
-         database editing
-       * Complete user authentication and database with address
-         books and stored shopping carts
-       * Many, many, other features
-
-    Powerful search capability
-
-       * One-click scan and search -- build a whole search in a single HREF
-       * Pageable results, configurable in many ways
-       * Versatile built-in text search
-       * Complete Glimpse support
-       * Fast binary search
-       * Independent field search selection and return
-       * Range searching, numeric and alphanumeric
-       * Search sorting with reverse, numeric and case-insensitive options
-       * Search any file, build results from any database
-
-    Complete control of appearance
-
-       * Over 90 predefined tag functions
-       * Powerful user-definable tags
-       * Catalog pages automatically selected -- either built
-         "on the fly" from the database or pre-made for popular items
-       * Embedded Perl and conditional HTML allow complex and
-         flexible catalog pages to be completely built from the database
-       * ASP-like syntax available
-
-    Flexible Ordering Process
-
-        * Single- or multi-level order screens with configurable field
-          verification
-        * Multiple shopping carts per catalog, allows both buy
-          and sell operations
-        * Shipping calculation, mixed modes, with UPS table lookup
-        * Sales tax calculation, with fully independent non-taxable
-          item and taxed shipping
-        * Route orders to multiple fulfillment houses with
-          complete configurability
-        * PGP encryption of credit card information or
-          the entire emailed order
-        * Fully-configurable discounts with coupons or
-          across-the-board discounts
-        * Fully-configurable quantity pricing
-        * Fully-configurable item price adjustments
-        * Sophisticated back end order entry capability including CyberCash(R)
-        * Fully configurable order reports and receipts
-
-    Miscellaneous
-
-        * Automated installation and configuration
-        * Runs under Perl 5.005/5.6, Windows, and almost any UNIX
-        * Designed to be secure
-        * Static page build option for high performance
-        * Works well with all browsers
-
--------------------------------------------------------------------
-
-                      A V A I L A B I L I T Y
-                              A N D
-                     C O M P A T I B I L I T Y
-
-Minivend 4 has been tested on Solaris 2, Linux, FreeBSD, and Digital
-UNIX/Tru64. Its predecessor Minivend 3 also reportedly runs on SCO, AIX,
-and other Unix ports.  It should work on any UNIX or Win32 OS with Perl
-5.005 or higher.
-
-Windows does not support fork(), so the server runs in the foreground. There
-are other differences; the canonical installation is UNIX.
 
 UNIX INSTALLATION
 ------------------
 Here is the short version:
 
-    gzip -dc minivend-4.xxx.tar.gz | tar xvf -
+    gzip -dc minivend-4.xx.tar.gz | tar xvf -
     cd minivend-4*
     perl Makefile.PL
+    make
     make test && make install
 
 -- WHEN IN DOUBT, RE-START THE SERVER.  It won't take but a few
@@ -184,11 +100,39 @@ Here is the short version:
 
 WINDOWS INSTALLATION
 --------------------
+Not yet. When is not yet determined, but it will not be soon.
+If you are very experienced, you might try installing the ZIP
+file with "perl Makefile.PL". But *at least* the following problems will
+be present:
+
+    1. You need to put "SessionType  DB_File" in catalog.cfg.
+    2. Minimate will not work (unless you can build Safe::Hole).
+    3. You probably need to use Apache since we no longer support
+       cygwin.dll and tlink.exe. If you can get tlink.pl running
+       on other web servers, patches are welcome.
+
+Do not use it in a production system.
+
+-------------------------------------------------------------------
+
+                      A V A I L A B I L I T Y
+                              A N D
+                     C O M P A T I B I L I T Y
+
+Minivend 4 has been tested on Solaris 2, Linux, FreeBSD, and Digital
+UNIX/Tru64. Its predecessor Minivend 3 also reportedly runs on SCO, AIX,
+and other Unix ports.  It should work on any UNIX or Win32 OS with Perl
+5.005 or higher.
 
-    Not yet. You can manually create a software directory and
-    get things going if you know your way around Perl. But I 
-    don't recommend trying unless you are prepared for some
-    serious work.
+IMPORTANT NOTE FOR BSD USERS: Minivend has been known to segfault when
+reading sockets on Perl. This occurs more frequently on a busy system.
+The workaround is to set in minivend.cfg:
+
+    MaxServers   0
+    Housekeeping 1
+
+Windows does not support fork(), so the server runs in the foreground. There
+are other differences; the canonical installation is UNIX.
 
 -------------------------------------------------------------------
 
@@ -225,14 +169,23 @@ at www.minivend.com.
 
                     K N O W N   P R O B L E M S
 
-BSDI, FreeBSD:
-       If installing as root, you should use this procedure:
+BSDI, FreeBSD, Net BSD:
+    You will need to make sure the following are in effect
+    in minivend.cfg:
+
+        MaxServers 0
+        Housekeeping 1
+
+    Expect lots of crashes if you don't do this.
 
-           perl Makefile.PL PREFIX=/usr/local/minivend
+Apache with SUEXEC:
+    VLINK/UNIX socket mode will not work well unless you do the
+    install as a normal user. If you are going to support multiple
+    users, you must use TLINK/INET mode.
 
 Windows:
-       Just a few things don't work the same as UNIX. See the
-       README-win.txt file for more information.
+    Many things won't work the same as UNIX. See the
+    README-win.txt file for more information.
 
 ---------------------------------------------------------------------
 
index 5975c0e..a4b176f 100644 (file)
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -1,3 +1,27 @@
+Minivend-4.04 changes:
+* Demo: Fixed COLSPAN=0 in logo bars -- it was killing Gecko rendering.
+* Demo: fixed email password function
+* Makefile.PL adjusts for BSD MaxServers
+* Added README notes about BSD and MaxServers.
+* Config.pm: added AutoEnd to match Autoload
+* Interpolate.pm: fixed bug in shipping which prevented old-style
+  geographic qualification from working -- thanks to Bob Jordan.
+* Order.pm: fixed multi-item order / mv_order_group problem
+* Session.pm: changed session retries to internal code. Thanks to
+  Jim Balster.
+* UserDB.pm: added "load" function to complement "save". Thanks to
+  Christopher Thompson.
+* Util.pm: changed Data::Dumper::Indent setting to localize
+* makecat now handles symlinked minivend.cfg
+* minivend executable: 
+   -- AutoEnd added 
+   -- adjusted path settings so that FinalPath can be set in Autoload
+   -- Added ability to call GlobalSub as Autoload when matches /^\w+$/
+   -- cleaned up macro calls (remove redundant/unneeded defined checks)
+* doc updates -- thanks to Jeff Carnahan, Hans-Joachim Leidinger, and Bill Randle.
+* Fixed major problems in [sort ....], now works
+* Added vestigial Windows install
+
 Minivend-4.03 changes:
 * MiniMate now a part of Minivend
 * Fixed partial update problems with SQL databases
index 4a41745..5bf5d99 100644 (file)
@@ -339,6 +339,7 @@ SpecialPage          results        results
 SpecialPage          report         ../etc/report
 SpecialPage          receipt        ../etc/receipt
 
+NoCache  reconfig special config query ord multi
 Static        No
 StaticAll     Yes
 StaticDBM     static
index cc72509..db81495 100644 (file)
                <TD WIDTH=150 VALIGN=top  __HEADERBG__>
                        <TABLE WIDTH=150 VALIGN=TOP ALIGN=left CELLSPACING=0 BORDER=0 CELLPADDING=0>
                        <TR VALIGN=top ALIGN=left>
-                       <TD WIDTH=150 COLSPAN=0 BGCOLOR=__BARBG__ HEIGHT=13 VALIGN=top ROWSPAN=0 ALIGN=middle><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=__BARTEXT__><B>Search for product</B></FONT>
+                       <TD WIDTH=150 BGCOLOR=__BARBG__ HEIGHT=13 VALIGN=top ALIGN=middle><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=__BARTEXT__><B>Search for product</B></FONT>
                        </TD>
                        </TR>
                        <TR>
-                       <TD WIDTH=150 COLSPAN=0 __HEADERBG__ HEIGHT=82 VALIGN=top ROWSPAN=0 ALIGN=left><FORM ACTION="[area search]"><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=5 BORDER=0><BR>
+                       <TD WIDTH=150 __HEADERBG__ HEIGHT=82 VALIGN=top ALIGN=left><FORM ACTION="[area search]"><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=5 BORDER=0><BR>
                        <INPUT TYPE=hidden NAME=mv_coordinate VALUE=1>
                        <INPUT TYPE=hidden NAME=mv_search_field VALUE=category>
                        <INPUT TYPE=hidden NAME=mv_search_field VALUE=":artist,title,comment,display">
@@ -67,7 +67,7 @@
        <TD WIDTH=320 VALIGN=top __HEADERBG__>
                <TABLE WIDTH=320 VALIGN=TOP ALIGN=left CELLSPACING=0 BORDER=0 CELLPADDING=0>
                <TR VALIGN=top ALIGN=left>
-                       <TD WIDTH=320 COLSPAN=0 BGCOLOR=__LINECOLOR__ HEIGHT=65 VALIGN=top ROWSPAN=0 ALIGN=left><IMG SRC="__LOGO__" WIDTH=320 ALT="" HEIGHT=65 BORDER=0></TD>
+                       <TD WIDTH=320 BGCOLOR=__LINECOLOR__ HEIGHT=65 VALIGN=top ALIGN=left><IMG SRC="__LOGO__" WIDTH=320 ALT="" HEIGHT=65 BORDER=0></TD>
                </TR>
                <TR VALIGN=top ALIGN=left>
                <TD WIDTH=320 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ALIGN=left><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=1 BORDER=0></TD>
        </TR>
 
        <TR VALIGN=top ALIGN=left>
-     <TD WIDTH=620 COLSPAN=3 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ROWSPAN=0 ALIGN=left><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=1 BORDER=0></TD>
+     <TD WIDTH=620 COLSPAN=3 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ALIGN=left><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=1 BORDER=0></TD>
        </TR>
 </TABLE>
index c014250..5e98e0f 100644 (file)
@@ -33,7 +33,7 @@
        <TD VALIGN=top __HEADERBG__>
        <TABLE WIDTH=320 VALIGN=TOP ALIGN=left CELLSPACING=0 BORDER=0 CELLPADDING=0>
        <TR VALIGN=top ALIGN=left>
-               <TD WIDTH=320 COLSPAN=0 BGCOLOR=__LINECOLOR__ HEIGHT=65 VALIGN=top ROWSPAN=0 ALIGN=left>
+               <TD WIDTH=320 BGCOLOR=__LINECOLOR__ HEIGHT=65 VALIGN=top ALIGN=left>
                <IMG SRC="__LOGO__" WIDTH=320 HEIGHT=65 BORDER=0>
                </TD>
        </TR>
@@ -43,6 +43,6 @@
 </TR>
 
 <TR VALIGN=top ALIGN=left>
-     <TD WIDTH=620 COLSPAN=3 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ROWSPAN=0 ALIGN=left><IMG SRC="clear.gif" WIDTH=1 HEIGHT=1 BORDER=0></TD>
+     <TD WIDTH=620 COLSPAN=3 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ALIGN=left><IMG SRC="clear.gif" WIDTH=1 HEIGHT=1 BORDER=0></TD>
 </TR>
 </TABLE>
index cc72509..db81495 100644 (file)
                <TD WIDTH=150 VALIGN=top  __HEADERBG__>
                        <TABLE WIDTH=150 VALIGN=TOP ALIGN=left CELLSPACING=0 BORDER=0 CELLPADDING=0>
                        <TR VALIGN=top ALIGN=left>
-                       <TD WIDTH=150 COLSPAN=0 BGCOLOR=__BARBG__ HEIGHT=13 VALIGN=top ROWSPAN=0 ALIGN=middle><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=__BARTEXT__><B>Search for product</B></FONT>
+                       <TD WIDTH=150 BGCOLOR=__BARBG__ HEIGHT=13 VALIGN=top ALIGN=middle><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=__BARTEXT__><B>Search for product</B></FONT>
                        </TD>
                        </TR>
                        <TR>
-                       <TD WIDTH=150 COLSPAN=0 __HEADERBG__ HEIGHT=82 VALIGN=top ROWSPAN=0 ALIGN=left><FORM ACTION="[area search]"><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=5 BORDER=0><BR>
+                       <TD WIDTH=150 __HEADERBG__ HEIGHT=82 VALIGN=top ALIGN=left><FORM ACTION="[area search]"><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=5 BORDER=0><BR>
                        <INPUT TYPE=hidden NAME=mv_coordinate VALUE=1>
                        <INPUT TYPE=hidden NAME=mv_search_field VALUE=category>
                        <INPUT TYPE=hidden NAME=mv_search_field VALUE=":artist,title,comment,display">
@@ -67,7 +67,7 @@
        <TD WIDTH=320 VALIGN=top __HEADERBG__>
                <TABLE WIDTH=320 VALIGN=TOP ALIGN=left CELLSPACING=0 BORDER=0 CELLPADDING=0>
                <TR VALIGN=top ALIGN=left>
-                       <TD WIDTH=320 COLSPAN=0 BGCOLOR=__LINECOLOR__ HEIGHT=65 VALIGN=top ROWSPAN=0 ALIGN=left><IMG SRC="__LOGO__" WIDTH=320 ALT="" HEIGHT=65 BORDER=0></TD>
+                       <TD WIDTH=320 BGCOLOR=__LINECOLOR__ HEIGHT=65 VALIGN=top ALIGN=left><IMG SRC="__LOGO__" WIDTH=320 ALT="" HEIGHT=65 BORDER=0></TD>
                </TR>
                <TR VALIGN=top ALIGN=left>
                <TD WIDTH=320 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ALIGN=left><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=1 BORDER=0></TD>
        </TR>
 
        <TR VALIGN=top ALIGN=left>
-     <TD WIDTH=620 COLSPAN=3 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ROWSPAN=0 ALIGN=left><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=1 BORDER=0></TD>
+     <TD WIDTH=620 COLSPAN=3 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ALIGN=left><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=1 BORDER=0></TD>
        </TR>
 </TABLE>
index c014250..5e98e0f 100644 (file)
@@ -33,7 +33,7 @@
        <TD VALIGN=top __HEADERBG__>
        <TABLE WIDTH=320 VALIGN=TOP ALIGN=left CELLSPACING=0 BORDER=0 CELLPADDING=0>
        <TR VALIGN=top ALIGN=left>
-               <TD WIDTH=320 COLSPAN=0 BGCOLOR=__LINECOLOR__ HEIGHT=65 VALIGN=top ROWSPAN=0 ALIGN=left>
+               <TD WIDTH=320 BGCOLOR=__LINECOLOR__ HEIGHT=65 VALIGN=top ALIGN=left>
                <IMG SRC="__LOGO__" WIDTH=320 HEIGHT=65 BORDER=0>
                </TD>
        </TR>
@@ -43,6 +43,6 @@
 </TR>
 
 <TR VALIGN=top ALIGN=left>
-     <TD WIDTH=620 COLSPAN=3 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ROWSPAN=0 ALIGN=left><IMG SRC="clear.gif" WIDTH=1 HEIGHT=1 BORDER=0></TD>
+     <TD WIDTH=620 COLSPAN=3 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ALIGN=left><IMG SRC="clear.gif" WIDTH=1 HEIGHT=1 BORDER=0></TD>
 </TR>
 </TABLE>
index cc72509..db81495 100644 (file)
                <TD WIDTH=150 VALIGN=top  __HEADERBG__>
                        <TABLE WIDTH=150 VALIGN=TOP ALIGN=left CELLSPACING=0 BORDER=0 CELLPADDING=0>
                        <TR VALIGN=top ALIGN=left>
-                       <TD WIDTH=150 COLSPAN=0 BGCOLOR=__BARBG__ HEIGHT=13 VALIGN=top ROWSPAN=0 ALIGN=middle><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=__BARTEXT__><B>Search for product</B></FONT>
+                       <TD WIDTH=150 BGCOLOR=__BARBG__ HEIGHT=13 VALIGN=top ALIGN=middle><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=__BARTEXT__><B>Search for product</B></FONT>
                        </TD>
                        </TR>
                        <TR>
-                       <TD WIDTH=150 COLSPAN=0 __HEADERBG__ HEIGHT=82 VALIGN=top ROWSPAN=0 ALIGN=left><FORM ACTION="[area search]"><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=5 BORDER=0><BR>
+                       <TD WIDTH=150 __HEADERBG__ HEIGHT=82 VALIGN=top ALIGN=left><FORM ACTION="[area search]"><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=5 BORDER=0><BR>
                        <INPUT TYPE=hidden NAME=mv_coordinate VALUE=1>
                        <INPUT TYPE=hidden NAME=mv_search_field VALUE=category>
                        <INPUT TYPE=hidden NAME=mv_search_field VALUE=":artist,title,comment,display">
@@ -67,7 +67,7 @@
        <TD WIDTH=320 VALIGN=top __HEADERBG__>
                <TABLE WIDTH=320 VALIGN=TOP ALIGN=left CELLSPACING=0 BORDER=0 CELLPADDING=0>
                <TR VALIGN=top ALIGN=left>
-                       <TD WIDTH=320 COLSPAN=0 BGCOLOR=__LINECOLOR__ HEIGHT=65 VALIGN=top ROWSPAN=0 ALIGN=left><IMG SRC="__LOGO__" WIDTH=320 ALT="" HEIGHT=65 BORDER=0></TD>
+                       <TD WIDTH=320 BGCOLOR=__LINECOLOR__ HEIGHT=65 VALIGN=top ALIGN=left><IMG SRC="__LOGO__" WIDTH=320 ALT="" HEIGHT=65 BORDER=0></TD>
                </TR>
                <TR VALIGN=top ALIGN=left>
                <TD WIDTH=320 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ALIGN=left><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=1 BORDER=0></TD>
        </TR>
 
        <TR VALIGN=top ALIGN=left>
-     <TD WIDTH=620 COLSPAN=3 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ROWSPAN=0 ALIGN=left><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=1 BORDER=0></TD>
+     <TD WIDTH=620 COLSPAN=3 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ALIGN=left><IMG SRC="clear.gif" WIDTH=1 ALT="" HEIGHT=1 BORDER=0></TD>
        </TR>
 </TABLE>
index c014250..5e98e0f 100644 (file)
@@ -33,7 +33,7 @@
        <TD VALIGN=top __HEADERBG__>
        <TABLE WIDTH=320 VALIGN=TOP ALIGN=left CELLSPACING=0 BORDER=0 CELLPADDING=0>
        <TR VALIGN=top ALIGN=left>
-               <TD WIDTH=320 COLSPAN=0 BGCOLOR=__LINECOLOR__ HEIGHT=65 VALIGN=top ROWSPAN=0 ALIGN=left>
+               <TD WIDTH=320 BGCOLOR=__LINECOLOR__ HEIGHT=65 VALIGN=top ALIGN=left>
                <IMG SRC="__LOGO__" WIDTH=320 HEIGHT=65 BORDER=0>
                </TD>
        </TR>
@@ -43,6 +43,6 @@
 </TR>
 
 <TR VALIGN=top ALIGN=left>
-     <TD WIDTH=620 COLSPAN=3 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ROWSPAN=0 ALIGN=left><IMG SRC="clear.gif" WIDTH=1 HEIGHT=1 BORDER=0></TD>
+     <TD WIDTH=620 COLSPAN=3 BGCOLOR=__LINECOLOR__ HEIGHT=1 VALIGN=top ALIGN=left><IMG SRC="clear.gif" WIDTH=1 HEIGHT=1 BORDER=0></TD>
 </TR>
 </TABLE>
index 9b714db..911ca7f 100644 (file)
                <TD WIDTH=150 VALIGN=top  BGCOLOR=#4F87CB>
                        <TABLE WIDTH=150 VALIGN=TOP ALIGN=left CELLSPACING=0 BORDER=0 CELLPADDING=0>
                        <TR VALIGN=top ALIGN=left>
-                       <TD WIDTH=150 COLSPAN=0 BGCOLOR=#FF6701 HEIGHT=13 VALIGN=top ROWSPAN=0 ALIGN=middle><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF><B>Search for product</B></FONT>
+                       <TD WIDTH=150 BGCOLOR=#FF6701 HEIGHT=13 VALIGN=top ALIGN=middle><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF><B>Search for product</B></FONT>
                        </TD>
                        </TR>
                        <TR>
-                       <TD WIDTH=150 COLSPAN=0 BGCOLOR=#4F87CB HEIGHT=82 VALIGN=top ROWSPAN=0 ALIGN=left><FORM ACTION="http://__MVC_SERVERNAME____MVC_CGIURL__/search.html"><IMG SRC="__MVC_IMAGEURL__/clear.gif" WIDTH=1 ALT="" HEIGHT=5 BORDER=0><BR>
+                       <TD WIDTH=150 BGCOLOR=#4F87CB HEIGHT=82 VALIGN=top ALIGN=left><FORM ACTION="http://__MVC_SERVERNAME____MVC_CGIURL__/search.html"><IMG SRC="__MVC_IMAGEURL__/clear.gif" WIDTH=1 ALT="" HEIGHT=5 BORDER=0><BR>
                        <INPUT TYPE=hidden NAME=mv_coordinate VALUE=1>
                        <INPUT TYPE=hidden NAME=mv_search_field VALUE=category>
                        <INPUT TYPE=hidden NAME=mv_search_field VALUE=":artist,title,comment,display">
@@ -85,7 +85,7 @@
        <TD WIDTH=320 VALIGN=top BGCOLOR=#4F87CB>
                <TABLE WIDTH=320 VALIGN=TOP ALIGN=left CELLSPACING=0 BORDER=0 CELLPADDING=0>
                <TR VALIGN=top ALIGN=left>
-                       <TD WIDTH=320 COLSPAN=0 BGCOLOR=#000000 HEIGHT=65 VALIGN=top ROWSPAN=0 ALIGN=left><IMG SRC="__MVC_IMAGEURL__/blue1/logo.png" WIDTH=320 ALT="" HEIGHT=65 BORDER=0></TD>
+                       <TD WIDTH=320 BGCOLOR=#000000 HEIGHT=65 VALIGN=top ALIGN=left><IMG SRC="__MVC_IMAGEURL__/blue1/logo.png" WIDTH=320 ALT="" HEIGHT=65 BORDER=0></TD>
                </TR>
                <TR VALIGN=top ALIGN=left>
                <TD WIDTH=320 BGCOLOR=#000000 HEIGHT=1 VALIGN=top ALIGN=left><IMG SRC="__MVC_IMAGEURL__/clear.gif" WIDTH=1 ALT="" HEIGHT=1 BORDER=0></TD>
        </TR>
 
        <TR VALIGN=top ALIGN=left>
-     <TD WIDTH=620 COLSPAN=3 BGCOLOR=#000000 HEIGHT=1 VALIGN=top ROWSPAN=0 ALIGN=left><IMG SRC="__MVC_IMAGEURL__/clear.gif" WIDTH=1 ALT="" HEIGHT=1 BORDER=0></TD>
+     <TD WIDTH=620 COLSPAN=3 BGCOLOR=#000000 HEIGHT=1 VALIGN=top ALIGN=left><IMG SRC="__MVC_IMAGEURL__/clear.gif" WIDTH=1 ALT="" HEIGHT=1 BORDER=0></TD>
        </TR>
 </TABLE>
 
@@ -174,11 +174,11 @@ catalog system. Links that will help you to use this software:</I>
 </TR>
 <TR ALIGN=LEFT>
 <TD WIDTH=620 COLSPAN=2 BGCOLOR=MAROON HEIGHT=13 VALIGN=TOP ALIGN=CENTER>
-<FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF><A HREF="__MVC_SERVERNAME____MVC_CGIURL__/index.html"><B><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF>Home</FONT></B></A>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="__MVC_SERVERNAME____MVC_CGIURL__/account.html"><B><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF>Profile</FONT></B></A>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="__MVC_SERVERNAME____MVC_CGIURL__/browse1.html"><B><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF>Products</FONT></B></A>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="__MVC_SERVERNAME____MVC_CGIURL__/feedback.html"><B><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF>Contact</FONT></B></A>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="__MVC_SERVERNAME____MVC_CGIURL__/new_account.html"><B><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF>Registration</FONT></B></A>
+<FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF><A HREF="http://__MVC_SERVERNAME____MVC_CGIURL__/index.html"><B><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF>Home</FONT></B></A>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="http://__MVC_SERVERNAME____MVC_CGIURL__/account.html"><B><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF>Profile</FONT></B></A>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="http://__MVC_SERVERNAME____MVC_CGIURL__/browse1.html"><B><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF>Products</FONT></B></A>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="http://__MVC_SERVERNAME____MVC_CGIURL__/feedback.html"><B><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF>Contact</FONT></B></A>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="http://__MVC_SERVERNAME____MVC_CGIURL__/new_account.html"><B><FONT SIZE=1 FACE="Tahoma, Arial, Helvetica" COLOR=#FFFFFF>Registration</FONT></B></A>
 </FONT></TD>
 </TR>
 <TR ALIGN=LEFT>
index 9c1fa86..8c6b5f0 100644 (file)
@@ -3,6 +3,10 @@ __LOGOBAR__
 __MENUBAR__
 __LEFTSIDE__
 <H1>Trying to retrieve....</H1>
+[perl]
+    $CGI->{mv_todo} = 'search';
+       $Config->{NoSearch} = '';
+[/perl]
 [update process]
 [search-region]
 [set get_id_matches][search-list][if-item-data userdb email][item-code][/if-item-data][/search-list][/set]
@@ -12,6 +16,11 @@ __LEFTSIDE__
 [/no-match]
 [/search-region]
 
+[perl]
+    $Config->{NoSearch} = 'userdb';
+       return;
+[/perl]
+
 [if value mv_search_match_count > 1]
 <H2>That one generated more than one match. [page login]Try again[/page] with more info?</H2>
 [elsif scratch get_id_matches]
index 80f85a4..e624ff5 100644 (file)
@@ -39,7 +39,7 @@ If you have an account with us, please enter your user name and password. (test/
 
     </FORM>
 <P>
-<FORM METHOD="POST" ACTION="[area get_password]">
+<FORM METHOD="POST" ACTION="[area action/get_password]">
 <INPUT TYPE=hidden NAME=mv_coordinate VALUE=yes>
 <INPUT TYPE=hidden NAME=mv_searchtype VALUE=db>
 <INPUT TYPE=hidden NAME=mv_search_file VALUE=userdb>
index 539a84e..ff01063 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl -wT
 # tlink.pl: runs as a cgi program and passes request to Vend server
 #
-#   $Id: tlink.pl,v 1.1.1.1 2000/03/09 19:08:20 mike Exp $
+#   $Id: tlink.pl,v 1.2 2000/04/16 00:18:27 mike Exp $
 #
 # Copyright 1996-1998 by Michael J. Heins <mikeh@minivend.com>
 #
@@ -135,7 +135,7 @@ sub send_entity {
 $SIG{PIPE} = sub { die_page("signal"); };
 $SIG{ALRM} = sub { server_not_running(); exit 1; };
 
-alarm $LINK_TIMEOUT;
+eval { alarm $LINK_TIMEOUT; };
 
 my ($remote, $port, $iaddr, $paddr, $proto, $line);
 
index 5d7cd14..7fdb2fe 100644 (file)
@@ -8,14 +8,25 @@ UserTag  db-date  Order table format
 UserTag  db-date  PosNumber 2
 UserTag  db-date  Routine <<EOF
 sub {
-    my ($format, $db) = @_;
+    my ($db, $format) = @_;
+       my ($dbfile, $mtime);
 
-    $format = '%A %d %b %Y' unless $format;
+       # use defaults if necessary
        $db = 'products' unless $db;
+    $format = '%A %d %b %Y' unless $format;
+
+       # build database file name
+       $dbfile = $Vend::Cfg->{ProductDir} . '/' 
+               . $Vend::Cfg->{Database}{$db}{'file'};
 
-    my $mtime = (stat($Vend::Cfg->{Database}{'db_file'}))[9];
-    return POSIX::strftime($format, localtime($mtime));
+       # get last modified time
+       $mtime = (stat ($dbfile))[9];
 
+       if (defined ($mtime)) {
+               return POSIX::strftime($format, localtime($mtime));
+       } else {
+               logError ("Couldn't stat $dbfile: $!\n");
+       }
 }
 EOF
 
diff --git a/hints.pl b/hints.pl
new file mode 100644 (file)
index 0000000..66a1e92
--- /dev/null
+++ b/hints.pl
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+
+package mvhints;
+
+sub get_hints {
+       my @out;
+
+       my $condition;
+       my $routine;
+
+       $condition = sub { $^O =~ /bsd/i };
+       $routine = sub {
+               my $fn = 'minivend.cfg.dist';
+               rename $fn, "$fn.bak";
+               open HINTIN, "$fn.bak"
+                       or die "cannot open $fn.bak: $!\n";
+               open HINTOUT, ">$fn"
+                       or die "cannot write $fn: $!\n";
+               while(<HINTIN>) {
+                       s/
+                               ^\s*Housekeeping\s+\d+.*$
+                       /# Changed for $^O, no safe signals\nHousekeeping 1/xi;
+                       s/
+                               ^\s*MaxServers\s+\d+.*$
+                       /# Changed for $^O, no safe signals\nMaxServers 0/xi;
+                       print HINTOUT $_;
+               }
+               close HINTIN;
+               close HINTOUT;
+               unlink "$fn.bak";
+               return 1;
+       };
+       push @out, [ $condition, $routine ];
+
+       return @out;
+}
+
+1;
index 184147c..6113db5 100644 (file)
@@ -1,6 +1,6 @@
 # Config.pm - Configure Minivend
 #
-# $Id: Config.pm,v 1.2 2000/03/28 05:04:45 mike Exp $
+# $Id: Config.pm,v 1.4 2000/04/12 15:07:04 mike Exp $
 #
 # Copyright 1996-2000 by Michael J. Heins <mikeh@minivend.com>
 #
@@ -101,7 +101,7 @@ BEGIN {
        };
 }
 
-$VERSION = substr(q$Revision: 1.2 $, 10);
+$VERSION = substr(q$Revision: 1.4 $, 10);
 
 for( qw(search refresh cancel return secure unsecure submit control checkout) ) {
        $Global::LegalAction{$_} = 1;
@@ -113,6 +113,7 @@ qw/
                PriceCommas
                PriceDivide
                PriceField
+               PriceDefault
                SalesTax
                TaxShipping
 
@@ -139,6 +140,7 @@ qw/
 @Locale_directives_scalar = (
 qw/
                Autoload
+               AutoEnd
                CommonAdjust
                DescriptionField
                ImageDir
@@ -148,6 +150,7 @@ qw/
                PriceDivide
                PriceCommas
                PriceField
+               PriceDefault
                SalesTax
                StaticPath
                HTMLsuffix
@@ -236,7 +239,7 @@ sub global_directives {
     ['DumpStructure',   'yesno',            'No'],
     ['DisplayErrors',    'yesno',            'No'],
     ['TcpPort',          'warn',             ''],
-    ['TcpMap',           'hash',             '7786 mv_admin 7787 "" 7788 "" 7789 ""'],
+    ['TcpMap',           'hash',             ''],
        ['Environment',      'array',            ''],
     ['TcpHost',           undef,             'localhost 127.0.0.1'],
        ['SendMailProgram',  'executable',              $Global::SendMailLocation
@@ -324,6 +327,7 @@ sub catalog_directives {
        ['SessionLockFile',  undef,                      'etc/session.lock'],
        ['Database',             'database',             ''],
        ['Autoload',             undef,                  ''],
+       ['AutoEnd',                      undef,                  ''],
        ['Replace',                      'replace',              ''],
        ['Member',                       'variable',             ''],
        ['WritePermission',  'permission',       'user'],
@@ -414,6 +418,7 @@ sub catalog_directives {
     ['OnFly',                   undef,              ''],
     ['HTMLmirror',              'yesno',            'No'],
     ['DescriptionField', undef,              'description'],
+    ['PriceDefault',    undef,              'price'],
     ['PriceField',              undef,              'price'],
        ['Shipping',         'locale',           ''],
 
@@ -1492,6 +1497,8 @@ sub parse_special {
 sub parse_hash {
        my($item,$settings) = @_;
        return {} if ! $settings;
+       $settings =~ s/^\s+//;
+       $settings =~ s/\s+$//;
        my(@setting) = Text::ParseWords::shellwords($settings);
 
        my $c;
@@ -1507,6 +1514,7 @@ sub parse_hash {
        my $i;
        for ($i = 0; $i < @setting; $i += 2) {
                $c->{$setting[$i]} = $setting[$i + 1];
+#::logDebug("$item hash $setting[$i]=$setting[$i+1]");
        }
        $c;
 }
@@ -1532,7 +1540,17 @@ my %IllegalValue = (
 );
 
 
+my $Have_set_global_defaults;
 my %Default = (
+               TcpMap => sub {
+                                                       shift;
+                                                       return 1 if defined $Have_set_global_defaults;
+                                                       $Have_set_global_defaults = 1;
+                                                       my (@sets) = keys %{$Global::TcpMap};
+                                                       return 1 if @sets;
+                                                       $Global::TcpMap->{7786} = '-';
+                                                       return 1;
+                                               },
 
                ProductFiles => sub {
                                                        shift;
index 2a6be5a..35f325c 100644 (file)
@@ -1,6 +1,6 @@
 # Data.pm - Minivend databases
 #
-# $Id: Data.pm,v 1.1.1.1 2000/03/09 19:08:20 mike Exp $
+# $Id: Data.pm,v 1.2 2000/04/02 10:20:34 mike Exp $
 # 
 # Copyright 1996-2000 by Michael J. Heins <mikeh@minivend.com>
 #
@@ -1120,8 +1120,9 @@ CHAIN:
                                $price = $item->{mv_price} || $mod;
                                redo CHAIN;
                        }
-                       elsif($mod =~ /^(\w*):([^:]+)(:(\S*))?$/) {
+                       elsif($mod =~ /^(\w*):([^:]*)(:(\S*))?$/) {
                                my ($table,$field,$key) = ($1, $2, $4);
+                               $field = $Vend::Cfg->{PriceDefault} if ! $field;
                                if($passed_key) {
                                        (! $key   and $key   = $passed_key)
                                                or 
index beb6940..e04479c 100644 (file)
@@ -1,6 +1,6 @@
 # Error.pm - Handle MiniVend error pages and messages
 # 
-# $Id: Error.pm,v 1.1.1.1 2000/03/09 19:08:21 mike Exp $
+# $Id: Error.pm,v 1.2 2000/04/02 10:20:34 mike Exp $
 #
 # Copyright 1996-2000 by Michael J. Heins <mikeh@minivend.com>
 #
@@ -37,7 +37,7 @@ use strict;
 
 use vars qw/$VERSION/;
 
-$VERSION = sprintf("%d.%02d", q$Revision: 1.1.1.1 $ =~ /(\d+)\.(\d+)/);
+$VERSION = sprintf("%d.%02d", q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/);
 
 my $wantref = 1;
 
@@ -95,8 +95,9 @@ EOF
                $out .= "$_: $Vend::Session->{$_}\n";
        }
 
-       for(keys %$::Carts) {
-               $out .= scalar @{$::Carts->{$_}};
+       for(keys %{$Vend::Session->{carts}} ) {
+               next if ! $Vend::Session->{carts}->{$_};
+               $out .= scalar @{$Vend::Session->{carts}->{$_}};
                $out .= " items in $_ cart.\n";
        }
        return $out;
index 714ca28..37c3cd5 100644 (file)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl
 # Interpolate.pm - Interpret MiniVend tags
 # 
-# $Id: Interpolate.pm,v 1.5 2000/03/25 07:16:49 mike Exp $
+# $Id: Interpolate.pm,v 1.10 2000/04/16 00:18:43 mike Exp $
 #
 # Copyright 1996-2000 by Michael J. Heins <mikeh@minivend.com>
 #
@@ -32,7 +32,7 @@ package Vend::Interpolate;
 require Exporter;
 @ISA = qw(Exporter);
 
-$VERSION = substr(q$Revision: 1.5 $, 10);
+$VERSION = substr(q$Revision: 1.10 $, 10);
 
 @EXPORT = qw (
 
@@ -715,6 +715,8 @@ sub tag_data {
                                                }
                                                $out .= "$anchor</A>";
                                },
+       'tt' =>                 sub { return '<TT>' . shift(@_) . '</TT>'; },
+       'pre' =>                sub { return '<PRE>' . shift(@_) . '</PRE>'; },
        'bold' =>               sub { return '<B>' . shift(@_) . '</B>'; },
        'italics' =>    sub { return '<I>' . shift(@_) . '</I>'; },
        'strikeout' =>  sub { return '<strike>' . shift(@_) . '</strike>'; },
@@ -1290,7 +1292,13 @@ EOF
                $value =~ s/"/&quot;/g;
 
                $value eq '' and $default eq '' and $select = "CHECKED";
-               $default =~ /\b\Q$value\E\b/ and $select = "CHECKED" if length($value);
+
+               if(length $value) {
+                       my $regex       = $opt->{contains}
+                                               ? qr/\Q$value\E/ 
+                                               : qr/\b\Q$value\E\b/;
+                       $default =~ $regex and $select = "CHECKED";
+               }
 
                $label =~ s/ /&nbsp;/g if $xlt;
 
@@ -1359,10 +1367,13 @@ sub tag_accessories {
                if "\L$type" eq 'hidden';
        return qq|<INPUT TYPE="hidden" NAME="$name" VALUE="$attrib_value">$attrib_value|
                if $type =~ /hidden/;
-       return qq|<TEXTAREA NAME="$name" ROWS=$1 COLS=$2>$attrib_value</TEXTAREA>|
-               if "\L$type" =~ /^textarea_(\d+)_(\d+)$/;
-       return qq|<INPUT TYPE=text NAME="$name" SIZE=$1 VALUE="$attrib_value">|
-               if "\L$type" =~ /^text_(\d+)$/;
+       if($type =~ /^text/i) {
+               HTML::Entities::encode($attrib_value);
+               return qq|<TEXTAREA NAME="$name" ROWS=$1 COLS=$2>$attrib_value</TEXTAREA>|
+                       if "\L$type" =~ /^textarea_(\d+)_(\d+)$/;
+               return qq|<INPUT TYPE=text NAME="$name" SIZE=$1 VALUE="$attrib_value">|
+                       if "\L$type" =~ /^text_(\d+)$/;
+       }
 
        my ($default, $label, $select, $value, $run);
        my @opts = split /\s*,\s*/, $data;
@@ -1520,7 +1531,12 @@ sub tag_perl {
        $ready_safe->share(@share) if @share;
 
        $MVSAFE::Safe = 1;
-       if($opt->{global} and $Global::AllowGlobal->{$Vend::Cfg->{CatalogName}}) {
+       if (
+               $opt->{global}
+                       and
+               $Global::AllowGlobal->{$Vend::Cfg->{CatalogName}}
+               )
+       {
                $MVSAFE::Safe = 0 unless $MVSAFE::Unsafe;
        }
 
@@ -2412,23 +2428,23 @@ my (@Opts);
 my (@Flds);
 my %Sort = (
 
-       ''      => sub { $a cmp $b                              },
-       none    => sub { $a cmp $b                              },
-       f       => sub { (lc $a) cmp (lc $b)    },
-       fr      => sub { (lc $b) cmp (lc $a)    },
+       ''      => sub { $_[0] cmp $_[1]                                },
+       none    => sub { $_[0] cmp $_[1]                                },
+       f       => sub { (lc $_[0]) cmp (lc $_[1])      },
+       fr      => sub { (lc $_[1]) cmp (lc $_[0])      },
     l  => sub {
-            my ($a1,$a2) = split /[,.]/, $a, 2;
-            my ($b1,$b2) = split /[,.]/, $b, 2;
+            my ($a1,$a2) = split /[,.]/, $_[0], 2;
+            my ($b1,$b2) = split /[,.]/, $_[1], 2;
             return $a1 <=> $b1 || $a2 <=> $b2;
     },  
     lr  => sub {
-            my ($a1,$a2) = split /[,.]/, $a, 2;
-            my ($b1,$b2) = split /[,.]/, $b, 2;
+            my ($a1,$a2) = split /[,.]/, $_[0], 2;
+            my ($b1,$b2) = split /[,.]/, $_[1], 2;
             return $b1 <=> $a1 || $b2 <=> $a2;
     },      
-       n       => sub { $a <=> $b                              },
-       nr      => sub { $b <=> $a                              },
-       r       => sub { $b cmp $a                              },
+       n       => sub { $_[0] <=> $_[1]                                },
+       nr      => sub { $_[1] <=> $_[0]                                },
+       r       => sub { $_[1] cmp $_[0]                                },
 );
 
 @Sort{qw/rf rl rn/} = @Sort{qw/fr lr nr/};
@@ -2436,16 +2452,6 @@ my %Sort = (
 use vars qw/%Sort_field/;
 %Sort_field = %Sort;
 
-sub field_sort {
-       my(@a) = split /\t/, $a;
-       my(@b) = split /\t/, $b;
-       my ($r, $i);
-       for($i = 0; $i < @Flds; $i++) {
-               $r = &{$Vend::Interpolate::Sort_field{$Opts[$i]}}($a[$Flds[$i]], $b[$Flds[$i]]);
-               return $r if $r;
-       }
-}
-
 sub tag_sort_ary {
     my($opts, $list) = (@_); 
     $opts =~ s/^\s+//; 
@@ -2455,6 +2461,7 @@ sub tag_sort_ary {
        my $key = 0;
 
        my ($start, $end, $num);
+       my $glob_opt = 'none';
 
     my @opts =  split /\s+/, $opts;
     my @option; my @bases; my @fields;
@@ -2462,8 +2469,9 @@ sub tag_sort_ary {
     for(@opts) {
         my ($base, $fld, $opt) = split /:/, $_;
 
-               if($base =~ /^([-\d]\d*)$/) {
+               if($base =~ /^(\d+)$/) {
                        $key = $1;
+                       $glob_opt = $fld || $opt || 'none';
                        next;
                }
                if($base =~ /^([-=+])(\d+)-?(\d*)/) {
@@ -2493,18 +2501,18 @@ sub tag_sort_ary {
                        $routine .= '&{$Vend::Interpolate::Sort_field{"' .
                                                $option[$i] .
                                                '"}}(' . "\n";
-                       $routine .= "tag_data('$bases[$i]','$fields[$i]', \$a->[$key]),\n";
-                       $routine .= "tag_data('$bases[$i]','$fields[$i]', \$b->[$key]) ) or ";
+                       $routine .= "tag_data('$bases[$i]','$fields[$i]', \$_[0]->[$key]),\n";
+                       $routine .= "tag_data('$bases[$i]','$fields[$i]', \$_[1]->[$key]) ) or ";
        }
-       $routine .= '0 or &{$Vend::Interpolate::Sort_field{none}}';
-       $routine .= '($a->[$key],$b->[$key]); }';
+       $routine .= qq!0 or &{\$Vend::Interpolate::Sort_field{"$glob_opt"}}!;
+       $routine .= '($_[0]->[$key],$_[1]->[$key]); }';
 #::logDebug("tag_sort_ary routine: $routine\n");
 
     my $code = eval $routine;  
     die "Bad sort routine\n" if $@;
 
        #Prime the sort? Prevent variable suicide??
-       &{$Vend::Interpolate::Sort_field{'n'}}('31', '30');
+       #&{$Vend::Interpolate::Sort_field{'n'}}('31', '30');
 
        use locale;
        if($::Scratch->{mv_locale}) {
@@ -2512,7 +2520,7 @@ sub tag_sort_ary {
                        $::Scratch->{mv_locale});
        }
 
-       @codes = sort {&$code} @$list;
+       @codes = sort {&$code($a, $b)} @$list;
 
        if(defined $start and $start > 1) {
                splice(@codes, 0, $start - 1);
@@ -2534,14 +2542,16 @@ sub tag_sort_hash {
        my $key = 'code';
 
        my ($start, $end, $num);
+       my $glob_opt = 'none';
 
     my @opts =  split /\s+/, $opts;
     my @option; my @bases; my @fields;
 
     for(@opts) {
 
-               if(/^(\w+)$/) {
+               if(/^(\w+)(:([flnr]+))?$/) {
                        $key = $1;
+                       $glob_opt = $3 || 'none';
                        next;
                }
                if(/^([-=+])(\d+)-?(\d*)/) {
@@ -2577,18 +2587,18 @@ sub tag_sort_hash {
                        $routine .= '&{$Vend::Interpolate::Sort_field{"' .
                                                $option[$i] .
                                                '"}}(' . "\n";
-                       $routine .= "tag_data('$bases[$i]','$fields[$i]', \$a->{$key}),\n";
-                       $routine .= "tag_data('$bases[$i]','$fields[$i]', \$b->{$key}) ) or ";
+                       $routine .= "tag_data('$bases[$i]','$fields[$i]', \$_[0]->{$key}),\n";
+                       $routine .= "tag_data('$bases[$i]','$fields[$i]', \$_[1]->{$key}) ) or ";
        }
-       $routine .= '0 or &{$Vend::Interpolate::Sort_field{none}}';
-       $routine .= '($a->{$key},$b->{$key}); }';
+       $routine .= qq!0 or &{\$Vend::Interpolate::Sort_field{"$glob_opt"}}!;
+       $routine .= '($a->{$key},$_[1]->{$key}); }';
 
 #::logDebug("tag_sort_hash routine: $routine\n");
     my $code = eval $routine;  
     die "Bad sort routine\n" if $@;
 
        #Prime the sort? Prevent variable suicide??
-       &{$Vend::Interpolate::Sort_field{'n'}}('31', '30');
+       #&{$Vend::Interpolate::Sort_field{'n'}}('31', '30');
 
        use locale;
        if($::Scratch->{mv_locale}) {
@@ -2596,7 +2606,7 @@ sub tag_sort_hash {
                        $::Scratch->{mv_locale});
        }
 
-       @codes = sort {&$code} @$list;
+       @codes = sort {&$code($a,$b)} @$list;
 
        if(defined $start and $start > 1) {
                splice(@codes, 0, $start - 1);
@@ -2609,90 +2619,6 @@ sub tag_sort_hash {
        return \@codes;
 }
 
-sub tag_sort_text {
-    my($opts, $list, $joiner) = (@_); 
-       my $hash;
-       my $key;
-    $opts =~ s/^\s+//; 
-    $opts =~ s/\s+$//; 
-#::logDebug("tag_sort_text: opts=$opts list:\n$list");
-       my @codes;
-       $list =~ s/^\s+//;
-       $list =~ s/\s+$//;
-       if(defined $joiner) {
-               @codes = split $joiner, $list;
-       }
-       else {
-               @codes = split /\s+/, $list;
-       }
-       $joiner = " " unless defined $joiner;
-
-       my ($start, $end, $num);
-
-    my @opts =  split /\s+/, $opts;
-    my @option; my @bases; my @fields;
-    for(@opts) {
-        my ($base, $fld, $opt) = split /:/, $_;
-
-               if($base =~ /^(\w+)$/) {
-                       $key = $1;
-                       next;
-               }
-               if($base =~ /^([-=+])(\d+)-?(\d*)/) {
-                       my $op = $1;
-                       if    ($op eq '-') { $start = $2 }
-                       elsif ($op eq '+') { $num   = $2 }
-                       elsif ($op eq '=') {
-                               $start = $2;
-                               $end = ($3 || undef);
-                       }
-                       next;
-               }
-               
-        push @bases, $base;
-        push @fields, $fld;
-        push @option, (defined $Vend::Interpolate::Sort_field{$opt} ? $opt : 'none');
-    }
-
-       if(defined $end) {
-               $num = 1 + $end - $start;
-               $num = undef if $num < 1;
-       }
-
-    my $i;
-    my $routine = 'sub { ';
-       for( $i = 0; $i < @bases; $i++) {
-                       $routine .= '&{$Vend::Interpolate::Sort_field{"' . $option[$i] . '"}}(' . "\n";
-                       $routine .= "tag_data('$bases[$i]','$fields[$i]'," . '$a),' . "\n";
-                       $routine .= "tag_data('$bases[$i]','$fields[$i]'," . '$b) ) or ';
-       }
-       $routine .= '0 or &{$Vend::Interpolate::Sort_field{none}}($a,$b); }';
-    my $code = eval $routine;  
-    die "Bad sort routine\n" if $@;
-
-       #Prime the sort? Prevent variable suicide??
-       &{$Vend::Interpolate::Sort_field{'n'}}('31', '30');
-
-       use locale;
-       if($::Scratch->{mv_locale}) {
-               POSIX::setlocale(POSIX::LC_COLLATE(),
-                       $::Scratch->{mv_locale});
-       }
-
-       @codes = sort {&$code} @codes;
-
-       if(defined $start and $start > 1) {
-               splice(@codes, 0, $start - 1);
-       }
-
-       if(defined $num) {
-               splice(@codes, $num);
-       }
-#::logDebug("sort routine returns: " . ::uneval(\@codes));
-       return join $joiner, @codes;
-}
-
 my %Prev;
 
 sub check_change {
@@ -3004,7 +2930,7 @@ sub sort_cart {
                push @codes, $code;
        }
 
-       $sort_order = tag_sort($options, \@codes);
+       $sort_order = tag_sort_hash($options, \@codes);
 
        foreach $code (@$sort_order) {
                push @out, @{$order{$code}};
@@ -4649,7 +4575,7 @@ sub shipping {
                                        if $o->{qual};
        }
        elsif($lines[0][CRIT] =~ /[[\s]|__/) {
-               ($field, $qual) = split /\s+/, interpolate_html($field), 2;
+               ($field, $qual) = split /\s+/, interpolate_html($lines[0][CRIT]), 2;
                if($qual =~ /{}/) {
                        logError("Bad qualification code '%s', returning 0", $qual);
                        goto SHIPFORMAT;
index 9be1485..f8f3b33 100644 (file)
@@ -1,6 +1,6 @@
 # Static.pm - MiniVend static page routines
 # 
-# $Id: Static.pm,v 1.1.1.1 2000/03/09 19:08:21 mike Exp $
+# $Id: Static.pm,v 1.2 2000/04/02 10:20:56 mike Exp $
 #
 # Copyright 1996-2000 by Michael J. Heins <mikeh@minivend.com>
 #
@@ -52,7 +52,9 @@ sub fake_scan {
        my $c = { mv_search_immediate => 1 };
        find_search_params($c,$path);
        return undef if $c->{mv_more_matches};
-       return ::perform_search($c);
+       ::perform_search($c);
+       $page = readin($CGI::values{mv_nextpage} || ::find_special_page('results'));
+       return ::interpolate_html($page, 1);
 }
 
 # STATICPAGE
@@ -118,7 +120,7 @@ sub build_page {
                                        $Vend::Cfg->{StaticPage}{"scan/$search"}
                                                =~ s/$Vend::Cfg->{StaticSuffix}$//o;
                                        push @post, $Vend::Found_scan{$search};
-                                       Vend::Util::writefile(">$dir/$file", $newpage)
+                                       Vend::Util::writefile(">$dir/$file", $$newpage)
                                                or die "Couldn't write $dir/$file: $!\n";
                                        if($Vend::ScanName) {
                                                eval {
index bdd6d4c..e2ef795 100644 (file)
@@ -2,7 +2,7 @@
 #
 # MiniVend version 4.0
 #
-# $Id: Order.pm,v 1.3 2000/03/25 07:16:49 mike Exp $
+# $Id: Order.pm,v 1.4 2000/04/12 15:07:04 mike Exp $
 #
 # Copyright 1996-2000 by Michael J. Heins <mikeh@minivend.com>
 #
@@ -33,7 +33,7 @@
 package Vend::Order;
 require Exporter;
 
-$VERSION = substr(q$Revision: 1.3 $, 10);
+$VERSION = substr(q$Revision: 1.4 $, 10);
 
 @ISA = qw(Exporter);
 
@@ -1709,7 +1709,7 @@ sub add_items {
        $j = 0;
        my $set;
        foreach $code (@items) {
-         
+          undef $item;
        $quantity = defined $quantities[$j] ? $quantities[$j] : 1;
        ($j++,next) unless $quantity;
           $set = $quantity =~ s/^=//;
index 5bc6d43..151c0c8 100644 (file)
@@ -1,6 +1,6 @@
 # Server.pm:  listen for cgi requests as a background server
 #
-# $Id: Server.pm,v 1.2 2000/03/28 04:27:22 mike Exp $
+# $Id: Server.pm,v 1.3 2000/04/02 10:20:34 mike Exp $
 #
 # Copyright 1996-2000 by Michael J. Heins <mikeh@minivend.com>
 #
@@ -28,7 +28,7 @@
 package Vend::Server;
 
 use vars qw($VERSION);
-$VERSION = substr(q$Revision: 1.2 $, 10);
+$VERSION = substr(q$Revision: 1.3 $, 10);
 
 use POSIX qw(setsid strftime);
 use Vend::Util;
@@ -966,14 +966,33 @@ sub server_both {
 
          foreach $port (keys %{$Global::TcpMap}) {
                my $fh = gensym();
-#::logDebug("Trying to run server on $port, fh created: $fh");
-               
+               my $bind_addr;
+               my $bind_ip;
+#::logDebug("starting to parse port $port, fh created: $fh");
+               if ($port =~ s/^([-\w.]+):(\d+)$/$2/) {
+                       $bind_ip  = $1;
+                       $bind_addr = inet_aton($bind_ip);
+               }
+               else {
+                       $bind_ip  = '0.0.0.0';
+                       $bind_addr = INADDR_ANY;
+               }
+#::logDebug("Trying to run server on ip=$bind_ip port=$port");
+           if(! $bind_addr) {
+                       ::logGlobal({},
+                                       "Could not bind to IP address %s on port %s: %s",
+                                       $bind_ip,
+                                       $port,
+                                       $!,
+                                 );
+                       next;
+               }
                eval {
                        socket($fh, PF_INET, SOCK_STREAM, $proto)
                                        || die "socket: $!";
                        setsockopt($fh, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
                                        || die "setsockopt: $!";
-                       bind($fh, sockaddr_in($port, INADDR_ANY))
+                       bind($fh, sockaddr_in($port, $bind_addr))
                                        || die "bind: $!";
                        listen($fh,$so_max)
                                        || die "listen: $!";
@@ -985,8 +1004,8 @@ sub server_both {
                        $rin = '';
                        vec($rin, fileno($fh), 1) = 1;
                        $vector |= $rin;
-                       $vec_map{$port} = fileno($fh);
-                       $fh_map{$port} = $fh;
+                       $vec_map{"$bind_ip:$port"} = fileno($fh);
+                       $fh_map{"$bind_ip:$port"} = $fh;
                }
                else {
                  ::logGlobal({},
index 947be65..cb171c6 100644 (file)
@@ -1,6 +1,6 @@
 # Session.pm - Minivend Sessions
 #
-# $Id: Session.pm,v 1.1.1.1 2000/03/09 19:08:20 mike Exp $
+# $Id: Session.pm,v 1.3 2000/04/12 15:07:04 mike Exp $
 # 
 # Copyright 1996-2000 by Michael J. Heins <mikeh@minivend.com>
 #
@@ -30,7 +30,7 @@ package Vend::Session;
 require Exporter;
 
 use vars qw($VERSION);
-$VERSION = substr(q$Revision: 1.1.1.1 $, 10);
+$VERSION = substr(q$Revision: 1.3 $, 10);
 
 @ISA = qw(Exporter);
 
@@ -318,7 +318,20 @@ sub read_session {
     my($s);
 
 #::logDebug ("read session id=$Vend::SessionID  name=$Vend::SessionName\n");
-       $s = $Vend::SessionDBM{$Vend::SessionName};
+       $s = $Vend::SessionDBM{$Vend::SessionName}
+               or $Global::Variable->{MV_SESSION_READ_RETRY}
+               and do {
+                       my $i = 0;
+                       my $tries = $Global::Variable->{MV_SESSION_READ_RETRY} + 0 || 5;
+                       while($i++ < $tries) {
+                               ::logDebug("retrying session read on undef, try $i");
+                               $s = $Vend::SessionDBM{$Vend::SessionName};
+                               next unless $s;
+                               ::logDebug("Session re-read successfully on try $i");
+                               last;
+                       }
+               };
+               
 #::logDebug ("Session:\n$s\n");
        return new_session() unless $s;
     $Vend::Session = ref $s ? $s : evalr($s);
index 42bcba9..b31cc8b 100644 (file)
@@ -1,6 +1,6 @@
 # SessionFile.pm:  stores session information in files
 #
-# $Id: SessionFile.pm,v 1.2 2000/03/28 04:27:22 mike Exp $
+# $Id: SessionFile.pm,v 1.3 2000/04/02 10:20:34 mike Exp $
 #
 # Copyright 1996-2000 by Michael J. Heins <mikeh@minivend.com>
 #
 # MA  02111-1307  USA.
 
 
-# $Id: SessionFile.pm,v 1.2 2000/03/28 04:27:22 mike Exp $
+# $Id: SessionFile.pm,v 1.3 2000/04/02 10:20:34 mike Exp $
 
 package Vend::SessionFile;
 require Tie::Hash;
 @ISA = qw(Tie::Hash);
 
+use Symbol;
 use strict;
 use Vend::Util;
 
 use vars qw($VERSION);
-$VERSION = substr(q$Revision: 1.2 $, 10);
+$VERSION = substr(q$Revision: 1.3 $, 10);
 
 my $SessionDir;
 my $SessionFile;
 my $SessionLock;
 my %HaveLock;
+my $Lh;
+my $Fh;
 my $Last;
 my @Each;
 
@@ -58,9 +61,10 @@ sub FETCH {
        return undef unless -f $SessionFile;
        my $str;
        unless ($HaveLock{$SessionFile} || $Global::Windows) {
-               open(SESSIONLOCK, "+>>$SessionLock")
+               $Lh = gensym();
+               open($Lh, "+>>$SessionLock")
                        or die "Can't open '$SessionLock': $!\n";
-               lockfile(\*SESSIONLOCK, 1, 1)
+               lockfile($Lh, 1, 1)
                        and $HaveLock{$SessionFile} = 1;
        }
        my $ref = Vend::Util::eval_file($SessionFile);
@@ -109,9 +113,10 @@ sub STORE {
     $SessionLock = $SessionFile . ".lock";
     unlink $SessionFile;
        unless ($HaveLock{$SessionFile} || $Global::Windows) {
-               open(SESSIONLOCK, "+>>$SessionLock")
+               $Lh = gensym();
+               open($Lh, "+>>$SessionLock")
                        or die "Can't open '$SessionLock': $!\n";
-               lockfile(\*SESSIONLOCK, 1, 1)
+               lockfile($Lh, 1, 1)
                        and $HaveLock{$SessionFile} = 1;
        }
 #::logDebug("storing in $SessionFile: " . ::uneval($ref));
@@ -120,9 +125,9 @@ sub STORE {
        
 sub DESTROY {
        my($self) = @_;
-       close(SESSION);
-       unlockfile(\*SESSIONLOCK);
-       close(SESSIONLOCK);
+       unlockfile($Lh)
+               and delete $HaveLock{$SessionFile};
+       close($Lh);
        undef $self;
 }
 
index 96f453e..1989542 100644 (file)
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 #
-# $Id: UserDB.pm,v 1.2 2000/03/18 16:04:49 mike Exp $
+# $Id: UserDB.pm,v 1.3 2000/04/12 15:07:04 mike Exp $
 #
 # Copyright 1996-2000 by Michael J. Heins <mikeh@minivend.com>
 #
@@ -8,7 +8,7 @@
 
 package Vend::UserDB;
 
-$VERSION = substr(q$Revision: 1.2 $, 10);
+$VERSION = substr(q$Revision: 1.3 $, 10);
 
 use vars qw! $VERSION @S_FIELDS @B_FIELDS @P_FIELDS %S_to_B %B_to_S!;
 
@@ -1276,6 +1276,14 @@ sub userdb {
                }
                $status = $user->set_values();
        }
+       elsif($function eq 'load') {
+               $user = new Vend::UserDB %options;
+               unless (defined $user) {
+                       $Vend::Session->{failure} = "Unable to access user database.";
+                       return undef;
+               }
+               $status = $user->get_values();
+       }
        else {
                $user = new Vend::UserDB %options;
                unless (defined $user) {
index 281b6f7..c603fb9 100644 (file)
@@ -1,6 +1,6 @@
 # Util.pm - Minivend utility functions
 #
-# $Id: Util.pm,v 1.2 2000/03/18 16:04:49 mike Exp $
+# $Id: Util.pm,v 1.4 2000/04/12 15:07:04 mike Exp $
 # 
 # Copyright 1996-2000 by Michael J. Heins <mikeh@minivend.com>
 #
@@ -74,7 +74,7 @@ use Config;
 use Fcntl;
 use subs qw(logError logGlobal);
 use vars qw($VERSION @EXPORT @EXPORT_OK);
-$VERSION = substr(q$Revision: 1.2 $, 10);
+$VERSION = substr(q$Revision: 1.4 $, 10);
 
 BEGIN {
        eval {
@@ -854,7 +854,7 @@ sub vendUrl {
                unless $::Scratch->{mv_no_count};
 
     $r .= '/' . $path;
-       $r .= '.html' if $::Scratch->{mv_add_dot_html};
+       $r .= '.html' if $::Scratch->{mv_add_dot_html} and $r !~ /\.html?/;
        push @parms, "$::VN->{mv_session_id}=$id"                               if defined $id;
        push @parms, "$::VN->{mv_arg}=" . hexify($arguments)    if defined $arguments;
        push @parms, "$::VN->{mv_pc}=$ct"                       if defined $ct;
@@ -983,13 +983,10 @@ sub dump_structure {
        $name =~ s/\.cfg$//;
        $name .= '.structure';
        open(UNEV, ">$name") or die "Couldn't write structure $name: $!\n";
-       if(defined $Data::Dumper::Indent) {
-               $save = $Data::Dumper::Indent;
-               $Data::Dumper::Indent = 2;
-       }
+       local($Data::Dumper::Indent);
+       $Data::Dumper::Indent = 2;
        print UNEV uneval($ref);
        close UNEV;
-       $Data::Dumper::Indent = $save if defined $save;
 }
 
 # Do an internal HTTP authorization check
index 8c4ba27..e8012d6 100644 (file)
@@ -3310,6 +3310,17 @@ returns true or false based on the value.
     [/else]
     [/if]
 
+If you want to use another tag to select the key, and it is not
+a looping tag construct, you must use named parameters:
+
+       [set code]99-102[/set]
+    [if type=data term="products::size::[scratch code]"]
+    There is size information.
+    [else]
+    No size information.
+    [/else]
+    [/if]
+
 =item discount
 
 Checks to see if a discount is present for an item.
@@ -7445,6 +7456,23 @@ the product code, but could be a key to any of the arbitrary
 databases. The value placed by the C<[item-code]> tag is set to
 the first field returned from the search.
 
+The basic structure looks like this:
+
+[search-region]
+[search-list]
+       your iterating code, once for each match
+[/search-list]
+[no-match] 
+       Text / tags to be output if no matches found (optional but recommended)
+[/no-match]
+[more-list]
+       More / paging area (optional)
+[/more-list]
+[/search-region]
+
+TIP FOR MV3 PORTS: A C<[search-list][/search-list]> must always be surrounded by a
+C<[search-region][/search-region]> pair. This is a change from Minivend 3.
+
 =over 4
 
 =item [search-list]
@@ -7454,23 +7482,45 @@ embedded in the search list, yielding a table or formatted
 list of items with part number, description, price, and  hyperlinks to
 order or go to its catalog page. 
 
-The set of tags for C<[item-list]> are available, with the exception
-of tags like C<[item-modifier]>, C<[modifier-name]>, C<[item-accessories]>,
-and others that access shopping-cart specific elements. Thse include:
-
-    [if-item-data table column] [/if-item-data]
-    [if-item-field column] [/if-item-field]
-    [item-code]
-    [item-data table column]
-    [item-discount]
-    [item-field column]
-    [item-price quantity* noformat*]
-
-In fact, any of the MiniVend database access tags can be used,
-allowing you to pull data from any of the fields in any of
-your predefined databases. Along with the MiniVend conditional
-tags, very complex pages can be built for each individual item
-returned in the search.
+The example tags shown have an C<item-> prefix, which is the
+default. You can set any prefix you want with the C<prefix> parameter
+to C<[search-region]>:
+
+       [search-region prefix=my]
+       [search-list]
+               SKU:   [my-code]
+               Title: [my-data products title]
+       [/search-list]
+       [/search-region]
+               
+The standard set of Minivend iterative MML tags are available. They are
+interpolated in this order:
+
+               [item-alternate N] true [else] false [/else] [/item-alternate]
+               [if-item-param named_field] true [else] false [/else] [/if-item-param]
+               [item-param named_field]
+               [if-item-pos N] true [else] false [/else] [/if-item-pos]
+               [item-pos N]
+               [if-item-field products_field] true [else] false [/else] [/if-item-field]
+               [item-field products_column]
+               [item-increment]
+               [item-accessories]
+               [item-code]
+               [item-description]
+               [if-item-data table column] true [else] false [/else] [/if-item-data]
+               [item-data table column]
+               [item-price N* noformat=1*]
+               [item-calc] [/item-calc]
+               [item-change marker]
+                       [condition]variable text[/condition]
+                       true
+                       [else] false [/else]
+               [/item-change marker]
+               [item-last] condition [/item-last]
+               [item-next] condition [/item-next]
+
+NOTE: those that reference the shopping cart do not apply, i.e. [item-quantity],
+[item-modifier ...] and friends.
 
 =item [/search-list]
 
@@ -7492,58 +7542,8 @@ Sorts the search list return based on database fields. If no
 options are supplied, sorts according to the return code. See
 I<SORTING>.
 
-=item [sort]<options>[/sort]
-
-(This form of sort is deprecated, as it is difficult to use.
-Use the above method.)
-
-Placed inside the search list. Causes sorting of the search return
-based on the passed options. The fields that are there
-to sort are set by C<mv_return_fields>.
-
-The field options passed in either numeric or field name form. If
-they are field numbers, they are numbered as sent to the search list
-in the order specified by F<mv_return_fields>,
-starting from 0 and proceeding upwards. If column names, they are
-as found in the first record of the searched file (by default the
-ASCII source for the product database), F<except for the key or first field>.
-followed by a F<required> colon (:) and the options, if any.
-
-Accepts none, any, or combinations of the flags:
-
-  f   case-insensitive sort (folded) (mutually exclusive of n)
-  n   numeric order (mutually exclusive of f)
-  r   reverse sort
-
-The <options> are a field number and an optional flag or flags, in a
-similar fashion to the Unix sort command, and are interpolated for form
-values before being used. As an example, if you set up the following
-fields on your search form:
-
-  <INPUT TYPE="hidden" NAME="mv_return_fields" VALUE="0,title,artist,price">
-  <INPUT TYPE="radio" NAME="the_sort_field" VALUE="title"> Sort by Title
-  <INPUT TYPE="radio" NAME="the_sort_field" VALUE="artist"> Sort by Artist
-  <INPUT TYPE="radio" NAME="the_sort_option" VALUE=""> Forward sort
-  <INPUT TYPE="radio" NAME="the_sort_option" VALUE="r"> Reverse sort
-  
-  NOTE: The 0 refers to the database code/key used for [item-code]
-
-This would combine with the following search result page fragment
-to sort by either title or artist.
-
-    [search-list]
-      [sort]
-        [value the_sort_field]:[value the_sort_option]
-      [/sort]
-    <B>[item-field title]</B>, by [item-field artist]<BR>
-    [/search-list]
-
-The [value...] lines will end up looking like C<artist:r> or C<title:>. This
-could also be specified with C<2r> or C<1>.
-
-PERFORMANCE TIP: on heavily trafficked systems, it will pay to use only
-column numbers rather than named fields, as it reduces processing and may
-obviate an access to the searched file to find the field names.
+This is slow, and it is far better to pre-sort your return in the 
+search specification.
 
 =item [item-change marker]
 
@@ -7639,13 +7639,29 @@ and C<border_selected> values are integers indicating the border that
 should be put around images in the C<page_img> selection. The <border_selected>
 is used for the current page if set.
 
-As an example, if you use C<[more-list next.gif prev.gif page_num.cgi]>, the
-following will be the anchors:
+Examples:
+
+C<[more-list next.gif prev.gif page_num.cgi 3]> causes anchors of:
+
+     Previous   <IMG SRC="prev.gif" Border=3>
+     Page 1     <IMG SRC="/cgi-bin/page_num.cgi?1">
+     Page 2     <IMG SRC="/cgi-bin/page_num.cgi?2">
+     Next       <IMG SRC="next.gif" Border=3>
+
+C<[more-list next.gif prev.gif page_num.cgi]> causes anchors of:
+
+     Previous   <IMG SRC="prev.gif">
+     Page 1     <IMG SRC="/cgi-bin/page_num.cgi?1">
+     Page 2     <IMG SRC="/cgi-bin/page_num.cgi?2">
+     Next       <IMG SRC="next.gif">
 
-  Previous   <IMG SRC="prev.gif">
-  Page 1     <IMG SRC="/cgi-bin/page_num.cgi?1">
-  Page 2     <IMG SRC="/cgi-bin/page_num.cgi?2">
-  Next       <IMG SRC="next.gif">
+C<[more-list next.gif prev.gif 0 0]> causes anchors of:
+
+
+     Previous   <IMG SRC="prev.gif" Border=0>
+     Page 1     <IMG SRC="/cgi-bin/page_num.cgi?1">
+     Page 2     <IMG SRC="/cgi-bin/page_num.cgi?2">
+     Next       <IMG SRC="next.gif" Border=0>
 
 If you wish to set custom text for the "Previous" and "Next" usually
 used, then you can define the next_img, prev_img, and page_img with
@@ -7717,65 +7733,6 @@ targeted to a different window than the one set by SearchFrame (which is
 
 =back
 
-=head2 Updating session variables after a search
-
-You may notice that if you set a scratch variable or reference a
-variable set in a search routine on the results page, the change does
-not stay in the user session.
-
-To change this, set the B<scratch> variable C<mv_put_session> on the page
-in question:
-
-    [set mv_put_session]Yes[/set]
-
-This setting is persistent, so it is recommended that you
-do it once at the beginning of the user session if you wish it to be the
-default. If you don't want it to be the default, reset it to the
-empty value (or zero) on another page:
-
-    [set mv_put_session][/set]
-
-=head2 Using a Search Cache
-
-Each catalog may maintain a search cache, which is enabled by specifying
-C<Yes> for the I<SearchCache> directive in F<catalog.cfg>. It operates
-by developing a MD5 key or 3-byte checksum of the combined parameters
-of a search.
-
-If your catalog frequently specifies category searches in a
-large catalog, speed of search return can be increased by a
-large factor, mostly by obviating the need for database lookups.
-
-If you have mostly dynamic session-based content based on user
-variables, you should not use SearchCache unless you want
-to give that up. MiniVend will not cache pages with dynamic
-content, and using cache slows down searches that don't cache.
-
-If you have the MD5 module installed on Perl, it will be used to generate
-the cache keys. This will guarantee a unique cache ID. If you don't
-have MD5 installed, a 32-bit checksum will be used to create the cache
-key. It is conceivable, indeed likely in a large catalog, that two
-separate searches could generate the same 32-bit checksum and return
-the same cached search.
-
-The search cache is invalidated when a user hits "RELOAD". It
-can also be invalidated by a C<[set mv_no_cache]1[/set]> scratch setting,
-which only takes effect for the next page.
-
-If you change your product database or any other files you search, you
-should reconfigure or the search returns may be wrong. You also may just
-remove all files in the tmp/ directory.
-
-Search caching is disabled on a client-by-client basis if the
-client browser does not have cookie capability, for the generated
-session numbers would be incorrect otherwise.
-
-Multiple page returns are also cached. If you C<[set mv_no_count]1[/set]>
-on the calling page, then the user's browser will keep track of the
-traveled links.
-
-The last search can be recalled with C<[page href="[data session last_search]"]>.
-
 =head1 THE ORDER PROCESS
 
 MiniVend has a completely flexible order basket and checkout
@@ -8334,6 +8291,39 @@ the check of the email address if any of the previous checks failed.
 If you want to place multiple order profiles in the same file,
 separate them with __END__, which must be on a line by itself.
 
+
+User-defined check routines can be defined in a GlobalSub:
+
+       GlobalSub <<EOF
+       sub set_up_extra_check {
+               BEGIN {
+                       package Vend::Order;
+                       sub _pt_postcode {
+                               # $ref is to Vend::Session->{'values'} hash
+                               # $var is the passed name of the variable
+                               # $val is current value of checked variable
+                               my($ref, $var, $val) = @_;
+                               
+                               if ($ref->{country} =~ /^(PT|portugal)$/i) {
+                                       return $val =~ /^\d\d\d\d$/ ?  1 : 0;
+                               }
+                               else {
+                                       return 1;
+                               }
+                       }
+               }
+       }
+       EOF
+
+Now you can specify in an order profile:
+
+  postcode=pt_postcode
+
+There must be an underscore preceding the routine name in this
+case. Very elaborate checks are possible, of course. If some user
+takes on the polyglot it would be appreciated if they contribute
+the routines.
+
 =head2 Simple Order Report File
 
 The simple order report file, "report", defines the layout of the order
@@ -9312,10 +9302,10 @@ be directly after the list call:
         [item-price] [item-code]<BR>
     [/item-list]
  
-    [tag each products]
+    [loop search="ra=yes"]
     [sort products:category products:title]
     [loop-field category] [loop-field title] <BR>
-    [/tag]
+    [/loop]
 
 All sort situations -- C<[search list]> , C<[loop list]> , C<[tag each table]>, and
 C<[item-list]>, take options of the form:
@@ -12248,10 +12238,10 @@ document notation in minivend.cfg.
 With this in effect, the internal HTTP server would map the following
 addresses:
 
-    http://www.minivend.com:7786   mv_admin
-    http://www.minivend.com:7787   simple
-    http://www.minivend.com:7788   sample
-    http://www.minivend.com:7789   search
+    *:7786   mv_admin
+    *:7787   simple
+    *:7788   sample
+    *:7789   search
 
 NOTE: This does not pertain to the use of C<tlink>, which still
 relies on the CGI SCRIPT_PATH.
@@ -12261,6 +12251,17 @@ be set in the C<Catalog> directive. This would look like:
 
   Catalog  simple  /home/minivend/catalogs/simple /cgi-bin/simple /simple
 
+If you want to bind to specific IP addresses, add them in the same
+fashion that you would an Apache Listen directive:
+
+       TcpMap <<EOF
+               127.0.0.1:7786         -
+               www.minivend.com:7787  -
+       EOF
+
+NOTE: As usual, the EOF should be at the beginning of a line with no leading
+or trailing whitespace.
+
 =head2 TemplateDir
 
 Sets a directory which will be searched for pages if not found in the users
@@ -14241,6 +14242,8 @@ testing and feature content. They include:
     Bob Jordan         
     Brian Bullen       
     Bruce Albrecht     
+    Christian Mueller
+       Christopher Thompson
     Don Grodecki       
     Frank Bonita       
     Gunnar Hellekson   
index 86ba48d..f671d78 100644 (file)
@@ -4,7 +4,7 @@ mvfaq - MiniVend FAQ
 
 =head2 VERSION
 
-Document version: $Id: mvfaq.pod,v 1.4 2000/03/28 05:37:15 mike Exp $
+Document version: $Id: mvfaq.pod,v 1.5 2000/04/02 10:21:09 mike Exp $
 
 This document describes MiniVend 4.0 and later.
 
@@ -84,7 +84,7 @@ ones.
 
 These modules are strongly recommended:
 
-    MD5
+    Digest::MD5
     MIME::Base64
     SQL::Statement
     URI::URL
@@ -2553,6 +2553,9 @@ of passing a parameter).
 =head1 CHANGES
 
 $Log: mvfaq.pod,v $
+Revision 1.5  2000/04/02 10:21:09  mike
+* minor updates
+
 Revision 1.4  2000/03/28 05:37:15  mike
 Minor pod warning fixes.
 
index a3f85a0..3fa3fe1 100644 (file)
@@ -444,11 +444,7 @@ my %Prefix = (
        cgiurl       =>  sub {
                                                        return $ENV{MVC_CGIURL} if $ENV{MVC_CGIURL};
                                                        my $url = '';
-                                                       if ($Windows) {
-                                                               $url .= $Conf{cgibase} . '/' .
-                                                                               $catalog_name  . '.exe';
-                                                       }
-                                                       elsif ($Conf{cgibase} eq '') {
+                                                       if ($Conf{cgibase} eq '') {
                                                                $url =  $Tilde if defined $Tilde;
                                                                $url .= '/' .
                                                                                $catalog_name .
@@ -973,7 +969,7 @@ EOF
        }
 
        $Cfg->WriteConfig("$Configfile.new")
-               and rename "$Configfile.new", $Configfile;
+               and File::Copy::copy "$Configfile.new", $Configfile;
 
        print "#########     END BASE CONFIGURATION      #########\n\n";
 
@@ -1052,7 +1048,7 @@ if($Removeconfig) {
 }
 elsif ( ! prefix('nocopy') ) {
        $Cfg->WriteConfig("$Configfile.new")
-               and rename "$Configfile.new", $Configfile;
+               and File::Copy::copy "$Configfile.new", $Configfile;
 }
 
 undef $Cfg;
@@ -1172,9 +1168,7 @@ SETLINKMODE: {
        }
        if ($Windows) {
                $Conf{linkmode} = 'INET';
-               $prog = -f "$Conf{relocate}$Conf{vendroot}/win/tlink.exe"
-                               ? "$Conf{relocate}$Conf{vendroot}/win/tlink.exe"
-                               : "$Conf{relocate}$ProgRoot/win/tlink.exe";
+               $prog = "$Conf{relocate}$Conf{vendroot}/src/tlink.pl";
                last SETLINKMODE;
        }
        print <<EOF;
@@ -1784,8 +1778,8 @@ POSTCMD: {
                my ($newcfgline, $mark, @out);
                my ($tmpfile) = "minivend.cfg.$$";
                if (-f 'minivend.cfg') {
-                       rename ("minivend.cfg", $tmpfile)
-                               or die "\nCouldn't rename minivend.cfg: $!\n";
+                       File::Copy::copy ("minivend.cfg", $tmpfile)
+                               or die "\nCouldn't copy minivend.cfg: $!\n";
                }
                else {
                        File::Copy::copy('minivend.cfg.dist', $tmpfile);
@@ -1940,7 +1934,7 @@ makecat [--options] name
 
 =head1 VERSION
 
-$Id: makecat.PL,v 1.4 2000/03/25 21:51:48 racke Exp $
+$Id: makecat.PL,v 1.7 2000/04/16 00:19:12 mike Exp $
 
 =head1 INTRODUCTION
 
index 4550f37..dbab2c8 100644 (file)
@@ -25,7 +25,7 @@ DOIT: {
 #
 # MiniVend version 4.0xxx
 #
-# $Id: minivend.PL,v 1.4 2000/03/28 04:28:06 mike Exp $
+# $Id: minivend.PL,v 1.7 2000/04/16 00:19:12 mike Exp $
 #
 # Copyright 1996-2000 by Michael J. Heins <mikeh@minivend.com>
 #
@@ -124,7 +124,7 @@ use vars qw($VERSION);
 require Exporter;
 
 BEGIN {
-       $VERSION = '4.03';
+       $VERSION = '4.04';
 }
 
 
@@ -190,35 +190,6 @@ BEGIN {
 }
 
 
-eval {
-       package Vend::Order;
-       require CCLib;
-       $Vend::CC2 = 1;
-       my $ver = $CCLib::VERSION || '2.1';
-       ::logGlobal({}, "CyberCash module found (Version %s)", $ver )
-               unless $Vend::Quiet;
-};
-
-$Vend::CyberCash = ! $@;
-
-eval {
-       package Vend::Order;
-       require CCMckLib3_2 ;
-       import CCMckLib3_2 qw/InitConfig %Config $MCKversion/;
-       require CCMckDirectLib3_2;
-       import CCMckDirectLib3_2 qw/SendCC2_1Server doDirectPayment/;
-       require CCMckErrno3_2;
-       import CCMckErrno3_2 qw/MCKGetErrorMessage/;
-       $Vend::CC3 = 1;
-       $Vend::CC3server = 0;
-       my $ver = $CCMckLib3_2::VERSION || '3.x';
-       ::logGlobal({}, "CyberCash module found (Version %s)", $ver )
-               unless $Vend::Quiet;
-};
-
-$Vend::CyberCash = $Vend::CyberCash || ! $@;
-
-
 use Vend::Util;
 use Vend::Server;
 use Vend::Session;
@@ -1189,7 +1160,7 @@ sub dispatch {
 
        adjust_cgi();
 
-    my($sessionid, $path);
+    my($sessionid);
        my(@path);
        my($g, $action);
 
@@ -1473,14 +1444,18 @@ EOF
        $CGI::pragma = 'no-cache'
                if delete $Vend::Session->{scratch}{mv_no_cache};
 
-       $path = $Vend::Session->{last_url} = $CGI::path_info;
-       if(     defined $Vend::Session->{one_time_path_alias}{$path} ) {
-               $CGI::path_info = $path = delete $Vend::Session->{one_time_path_alias}{$path};
+       $Vend::FinalPath = $Vend::Session->{last_url} = $CGI::path_info;
+       if(     defined $Vend::Session->{one_time_path_alias}{$Vend::FinalPath} ) {
+               $CGI::path_info
+                                       = $Vend::FinalPath
+                                       = delete $Vend::Session->{one_time_path_alias}{$Vend::FinalPath};
        } 
-       elsif( defined $Vend::Session->{path_alias}{$path}      ) {
-               $CGI::path_info = $path = $Vend::Session->{path_alias}{$path};
+       elsif( defined $Vend::Session->{path_alias}{$Vend::FinalPath}   ) {
+               $CGI::path_info
+                                       = $Vend::FinalPath
+                                       = $Vend::Session->{path_alias}{$Vend::FinalPath};
        }
-    url_history($path) if $Vend::Cfg->{History};
+    url_history($Vend::FinalPath) if $Vend::Cfg->{History};
 
        if($Vend::Cfg->{DisplayErrors} and $Global::DisplayErrors) {
                $SIG{"__DIE__"} = sub {
@@ -1497,11 +1472,11 @@ EOF
 
 # LEGACY
        ROUTINES: {
-               last ROUTINES unless index($path, '/process/') == 0;
-               while ($path =~ s:/process/(locale|language|currency)/([^/]*)/:/process/:) {
+               last ROUTINES unless index($Vend::FinalPath, '/process/') == 0;
+               while ($Vend::FinalPath =~ s:/process/(locale|language|currency)/([^/]*)/:/process/:) {
                        $Vend::Session->{scratch}->{"mv_$1"} = $2;
                }
-               $path =~ s:/process/page/:/:;
+               $Vend::FinalPath =~ s:/process/page/:/:;
        }
        my $locale;
        if($locale = $Vend::Session->{scratch}->{mv_language}) {
@@ -1526,21 +1501,17 @@ EOF
 # END LEGACY
 
        my $macro;
-       if (
-               defined $Vend::Cfg->{Autoload} and
-               $macro = $Vend::Cfg->{Autoload}
-               )
-       {
+       if ($macro = $Vend::Cfg->{Autoload}) {
                if($macro =~ /\[\w+/) {
                        interpolate_html($macro);
                }
+               elsif ($macro =~ /^\w+$/) {
+                       my $sub = $Vend::Cfg->{Sub}{$macro} || $Global::GlobalSub->{$macro};
+                       $sub->();
+               }
        }
 
-       if (
-               defined $Vend::Cfg->{Filter} and
-               $macro = $Vend::Cfg->{Filter}
-               )
-       {
+       if ($macro = $Vend::Cfg->{Filter}) {
                for(keys %$macro) {
                        Vend::Interpolate::input_filter_do($_, { 'op' => $macro->{$_} } );
                }
@@ -1573,28 +1544,27 @@ EOF
 
     # If the cgi-bin program was invoked with no extra path info,
     # just display the catalog page.
-    if (! $path || $path =~ m:^/+$:) {
-               $path = find_special_page('catalog');
+    if (! $Vend::FinalPath || $Vend::FinalPath =~ m:^/+$:) {
+               $Vend::FinalPath = find_special_page('catalog');
     }
 
-       $path =~ s:^/+::;
-       $path =~ s/\.html?$//;
-#::logDebug("path=$path");
-       $Vend::FinalPath = $path;
-    @path = split('/', $path, 2);
+       $Vend::FinalPath =~ s:^/+::;
+       $Vend::FinalPath =~ s/\.html?$//;
+#::logDebug("path=$Vend::FinalPath");
+
+    @path = split('/', $Vend::FinalPath, 2);
        if (defined $CGI::values{mv_action}) {
                $Vend::Action = 'process';
                $CGI::values{mv_todo} = $CGI::values{mv_action}
                        if ! defined $CGI::values{mv_todo} and ! defined $CGI::values{mv_doit};
-               $CGI::values{mv_nextpage} = $path
+               $CGI::values{mv_nextpage} = $Vend::FinalPath
                        if ! defined $CGI::values{mv_nextpage};
        }
        else {
                $Vend::Action = shift @path;
-               $Vend::FinalPath = join "", @path;
        }
 
-#::logDebug("action=$Vend::Action path=$path");
+#::logDebug("action=$Vend::Action path=$Vend::FinalPath");
        my ($sub, $status);
        Vend::Interpolate::reset_calc();
        if(defined $Vend::Cfg->{ActionMap}{$Vend::Action}) {
@@ -1603,8 +1573,8 @@ EOF
                $CGI::values{mv_nextpage} = $Vend::FinalPath
                        if ! defined $CGI::values{mv_nextpage};
        }
-       elsif ( ! defined ($sub = $action{$Vend::Action}) )  {
-               $Vend::FinalPath = $path;
+       elsif ( defined ($sub = $action{$Vend::Action}) )  {
+               $Vend::FinalPath = join "", @path;
        }
 
        eval {
@@ -1632,13 +1602,23 @@ EOF
                ::response($template);
        }
 
-       $CGI::values{mv_nextpage} = $path
+       $CGI::values{mv_nextpage} = $Vend::FinalPath
                if ! defined $CGI::values{mv_nextpage};
 
        do_page() if $status;
 
 #::logDebug ("end dispatch: " . (join " ", times()) . "\n");
 
+       if(my $macro = $Vend::Cfg->{AutoEnd}) {
+               if($macro =~ /\[\w+/) {
+                       interpolate_html($macro);
+               }
+               elsif ($macro =~ /^\w+$/) {
+                       $sub = $Vend::Cfg->{Sub}{$macro} || $Global::GlobalSub->{$macro};
+                       $sub->();
+               }
+       }
+
        put_session() if $Vend::HaveSession;
        close_database();
 
@@ -2082,10 +2062,40 @@ sub main_loop {
        $Global::PIDfile = "$Global::ConfDir/minivend.pid";
        $Vend::mode = 'serve';      # mode will be reset by options if appropriate
        parse_options() or die usage() . "\n";
-       if($> == 0) {
+       if($> == 0 and ! $Global::Windows) {
                die errmsg("The Minivend server must not be run as root.\n")
                        unless $ENV{MINIVEND_ROOT} =~ m{/blib$};
        }
+
+       ## Moved here to prevent unwanted messages
+       eval {
+               package Vend::Order;
+               require CCLib;
+               $Vend::CC2 = 1;
+               my $ver = $CCLib::VERSION || '2.1';
+               ::logGlobal({}, "CyberCash module found (Version %s)", $ver )
+                       unless $Vend::Quiet;
+       };
+
+       $Vend::CyberCash = ! $@;
+
+       eval {
+               package Vend::Order;
+               require CCMckLib3_2 ;
+               import CCMckLib3_2 qw/InitConfig %Config $MCKversion/;
+               require CCMckDirectLib3_2;
+               import CCMckDirectLib3_2 qw/SendCC2_1Server doDirectPayment/;
+               require CCMckErrno3_2;
+               import CCMckErrno3_2 qw/MCKGetErrorMessage/;
+               $Vend::CC3 = 1;
+               $Vend::CC3server = 0;
+               my $ver = $CCMckLib3_2::VERSION || '3.x';
+               ::logGlobal({}, "CyberCash module found (Version %s)", $ver )
+                       unless $Vend::Quiet;
+       };
+
+       $Vend::CyberCash = $Vend::CyberCash || ! $@;
+
        delete $INC{'FindBin.pm'};
        delete $INC{'Getopt/Long.pm'};
        $Global::ErrorFile = "$Global::VendRoot/error.log"
@@ -2279,6 +2289,7 @@ Contributions to MiniVend have been made by:
     Brian Bullen           
     Bruce Albrecht         
     Christian Mueller
+       Christopher Thompson
     Don Grodecki           
     Frank Bonita           
     Gunnar Hellekson