dist/simple/images/blue_pap.gif
dist/simple/images/coolad1.gif
dist/simple/images/coolbits.gif
+dist/simple/images/download.gif
dist/simple/images/mini.gif
dist/simple/images/mvlogo.gif
dist/simple/images/mvlogo_dark.gif
lib/Vend/Cart.pm
lib/Vend/Config.pm
lib/Vend/Data.pm
+lib/Vend/DbSearch.pm
lib/Vend/FlyCat.pm
lib/Vend/Glimpse.pm
lib/Vend/Http.pm
unless $install;
# Do the extra library checks
- eval {
- require File::Spec;
- };
- if ($@) {
- push @extra_lib_dirs, 'File', 'File/Spec';
- my (@f) = glob 'extra/File/Spec/*';
- for (@f) { s:extra/:: }
- push @extra_lib_files, 'File/Spec.pm', @f;
- }
# We will use our own version of File::CounterFile always
push @extra_lib_dirs, 'File';
W H A T ' S N E W
+MiniVend 3.14 is a bug fix release with a couple of new features:
+
+ * You can now specify a database in minivend.cfg. It becomes
+ global and is available in all catalogs. It also remains connected
+ all of the time, so no connection overhead exists. Careful;
+ it is writable by any catalog unless you use WRITE_CONTROL
+ defined below.
+
+ * Added write control to all databases including SQL. If you wish to
+ control writing of a global database, or to a certain catalog within
+ a series of subcatalogs, or make one read only, you can do so.
+
+ To enable write control:
+
+ Database products WRITE_CONTROL 1
+
+ Once that is done, you can make a database read only, which won't
+ allow writing even if [tag flag write]products[/tag] is specified:
+
+ Database products READ_ONLY 1
+
+ If you want to have control with [tag flag write]products[/tag]:
+
+ Database products WRITE_TAGGED 1
+
+ If you want to limit write to certain catalogs, you can set:
+
+ Database products WRITE_CATALOG simple=0, sample=1
+
+ The "simple" catalog will not be able to write, while "sample"
+ will if [tag flag write]products[/tag] is enabled.
+
+ If you want a database to be always writable without having
+ to specify [tag flag write] ... [/tag], then you can
+ define:
+
+ Database products WRITE_ALWAYS 1
+
+ The default behavior of SQL datbases is equivalent to
+ WRITE_ALWAYS, while the default for GDBM_File, DB_File,
+ and Memory databases is equivalent to:
+
+ Database products WRITE_CONTROL 1
+ Database products WRITE_TAGGED 1
+
+ As a side effect, I also removed the server error if a write
+ fails on a DBM database. It simply doesn't write and logs
+ the problem.
+
+ * Added a DbSearch.pm module which adds a new search type called
+ "db". This searches a SQL database with MiniVend search types,
+ or searches a MiniVend database instead of the ASCII file.
+
+ If it is a SQL table being searched, you can specify a coordinated
+ search and any "==" or "eq" operators will be used to filter the
+ initial search return. Otherwise, all rows of the database are
+ scanned upon each search. This can get slow, so you won't want to
+ do this for large tables.
+
+ The major difference between this and the TextSearch type is that
+ you must set base_directory to the table name/identifier of the
+ default database being searched; it defaults to 'products', which
+ is probably not what you want. This sets the field specifications
+ for the SQL qualification, so you must be careful. You can search
+ multiple tables, which will work well if the column names and orders
+ are the same. It will not work well if they are different, so it will
+ be rare when you want to search multiple tables.
+
+ Bug fixes:
+
+ * Set default for NewReport to "yes", which prevents the occasional
+ problem with returning a bogus error report if mv_order_report is
+ not set.
+
+ * Fixed some weirdness in parsing certain search parameters, notably
+ mv_sql_query and index search specifications.
+
+ * Changed sort variables to globals so that sorting should be
+ reliable. I hope.
+
+ * Fixed quantity problem for [price code].
+
+ * Made mv_order_subject work for order routing.
+
+ * Order tracking now can be done in order routing.
+
MiniVend 3.12 is a major release with multiple new features,
particularly in the area of user access control.
#
# MiniVend session dumper
#
-# $Id: dump,v 1.11 1999/01/23 19:52:33 mike Exp $
+# $Id: dump,v 1.14 1999/06/07 08:08:56 mike Exp mike $
#
# This program is largely based on Vend 0.2
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
#
# MiniVend session expiration
#
-# $Id: expire,v 1.13 1999/01/23 19:52:35 mike Exp $
+# $Id: expire,v 1.16 1999/06/07 08:09:03 mike Exp mike $
#
# This program is largely based on Vend 0.2
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
}
BEGIN {
- $VERSION = '3.12';
+ $VERSION = '3.14';
}
use strict;
use Fcntl;
use Vend::Scan;
use Vend::TextSearch;
+use Vend::DbSearch;
use Vend::Order;
use Vend::Data;
use Vend::Util;
unless ($Vend::Cfg->{Locale}) {
for(@n) {
next unless $Vend::Cfg->{Locale_repository}{$_}{'default'};
+ $Vend::Cfg->{DefaultLocale} = $_;
$Vend::Cfg->{Locale} = $Vend::Cfg->{Locale_repository}{$_};
last;
}
- $Vend::Cfg->{Locale} = $Vend::Cfg->{Locale_repository}{$n[0]}
- unless $Vend::Cfg->{Locale};
+ unless ($Vend::Cfg->{Locale}) {
+ $Vend::Cfg->{Locale} = $Vend::Cfg->{Locale_repository}{$n[0]};
+ $Vend::Cfg->{DefaultLocale} = $n[0];
+ }
}
}
undef $Vend::Cfg->{$_};
}
copyref $c, $Vend::Cfg;
+ if($Vend::Cfg->{Variable}{MV_LANG}) {
+ my $loc = $Vend::Cfg->{Variable}{MV_LANG};
+ $Vend::Cfg->{Locale} = $Vend::Cfg->{Locale_repository}{$loc}
+ if defined $Vend::Cfg->{Locale_repository}{$loc};
+ }
$Vend::Cfg->{StaticPage} = {}
unless $Vend::Cfg->{Static};
}
last COOKIELOGIN unless
$password = Vend::Util::read_cookie('MV_PASSWORD');
$CGI::values{mv_password} = $password;
+ eval {
Vend::UserDB::userdb('login');
+ };
+ if($@) {
+ $Vend::Session->{failure} .= $@;
+ }
}
}
$Vend::Session->{'id'} = $Vend::SessionID;
- $Vend::Session->{'arg'} = $Vend::Argument;
+ $Vend::Session->{'arg'} =
+ $Vend::Argument ? ($Vend::Argument) : $CGI::values{mv_arg} || '';
$Vend::Session->{'source'} = $rest
if ! $Vend::Session->{source} &&
$rest && $rest =~ /[A-Za-z]/;
defined $Vend::Cfg->{Locale_repository}->{$locale}
)
{
+ $Global::Variable->{LANG}
+ = $Vend::Cfg->{Variable}->{LANG}
+ = $::Scratch->{mv_language}
+ = $locale
+ if ! $::Scratch->{mv_language};
Vend::Util::setlocale( $locale,
($Vend::Session->{scratch}{mv_currency} || undef)
);
DOMULTI: {
for (@parts) {
- last if ! $_ || $_ eq '--';
+ last if ! $_ || ($_ =~ /^--(\r?\n)?$/);
s/^\s+//;
my($header, $data) = split /\r?\n\r?\n/, $_, 2;
my $token = '[-\w!\#$%&\'*+.^_\`|{}~]';
#
# offline - MiniVend database builder and indexer
#
-# $Id: offline,v 1.8 1998/07/18 11:48:28 mike Exp $
+# $Id: offline,v 1.9 1999/06/07 08:09:25 mike Exp mike $
#
# This program is largely based on Vend 0.2
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
<BR>[page quantity [item-code]]
<FONT SIZE=1 COLOR=RED>QUANTITY PRICING</FONT>
</A>
+ [if-field weight]
[summary amount="[calc][item-quantity] * ([item-field weight] || 0)[/calc]" hide=1]
+ [/if-field]
<BR><FONT SIZE="-1">
[if-field related]
[loop arg="[item-field related]"]
<LI><A HREF="#IMPORT_ONCE">IMPORT_ONCE</A>
<LI><A HREF="#Importing_in_a_page">Importing in a page</A>
<LI><A HREF="#Exporting_from_a_database">Exporting from a database</A>
+ <LI><A HREF="#Write_Control">Write Control</A>
+ <LI><A HREF="#Global_Databases">Global Databases</A>
</UL>
<LI><A HREF="#SQL_SUPPORT">SQL SUPPORT</A>
<P>
<HR>
+<H2><A NAME="Write_Control">Write Control</A></H2>
+<P>
+MiniVend databases can be written in the normal course of events, either
+using the <CODE>[import ...]</CODE> tag or with a tag like
+<CODE>[data table=table column=field key=code value=new-value]</CODE>.
+
+<P>
+If you wish to control writing of a global database, or to a certain
+catalog within a series of subcatalogs, or make one read only, you can do
+so.
+
+<P>
+To enable write control:
+
+<P>
+<PRE> Database products WRITE_CONTROL 1
+</PRE>
+<P>
+Once that is done, you can make a database read only, which won't allow
+writing even if <CODE>[tag flag write]products[/tag]</CODE> is specified:
+
+<P>
+<PRE> Database products READ_ONLY 1
+</PRE>
+<P>
+If you want to have control with <CODE>[tag flag write]products[/tag]</CODE>:
+
+<P>
+<PRE> Database products WRITE_TAGGED 1
+</PRE>
+<P>
+If you want to limit write to certain catalogs, you can set:
+
+<P>
+<PRE> Database products WRITE_CATALOG simple=0, sample=1
+</PRE>
+<P>
+The ``simple'' catalog will not be able to write, while ``sample'' will if <CODE>[tag flag write]products[/tag]</CODE> is enabled.
+
+<P>
+If you want a database to be always writable without having to specify <CODE>[tag flag write] ... [/tag]</CODE>, then you can define:
+
+<P>
+<PRE> Database products WRITE_ALWAYS 1
+</PRE>
+<P>
+The default behavior of
+<FONT SIZE=-1>SQL</FONT> datbases is equivalent to
+<FONT SIZE=-1>WRITE_ALWAYS,</FONT> while the default for GDBM_File, DB_File, and Memory databases is equivalent to:
+
+<P>
+<PRE> Database products WRITE_CONTROL 1
+ Database products WRITE_TAGGED 1
+</PRE>
+<P>
+<HR>
+<H2><A NAME="Global_Databases">Global Databases</A></H2>
+<P>
+If you have a database you want to make available to all catalogs on the MiniVend server instance, you may define a database in minivend.cfg. Any catalog running under that server will be able to use it. Careful; it is writable by any catalog unless you use
+<FONT SIZE=-1>WRITE_CONTROL.</FONT>
+
+<P>
+<HR>
<H1><A NAME="SQL_SUPPORT">SQL SUPPORT</A></H1>
<P>
MiniVend can use any of a number of
mv_return_delim rd S Return record delimiter
mv_return_fields rf S Fields to return on a search
mv_return_file_name rn S Set return of file name for searches
- mv_return_spec rs S Return the MiniVend page specified in search string
+ mv_return_spec rs S Return the search string as the only result
mv_save_session C Set to non-zero to prevent expiration of user session
mv_search_field sf S Sets the fields to be searched
mv_search_file fi S Sets the file(s) to be searched
mv_search_line_return lr S Each line is a return code (loop search)
- mv_search_match_count S Returns the number of matches found (read-only)
+ mv_search_match_count S Returns the number of matches found (read-only)
mv_search_over_msg S Returns string indicating search overflow (read-only)
mv_search_page sp S Sets the page for search display
mv_searchspec se S Search specification
- mv_searchtype st S Sets search type (text or glimpse)
+ mv_searchtype st S Sets search type (text, glimpse, db or sql)
mv_separate_items O Sets separate order lines (one per item ordered)
mv_shipmode O Sets shipping mode for custom shipping
mv_sort_command tc S Sets the command to use for sorting searches
mv_search_file S Sets the table to be searched
mv_search_page S Sets the page for search display
mv_searchspec S Search specification(s)
- mv_searchtype S Sets search type (text, glimpse, or sql)
+ mv_searchtype S Sets search type (text, glimpse, db, or sql)
mv_sort_field S Column(s) to sort on
mv_sort_option S Options for sort (only global reverse)
mv_sql_query S SQL query text for simple query
field to be returned if searching the products database, since that is the
key for accessing database fields.
+<P><DT><STRONG><A NAME="item_mv_return_spec">mv_return_spec</A></STRONG><DD>
+
+Returns the string specified as the search (i.e. the value of <A HREF="#item_mv_searchspec">mv_searchspec</A>) as the one and only match. Typically used in a SKU/part number search.
+
<P><DT><STRONG><A NAME="item_mv_search_field">mv_search_field</A></STRONG><DD>
The <CODE>field(s)</CODE> to be searched, specified either by column name
<FONT SIZE=-1>SQL</FONT> select statement to return the search list.
<P>
+If set to <EM>db</EM>, iterates over every row of the database (not the associated text source
+file).
+
+<P>
If set to <EM>text</EM>, selects the text-based search.
<P>
Default is not to increment, as the order number should usually be the same
for different routes within the same customer order.
+<P><DT><STRONG><A NAME="item_individual_track">individual_track</A></STRONG><DD>
+
+<FONT SIZE=-1>A</FONT> <EM>directory</EM> where individual order tracking files will be placed. The file name will
+correspond to the value of <CODE>mv_order_number</CODE>. This can be useful for batching orders via download.
+
<P><DT><STRONG><A NAME="item_pgp_cc_key">pgp_cc_key</A></STRONG><DD>
The
Whether this route should supplant the main order report. If set, the <EM>AsciiTrack</EM> operation will use this route and the normal MiniVend order email sequence
will not be performed.
+<P><DT><STRONG><A NAME="item_track">track</A></STRONG><DD>
+
+The name of a file which should be used for tracking. If the
+<A HREF="#item_supplant">supplant</A> attribute is set, then the normal order tracking will be used as well.
+
+<P><DT><STRONG>track</STRONG><DD>
+
+<FONT SIZE=-1>A</FONT> number representing the mode to change either <A HREF="#item_track">track</A> or
+<A HREF="#item_individual_track">individual_track</A> files to.
+
<P></DL>
<P>
An individual item routing causes all items labeld with that route to be
<P><A HREF="minivend.html#SETTING_UP_YOUR_CATALOG">SETTING UP YOUR CATALOG</A>
<BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Start_with_a_database">Start with a database</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#On_the_fly_pages_static_or_bot">On-the-fly pages, static, or both?</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Use_the_demo_catalogs">Use the demo catalogs</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Tree_design">Tree design</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#The_Essentials">The Essentials</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Catalog_Pages_MiniVend_tags">Catalog Pages -- MiniVend tags</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Cookies">Cookies</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Basic_MiniVend_Tags">Basic MiniVend Tags</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#_area_">[area ...]</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#How_to_order_an_item">How to order an item</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Where_do_I_go_from_here_">Where do I go from here?</A>
<P><A HREF="minivend.html#DATABASES">DATABASES</A>
-<BR><IMG SRC="bullet.gif"><A HREF="minivend.html#The_Product_Database">The Product Database</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Arbitrary_Databases">Arbitrary Databases</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#MiniVend_built_in_database_suppo">MiniVend built-in database support</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Character_usage_restrictions">Character usage restrictions</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Import_Attributes">Import Attributes</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Dictionary_indexing_with_INDEX">Dictionary indexing with INDEX</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#MEMORY_for_memory_only_databases">MEMORY for memory-only databases</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#IMPORT_ONCE">IMPORT_ONCE</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Importing_in_a_page">Importing in a page</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Exporting_from_a_database">Exporting from a database</A>
+<BR><IMG SRC="bullet.gif"><A HREF="minivend.html#The_Product_Database">The Product Database</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Arbitrary_Databases">Arbitrary Databases</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#MiniVend_built_in_database_suppo">MiniVend built-in database support</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Character_usage_restrictions">Character usage restrictions</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Import_Attributes">Import Attributes</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Dictionary_indexing_with_INDEX">Dictionary indexing with INDEX</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#MEMORY_for_memory_only_databases">MEMORY for memory-only databases</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#IMPORT_ONCE">IMPORT_ONCE</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Importing_in_a_page">Importing in a page</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Exporting_from_a_database">Exporting from a database</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Write_Control">Write Control</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Global_Databases">Global Databases</A>
<P><A HREF="minivend.html#SQL_SUPPORT">SQL SUPPORT</A>
<BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Msql_support">Msql support</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#SQL_support_via_DBI">SQL support via DBI</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#SQL_Access_Methods">SQL Access Methods</A><BR><IMG SRC="bullet.gif"><A HREF="minivend.html#Importing_from_an_ASCII_file">Importing from an ASCII file</A>
<P><A HREF="minivend.html#MINIVEND_TAG_REFERENCE">MINIVEND TAG REFERENCE</A>
</UL><LI><A HREF="minivend.html#SETTING_UP_YOUR_CATALOG">SETTING UP YOUR CATALOG</A>
<UL><LI><A HREF="minivend.html#Start_with_a_database">Start with a database</A><LI><A HREF="minivend.html#On_the_fly_pages_static_or_bot">On-the-fly pages, static, or both?</A><LI><A HREF="minivend.html#Use_the_demo_catalogs">Use the demo catalogs</A><LI><A HREF="minivend.html#Tree_design">Tree design</A><LI><A HREF="minivend.html#The_Essentials">The Essentials</A><LI><A HREF="minivend.html#Catalog_Pages_MiniVend_tags">Catalog Pages -- MiniVend tags</A><LI><A HREF="minivend.html#Cookies">Cookies</A><LI><A HREF="minivend.html#Basic_MiniVend_Tags">Basic MiniVend Tags</A><LI><A HREF="minivend.html#_area_">[area ...]</A><LI><A HREF="minivend.html#How_to_order_an_item">How to order an item</A><LI><A HREF="minivend.html#Where_do_I_go_from_here_">Where do I go from here?</A>
</UL><LI><A HREF="minivend.html#DATABASES">DATABASES</A>
-<UL><LI><A HREF="minivend.html#The_Product_Database">The Product Database</A><LI><A HREF="minivend.html#Arbitrary_Databases">Arbitrary Databases</A><LI><A HREF="minivend.html#MiniVend_built_in_database_suppo">MiniVend built-in database support</A><LI><A HREF="minivend.html#Character_usage_restrictions">Character usage restrictions</A><LI><A HREF="minivend.html#Import_Attributes">Import Attributes</A><LI><A HREF="minivend.html#Dictionary_indexing_with_INDEX">Dictionary indexing with INDEX</A><LI><A HREF="minivend.html#MEMORY_for_memory_only_databases">MEMORY for memory-only databases</A><LI><A HREF="minivend.html#IMPORT_ONCE">IMPORT_ONCE</A><LI><A HREF="minivend.html#Importing_in_a_page">Importing in a page</A><LI><A HREF="minivend.html#Exporting_from_a_database">Exporting from a database</A>
+<UL><LI><A HREF="minivend.html#The_Product_Database">The Product Database</A><LI><A HREF="minivend.html#Arbitrary_Databases">Arbitrary Databases</A><LI><A HREF="minivend.html#MiniVend_built_in_database_suppo">MiniVend built-in database support</A><LI><A HREF="minivend.html#Character_usage_restrictions">Character usage restrictions</A><LI><A HREF="minivend.html#Import_Attributes">Import Attributes</A><LI><A HREF="minivend.html#Dictionary_indexing_with_INDEX">Dictionary indexing with INDEX</A><LI><A HREF="minivend.html#MEMORY_for_memory_only_databases">MEMORY for memory-only databases</A><LI><A HREF="minivend.html#IMPORT_ONCE">IMPORT_ONCE</A><LI><A HREF="minivend.html#Importing_in_a_page">Importing in a page</A><LI><A HREF="minivend.html#Exporting_from_a_database">Exporting from a database</A><LI><A HREF="minivend.html#Write_Control">Write Control</A><LI><A HREF="minivend.html#Global_Databases">Global Databases</A>
</UL><LI><A HREF="minivend.html#SQL_SUPPORT">SQL SUPPORT</A>
<UL><LI><A HREF="minivend.html#Msql_support">Msql support</A><LI><A HREF="minivend.html#SQL_support_via_DBI">SQL support via DBI</A><LI><A HREF="minivend.html#SQL_Access_Methods">SQL Access Methods</A><LI><A HREF="minivend.html#Importing_from_an_ASCII_file">Importing from an ASCII file</A>
</UL><LI><A HREF="minivend.html#MINIVEND_TAG_REFERENCE">MINIVEND TAG REFERENCE</A>
#
# MiniVend version 3.12
#
-# $Id: Cart.pm,v 1.13 1999/02/15 08:50:23 mike Exp mike $
+# $Id: Cart.pm,v 1.14 1999/06/07 08:03:57 mike Exp $
#
# This program is largely based on Vend 0.2
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
@EXPORT_OK = qw(create add set);
-$VERSION = substr(q$Revision: 1.13 $, 10);
+$VERSION = substr(q$Revision: 1.14 $, 10);
$DEBUG = 0;
use vars qw($DEBUG $VERSION);
['Mall', 'yesno', 'No'],
['MaxServers', 'integer', 10],
['GlobalSub', 'subroutine', ''],
+ ['Database', 'database', ''],
['FullUrl', 'yesno', 'No'],
['Locale', 'locale', ''],
['HitCount', 'yesno', 'No'],
['Tracking', 'warn', ''],
['BackendOrder', undef, ''],
['SalesTax', undef, ''],
- ['NewReport', 'yesno', 'No'],
+ ['NewReport', 'yesno', 'Yes'],
['Static', 'yesno', 'No'],
['StaticAll', 'yesno', 'No'],
['StaticDepth', undef, '1'],
$c->{$_} = $sethash->{$_};
}
if($item eq 'Locale') {
+ $Vend::Cfg->{DefaultLocale} = $name;
$c->{mon_thousands_sep} = ','
unless defined $c->{mon_thousands_sep};
$c->{decimal_point} = '.'
}
my %Hash_ref = ( qw!
- COLUMN_DEF COLUMN_DEF
- NUMERIC NUMERIC
+ COLUMN_DEF COLUMN_DEF
+ NUMERIC NUMERIC
+ WRITE_CATALOG WRITE_CATALOG
! );
my %Ary_ref = ( qw!
sub parse_database {
my ($var, $value) = @_;
my ($c, $new);
- unless (defined $value && $value) {
+
+ if (! $value) {
$c = {};
return $c;
}
- $c = $C->{'Database'};
+
+ $c = $C ? $C->{Database} : $Global::Database;
my($database,$remain) = split /[\s,]+/, $value, 2;
- if($database ne 'products') {
+ if(! $C) {
+ # Do nada
+ }
+ elsif($database ne 'products') {
$new = 1 if ! defined $c->{$database};
}
- elsif( defined $c->{$database}->{",default"} ) {
+ elsif(defined $c->{$database}->{",default"} ) {
$new = 1 if ($C->{BaseCatalog} || ! defined $c->{$database}->{",initialized"});
$c->{$database}->{",initialized"} = 1;
}
sub tie_database {
my ($name, $data);
+ if($Global::Database) {
+ copyref($Global::Database, $Vend::Cfg->{Database});
+ }
while (($name,$data) = each %{$Vend::Cfg->{Database}}) {
# DEBUG
#Vend::Util::logDebug
sub column_exists {
my ($field_name) = @_;
- return $Products->test_column($field_name);
+ return defined $Products->test_column($field_name);
}
sub db_column_exists {
'MEMORY' => {
qw/
Cacheable 1
+ Tagged_write 1
Class Vend::Table::InMemory
/
},
qw/
TableExtension .gdbm
Extension gdbm
+ Tagged_write 1
Class Vend::Table::GDBM
/
},
qw/
TableExtension .db
Extension db
+ Tagged_write 1
Class Vend::Table::DB_File
/
},
}
}
- my $read_only = ! defined $Vend::WriteDatabase{$name};
+ my $read_only;
+
+ if($obj->{WRITE_CONTROL}) {
+ if($obj->{READ_ONLY}) {
+ $obj->{Read_only} = 1;
+ }
+ elsif($obj->{WRITE_ALWAYS}) {
+ $obj->{Read_only} = 0;
+ }
+ elsif($obj->{WRITE_CATALOG}) {
+ $obj->{Read_only} = $obj->{WRITE_CATALOG}{$Vend::Cfg->{CatalogName}}
+ ? (! defined $Vend::WriteDatabase{$name})
+ : 1;
+ }
+ elsif($obj->{WRITE_TAGGED}) {
+ $obj->{Read_only} = ! defined $Vend::WriteDatabase{$name};
+ }
+ }
+ else {
+ $obj->{Read_only} = ! defined $Vend::WriteDatabase{$name}
+ if $class_config->{Tagged_write};
+ }
if($class_config->{Extension}) {
- $obj->{Read_only} = $read_only;
$obj->{db_file} = $table_name unless $obj->{db_file};
$obj->{db_text} = $database_txt unless $obj->{db_text};
$db = $class_config->{Class}->open_table( $obj, $table_name );
$obj->{NAME} = $db->[3] unless defined $obj->{NAME};
-# DEBUG
-#Vend::Util::logDebug
-#("Opening GDBM: RO=$read_only\n")
-# if ::debug(0x4);
-# END DEBUG
+#::logError ("Opening Database $obj->{name}: RO=$obj->{Read_only} WC=$obj->{WRITE_CONTROL} WA=$obj->{WRITE_ALWAYS}\n");
+
if($@) {
die $@ unless $no_import;
if(! -f $database_dbm) {
--- /dev/null
+# Vend/DbSearch.pm: Search indexes with Perl
+#
+# $Id: DbSearch.pm,v 1.22 1999/02/15 08:51:31 mike Exp mike $
+#
+# ADAPTED FOR USE WITH MINIVEND from Search::TextSearch
+#
+# Copyright 1996-1999 by Michael J. Heins <mikeh@iac.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+package Vend::DbSearch;
+require Vend::Search;
+
+@ISA = qw(Vend::Search);
+
+$VERSION = substr(q$Revision: 1.22 $, 10);
+
+use Search::Dict;
+use strict;
+
+sub new {
+ my ($class, %options) = @_;
+ my $self = new Vend::Search;
+ my ($key,$val);
+ init($self);
+ while ( ($key,$val) = each %options) {
+ $self->{global}->{$key} = $val;
+ }
+ bless $self, $class;
+}
+
+sub init {
+ my $s = shift;
+ my $g = $s->{global};
+ $s->{global}->{base_directory} = 'products';
+ $s->{global}->{search_file} = '';
+}
+
+sub version {
+ $Vend::DbSearch::VERSION;
+}
+
+sub escape {
+ my($self, @text) = @_;
+ if($self->{'global'}->{all_chars}) {
+ @text = map {quotemeta $_} @text;
+ }
+ for(@text) {
+ s!([^\\]?)([}])!$1\\$2!g;
+ }
+ return @text;
+}
+
+sub spec_check {
+ my ($s, $g, @specs) = @_;
+ my @pats;
+ SPEC_CHECK: {
+ last SPEC_CHECK if $g->{return_all};
+ # Patch supplied by Don Grodecki
+ # Now ignores empty search strings if coordinated search
+ my $i = 0;
+
+ unless ($g->{coordinate} and @specs == @{$s->{fields}}) {
+ for(qw! case_sensitive substring_match negate !) {
+ next unless ref $g->{$_};
+ $g->{$_} = $g->{$_}->[0];
+ }
+ $g->{coordinate} = '';
+ }
+
+ while ($i < @specs) {
+ if($#specs and length($specs[$i]) == 0) { # should add a switch
+ if($g->{coordinate}) {
+ splice(@{$s->{fields}}, $i, 1);
+ splice(@{$g->{column_op}}, $i, 1)
+ if ref $g->{column_op};
+ splice(@{$g->{case_sensitive}}, $i, 1)
+ if ref $g->{case_sensitive};
+ splice(@{$g->{numeric}}, $i, 1)
+ if ref $g->{numeric};
+ splice(@{$g->{substring_match}}, $i, 1)
+ if ref $g->{substring_match};
+ splice(@{$g->{negate}}, $i, 1)
+ if ref $g->{negate};
+ }
+ splice(@specs, $i, 1);
+ splice(@{$s->{specs}}, $i, 1);
+ }
+ else {
+ if(
+ $g->{coordinate}
+ and defined $g->{column_op}
+ and $g->{column_op}[$i] =~ /^(==?|eq)$/
+ )
+ {
+ my $spec = $specs[$i];
+ $g->{eq_specs} = []
+ unless $g->{eq_specs};
+ $spec = $g->{dbref}->quote($spec)
+ if ! $s->{numeric} || (ref $s->{numeric} and ! $s->{numeric}[$i]);
+ $spec = $g->{field_names}[ $s->{fields}[$i] ] . " = $spec";
+ push(@{$g->{eq_specs}}, $spec);
+ }
+ $i++;
+ }
+ }
+
+# DEBUG
+Vend::Util::logError
+($s->dump_options() . "\nspecs=" . join("|", @specs) . "|\n")
+ if $g->{mv_search_debug};
+# END DEBUG
+
+ if ( ! $g->{exact_match} and ! $g->{coordinate}) {
+ my $string = join ' ', @specs;
+ eval {
+ @specs = Text::ParseWords::shellwords( $string );
+ };
+ if($@ or ! @specs) {
+ $string =~ s/['"]/./g;
+ $g->{all_chars} = 0;
+ @specs = Text::ParseWords::shellwords( $string );
+ }
+ }
+
+ @specs = $s->escape(@specs);
+
+# DEBUG
+Vend::Util::logDebug
+("spec='" . (join "','", @specs) . "'\n")
+ if ::debug(0x10 );
+# END DEBUG
+
+ # untaint
+ for(@specs) {
+ /(.*)/s;
+ push @pats, $1;
+ }
+ @{$s->{'specs'}} = @pats;
+
+# DEBUG
+Vend::Util::logDebug
+("pats: '" . join("', '", @pats) . "'\n")
+ if ::debug(0x10);
+# END DEBUG
+
+ } # last SPEC_CHECK
+ return @pats;
+}
+
+sub search {
+
+ my($s,%options) = @_;
+ my $g = $s->{global};
+
+ my($delim);
+ my($max_matches,$mod,$spec);
+ my($code,$count,$matches_to_send,@out);
+ my($index_delim,$limit_sub,$return_sub,$delayed_return);
+ my($dict_limit,$f,$key,$val,$range_op);
+ my($return_file_name,$searchfile,@searchfiles);
+ my(@specs);
+ my(@pats);
+
+ while (($key,$val) = each %options) {
+ $g->{$key} = $val;
+ }
+
+ if(ref($g->{search_file}) =~ /^ARRAY/) {
+ @searchfiles = @{$g->{search_file}};
+ }
+ elsif ($g->{search_file}) {
+ @searchfiles = $g->{search_file};
+ }
+ else {
+ &{$g->{error_routine}}($g->{error_page},
+ "{search_file} must be array reference or scalar.\n");
+ $g->{matches} = -1;
+ return undef; # If it makes it this far
+ }
+
+ $g->{base_directory} =~ s/\..*//;
+ my $dbref = Vend::Data::database_exists_ref($g->{base_directory});
+
+ if(! $dbref) {
+ &{$g->{error_routine}}($g->{error_page},
+ "{base_directory} must be a valid database reference, was $g->{base_directory}.\n");
+ $g->{matches} = -1;
+ return undef; # If it makes it this far
+ }
+
+#::logError("DbSearch: made it past ref check");
+
+ $dbref = $g->{dbref} = $dbref->ref();
+ my (@fn) = ($dbref->config('FIRST_COLUMN_NAME') || 'code', $dbref->columns());
+#::logError("DbSearch: fn=@fn");
+
+ $g->{field_names} = \@fn;
+ my %fh;
+ my $idx = 0;
+ for (@fn) {
+ $fh{$_} = $idx++;
+ }
+ my $fa;
+ foreach $fa ( qw/ return_fields range_look search_field sort_field /) {
+ next unless $g->{$fa};
+ for( @{$g->{$fa}} ) {
+ $_ = $fh{$_} if defined $fh{$_};
+ }
+ }
+
+ $g->{matches} = 0;
+
+ if($g->{search_spec}) {
+ @specs = $g->{search_spec};
+ }
+ else {
+ @specs = @{$s->{specs}};
+ }
+
+ if(ref $g->{range_look}) {
+ no strict 'refs';
+ unless( scalar(@{$g->{range_look}}) == scalar(@{$g->{range_min}}) and
+ scalar(@{$g->{range_look}}) == scalar(@{$g->{range_max}}) ) {
+ &{$g->{error_routine}} ($g->{error_page},
+ "Must have min and max values for range.");
+ $g->{matches} = -1;
+ return undef;
+ }
+ $range_op = 1;
+ }
+
+ @specs = '' if @specs == 0;
+
+ @pats = $s->spec_check($g, @specs);
+
+#::logError("DbSearch: made it past spec check");
+
+ if ($g->{coordinate}) {
+ undef $f;
+ }
+ elsif ($g->{return_all}) {
+ $f = sub {1};
+ }
+ elsif ($g->{or_search}) {
+ eval {$f = $s->create_search_or( $g->{case_sensitive},
+ $g->{substring_match},
+ $g->{negate},
+ @pats )};
+ }
+ else {
+ eval {$f = $s->create_search_and( $g->{case_sensitive},
+ $g->{substring_match},
+ $g->{negate},
+ @pats )};
+ }
+ if($@) {
+ &{$g->{error_routine}}($g->{error_page}, $@);
+ $g->{matches} = -1;
+ return undef;
+ }
+
+ my $prospect;
+
+ eval {
+ ($limit_sub, $prospect) = $s->get_limit($f);
+ };
+
+ if($@) {
+ &{$g->{error_routine}}($g->{error_page}, $@);
+ $g->{matches} = -1;
+ return undef;
+ }
+
+ $f = $prospect if $prospect;
+
+#::logError("f=$f limit=$limit_sub");
+
+ eval {($return_sub, $delayed_return) = $s->get_return()};
+ if($@) {
+ &{$g->{error_routine}}($g->{error_page}, $@);
+ $g->{matches} = -1;
+ return undef;
+ }
+
+ $max_matches = int($g->{max_matches});
+
+ $g->{overflow} = 0;
+ my $qual;
+
+#::logError("DbSearch: made it past return subroutines");
+
+ foreach $searchfile (@searchfiles) {
+ $searchfile =~ s/\..*//;
+#::logError("DbSearch: searching $searchfile");
+ my $db;
+ if (! $g->{mv_one_sql_table} and $db = Vend::Data::database_exists_ref($searchfile)) {
+ $dbref = $db->ref();
+ $g->{field_names} = [ $dbref->config('FIRST_COLUMN_NAME') || 'code', $dbref->columns() ];
+ }
+ if(! $qual and $g->{eq_specs}) {
+ $qual = ' WHERE ';
+ my $joiner = ' AND ';
+ $joiner = ' OR ' if $g->{or_search};
+ $qual .= join $joiner, @{$g->{eq_specs}};
+ }
+
+ if(! defined $f and defined $limit_sub) {
+#::logError("no f, limit");
+ while($_ = join "\t", $dbref->each_record($qual || undef) ) {
+ next unless &$limit_sub($_);
+ (push @out, $searchfile and last)
+ if defined $return_file_name;
+ push @out, &$return_sub($_);
+ }
+ }
+ elsif(defined $limit_sub) {
+#::logError("f and limit");
+ while($_ = join "\t", $dbref->each_record($qual || undef) ) {
+ next unless &$f();
+#::logGlobal("matched f");
+ next unless &$limit_sub($_);
+ (push @out, $searchfile and last)
+ if defined $return_file_name;
+ push @out, &$return_sub($_);
+ }
+ }
+ elsif (!defined $f) {
+#::logError("no f!!!!??!!");
+ &{$g->{error_routine}}($g->{error_page}, 'No search definition');
+ $g->{matches} = -1;
+ return undef;
+ }
+ else {
+#::logError("just f");
+ while($_ = join "\t", $dbref->each_record($qual || undef) ) {
+ next unless &$f();
+ (push @out, $searchfile and last)
+ if defined $return_file_name;
+ push @out, &$return_sub($_);
+ }
+ }
+ }
+
+ if($delayed_return) {
+ $s->sort_search_return(\@out);
+ @out = map { &{$delayed_return}($_) } @out;
+ }
+
+ if($g->{unique_result}) {
+ my %seen;
+ @out = grep ! $seen{$_}++, @out;
+ }
+
+ $g->{matches} = scalar(@out);
+
+ if ($g->{matches} > $g->{match_limit}) {
+ $s->save_more(\@out)
+ or &{$g->{log_routine}}("Error saving matches: $!");
+ if ($g->{first_match}) {
+ splice(@out,0,$g->{first_match}) if $g->{first_match};
+ $g->{next_pointer} = $g->{first_match} + $g->{match_limit};
+ $g->{next_pointer} = 0
+ if $g->{next_pointer} > $g->{matches};
+ }
+ $#out = $g->{match_limit} - 1;
+ }
+
+ return \@out unless $g->{return_reference};
+
+ if($g->{return_reference} eq 'ARRAY') {
+ my $col = scalar @{$g->{return_fields}};
+ @out = map { [ split /$g->{return_delim}/, $_, $col ] } @out;
+ }
+ elsif($g->{return_format} eq 'HASH') {
+ my $col = scalar @{$g->{return_fields}};
+ my @col;
+ my @names;
+ @names = @{$g->{field_names}};
+ $names[0] eq '0' and $names[0] = 'code';
+ my %hash;
+ my $key;
+ for (@out) {
+ @col = split /$g->{return_delim}/, $_, $col;
+ $hash{$col[0]} = {};
+ @{ $hash{$col[0]} } {@names} = @col;
+ }
+ return \%hash;
+ }
+
+ \@out;
+}
+
+1;
+__END__
#!/usr/bin/perl
#
-# $Id: FlyCat.pm,v 1.3 1999/02/15 08:51:00 mike Exp mike $
+# $Id: FlyCat.pm,v 1.5 1999/06/07 08:06:28 mike Exp mike $
#
# Copyright 1998-1999 by Michael J. Heins <mikeh@iac.net>
#
package Vend::FlyCat;
-$VERSION = substr(q$Revision: 1.3 $, 10);
+$VERSION = substr(q$Revision: 1.5 $, 10);
$DEBUG = 0;
use vars qw! $VERSION $DEBUG @S_FIELDS @B_FIELDS @P_FIELDS %S_to_B %B_to_S!;
# Vend/Glimpse.pm: Search indexes with Glimpse
#
-# $Id: Glimpse.pm,v 1.18 1999/02/15 08:51:02 mike Exp mike $
+# $Id: Glimpse.pm,v 1.20 1999/06/07 08:06:32 mike Exp mike $
#
# ADAPTED FOR USE WITH MINIVEND from Search::Glimpse
#
require Vend::Search;
@ISA = qw(Vend::Search);
-$VERSION = substr(q$Revision: 1.18 $, 10);
+$VERSION = substr(q$Revision: 1.20 $, 10);
use strict;
sub new {
#
# Imagemap.pm -- interpret NCSA imagemap in CGI program
#
-# $Id: Imagemap.pm,v 1.6 1998/01/31 05:15:40 mike Exp $
+# $Id: Imagemap.pm,v 1.7 1999/06/07 08:07:01 mike Exp mike $
#
# This module adapted from the Perl imagemap program by:
#
@EXPORT = qw(action_map);
use strict;
use vars qw($VERSION);
-$VERSION = substr(q$Revision: 1.6 $, 10);
+$VERSION = substr(q$Revision: 1.7 $, 10);
my $Action = "";
my $minDistance = -1;
}
}
elsif($op =~ /^text/) {
- $data =~ interpolate_html($data);
Vend::Util::writefile($file, $data)
or return '';
}
do_tag(join(" ", $op, $base, $file), $text);
}
elsif ($op eq 'export') {
- do_export($base, $file, $type);
+ Vend::Data::export_database($base, $file, $type);
}
elsif (!$op) {
do_tag('', $text);
}
sub escape_mv {
- my ($joiner, $scan) = @_;
+ my ($joiner, $scan, $not_scan) = @_;
my @args;
}
@args = grep $_, @args;
for(@args) {
- s!/!__SLASH__!g;
+ s!/!__SLASH__!g unless defined $not_scan;
s!\0!__NULL__!g;
s!(\w\w=)(.*)!$1 . esc($2)!eg
or (undef $_, next);
- s!__SLASH__!::!g;
+ s!__SLASH__!::!g unless defined $not_scan;
}
return join $joiner, grep(defined $_, @args);
}
$arg = '' if ! $arg;
$arg = "mv_arg=$arg\n" if $arg && $arg !~ /\n/;
$extra .= $arg . $opt->{'form'};
- $extra = escape_mv('&', $extra);
+ $extra = escape_mv('&', $extra, 1);
return $href . '?' . $extra;
}
);
-my %Sort_field = (
+%Vend::Interpolate::Sort_field = (
none => sub { $_[0] cmp $_[1] },
f => sub { (lc $_[0]) cmp (lc $_[1]) },
my(@b) = split /\t/, $b;
my ($r, $i);
for($i = 0; $i < @Flds; $i++) {
- $r = &{$Sort_field{$Opts[$i]}}($a[$Flds[$i]], $b[$Flds[$i]]);
+ $r = &{$Vend::Interpolate::Sort_field{$Opts[$i]}}($a[$Flds[$i]], $b[$Flds[$i]]);
return $r if $r;
}
}
push @bases, $base;
push @fields, $fld;
- push @option, (defined $Sort_field{$opt} ? $opt : 'none');
+ push @option, (defined $Vend::Interpolate::Sort_field{$opt} ? $opt : 'none');
}
if(defined $end) {
my $i;
my $routine = 'sub { ';
for( $i = 0; $i < @bases; $i++) {
- $routine .= '&{$Sort_field{"' . $option[$i] . '"}}(' . "\n";
+ $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 &{$Sort_field{"none"}}($a,$b); }';
+ $routine .= '0 or &{$Vend::Interpolate::Sort_field{"none"}}($a,$b); }';
#print("Sort routine: $routine\n") if $Global::DEBUG;
my $code = eval $routine;
die "Bad sort routine\n" if $@;
#Prime the sort? Prevent variable suicide??
- &{$Sort_field{'n'}}('31', '30');
+ &{$Vend::Interpolate::Sort_field{'n'}}('31', '30');
eval {
if(! $code) {
($code, $extra) = ($item->{'code'}, $item->{mv_discount});
- $quantity = $item->{$quantity} unless $quantity;
+ $quantity = $item->{quantity} unless $quantity;
$Vend::Session->{discount} = {}
if $extra and !$Vend::Session->{discount};
}
$code = 'u' unless $code;
-print("Called zone '$code' lookup with type='$type' zip='$zip' weight='$weight'\n") if $Global::DEBUG;
unless (defined $Vend::Database{$type}) {
logError("UPS lookup called, no type file loaded for '$type'");
return undef;
# here we can adapt for pounds/kg
if ($zref->{mult_factor}) {
$weight = $weight * $zref->{mult_factor};
-print("Zone '$code' weight now $weight\n") if $Global::DEBUG;
}
$weight = ceil($weight);
$zip = substr($zip, 0, ($zref->{str_length} || 3));
@fieldnames = split /\t/, $zdata->[0];
-print("Fields: @fieldnames Num" . scalar @{$zdata} . "\n") if $Global::DEBUG;
for($i = 2; $i < @fieldnames; $i++) {
next unless $fieldnames[$i] eq $type;
$point = $i;
return undef;
}
-print("Column $point for $type\n") if $Global::DEBUG;
for(@{$zdata}[1..$#{$zdata}]) {
@data = split /\t/, $_;
next unless ($zip ge $data[0] and $zip le $data[1]);
$zone = $data[$point];
-print("Found match with $zip, $zone\n") if $Global::DEBUG;
return 0 unless $zone ||= 0;
last;
}
counter => '',
increment => 0,
supplant => 0,
- track => 1,
+ track => '',
errors_to => $Vend::Cfg->{MailOrderTo},
};
}
}
elsif ($address = $route->{email}) {
$address = $::Values->{$address} if $address =~ /^\w+$/;
- $::Values->{mv_order_subject} =~ s/%n/%s/;
$subject = $::Values->{mv_order_subject} || 'ORDER %s';
+ $subject =~ s/%n/%s/;
$subject = sprintf "$subject", $::Values->{mv_order_number};
$reply = $route->{reply} || $main->{reply};
$reply = $::Values->{$reply} if $reply =~ /^\w+$/;
if ($route->{supplant}) {
track_order($::Values->{mv_order_number}, $page);
}
+ if ($route->{track}) {
+ Vend::Util::writefile($route->{track}, $page)
+ or ::logError("route tracking error writing $route->{track}: $!");
+ chmod($route->{track_mode}, $route->{track}) if $route->{track_mode};
+ }
+ if ($route->{individual_track}) {
+ my $fn = Vend::Util::catfile(
+ $route->{individual_track},
+ $::Values->{mv_order_number},
+ );
+ Vend::Util::writefile( $fn, $page, )
+ or ::logError("route tracking error writing $fn: $!");
+ chmod($route->{track_mode}, $fn) if $route->{track_mode};
+ }
};
if($@) {
my $err = $@;
# PageBuild.pm - Interpret MiniVend tags
#
-# $Id: PageBuild.pm,v 1.5 1998/08/11 18:13:42 mike Exp $
+# $Id: PageBuild.pm,v 1.6 1999/06/07 08:07:23 mike Exp mike $
#
# Copyright 1996-1998 by Michael J. Heins <mikeh@iac.net>
#
require Exporter;
@ISA = qw(Exporter);
-$VERSION = substr(q$Revision: 1.5 $, 10);
+$VERSION = substr(q$Revision: 1.6 $, 10);
@EXPORT = qw ( fake_html );
# Parse.pm - Parse MiniVend tags
#
-# $Id: Parse.pm,v 1.48 1999/02/15 08:51:10 mike Exp mike $
+# $Id: Parse.pm,v 1.50 1999/06/07 08:07:27 mike Exp mike $
#
# Copyright 1997-1999 by Michael J. Heins <mikeh@iac.net>
#
package Vend::Parse;
-# $Id: Parse.pm,v 1.48 1999/02/15 08:51:10 mike Exp mike $
+# $Id: Parse.pm,v 1.50 1999/06/07 08:07:27 mike Exp mike $
require Vend::Parser;
-$VERSION = sprintf("%d.%02d", q$Revision: 1.48 $ =~ /(\d+)\.(\d+)/);
+$VERSION = sprintf("%d.%02d", q$Revision: 1.50 $ =~ /(\d+)\.(\d+)/);
use Safe;
use Vend::Util;
@ISA = qw(Exporter Vend::Parser);
-$VERSION = substr(q$Revision: 1.48 $, 10);
+$VERSION = substr(q$Revision: 1.50 $, 10);
@EXPORT = ();
@EXPORT_OK = qw(find_matching_end);
package Vend::Parser;
-# $Id: Parser.pm,v 1.15 1998/07/04 21:58:33 mike Exp $
+# $Id: Parser.pm,v 1.16 1999/06/07 08:07:30 mike Exp mike $
=head1 NAME
use HTML::Entities ();
use vars qw($VERSION);
-$VERSION = sprintf("%d.%02d", q$Revision: 1.15 $ =~ /(\d+)\.(\d+)/);
+$VERSION = sprintf("%d.%02d", q$Revision: 1.16 $ =~ /(\d+)\.(\d+)/);
sub new
bs mv_begin_string
co mv_coordinate
cs mv_case
+ cv mv_verbatim_columns
de mv_dict_end
df mv_dict_fold
di mv_dict_limit
if defined $found;
}
+ $c->{mv_verbatim_columns} = 1 if $c->{mv_searchtype} eq 'db';
foreach $param ( grep defined $c->{$_}, @Order) {
$p = $Map{$param};
$options{$p} = $c->{$param};
elsif ( $options{search_type} eq 'glimpse'){
$q = new Vend::Glimpse %options;
}
+ elsif ( $options{search_type} eq 'db'){
+ $q = new Vend::DbSearch %options;
+ }
else {
eval {
no strict 'refs';
sub sql_statement {
my($text, $ref, $table) = @_;
return $text if $text =~ m{([&/\s]|^)st=sql([&/\s]|$)};
+#::logError("sql_statement input=$text");
my @ss;
if ($table) {
eval {
$stmt = SQL::Statement->new($text, $parser);
};
- if($@ and $text =~ s/(\n\s*\w\w\s*=.*)//s) {
- push @ss, $1;
+ if($@ and $text =~ s/^\s*sq\s*=(.*)//m) {
+ my $query = $1;
+ push @ss, $text;
eval {
- $stmt = SQL::Statement->new($text, $parser);
+ $stmt = SQL::Statement->new($query, $parser);
};
}
if($@) {
EOF
}
elsif ($col =~ tr/:/,/) {
+ $col =~ tr/ \t//d;
$wild_card = 1;
$col =~ s/[^\d,.]//g;
$code .= <<EOF;
-my \$addl = join " ", (split m{$g->{index_delim}}, \$line)[$col];
+my \$addl = join " ", (split m{\Q$g->{index_delim}\E}, \$line)[$col];
\$line .= qq{$g->{index_delim}} . \$addl;
EOF
}
# Server.pm: listen for cgi requests as a background server
#
-# $Id: Server.pm,v 1.52 1999/02/15 08:51:26 mike Exp mike $
+# $Id: Server.pm,v 1.55 1999/06/07 08:07:47 mike Exp mike $
#
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
# Copyright 1996-1999 by Michael J. Heins <mikeh@iac.net>
@ISA = qw(Vend::Http::CGI);
use vars qw($VERSION);
-$VERSION = substr(q$Revision: 1.52 $, 10);
+$VERSION = substr(q$Revision: 1.55 $, 10);
use Vend::Util qw(strftime);
use POSIX qw(setsid);
# Session.pm - Minivend Sessions
#
-# $Id: Session.pm,v 1.34 1999/02/15 08:51:29 mike Exp mike $
+# $Id: Session.pm,v 1.36 1999/06/07 08:07:49 mike Exp mike $
#
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
# Copyright 1996-1999 by Michael J. Heins <mikeh@iac.net>
require Exporter;
use vars qw($VERSION);
-$VERSION = substr(q$Revision: 1.34 $, 10);
+$VERSION = substr(q$Revision: 1.36 $, 10);
@ISA = qw(Exporter);
sub param_query {
my($s, $text, $table, $config, @arg) = @_;
-
+
+ if($s->[$CONFIG]{Read_only} and $text !~ /^\s*select\s+/i) {
+ ::logError("Attempt to write read-only database $s->[$CONFIG]{name} with query '$text'");
+ return undef;
+ }
+
$text = $s->substitute_arg($text, @arg) if @arg;
my $db = $s->[$DBI];
sub array_query {
my($s, $text, $table, $config, @arg) = @_;
+
+ if($s->[$CONFIG]{Read_only} and $text !~ /^\s*select\s+/i) {
+ ::logError("Attempt to write read-only database $s->[$CONFIG]{name} with query '$text'");
+ return undef;
+ }
+
$text = $s->substitute_arg($text, @arg) if @arg;
my $db = $s->[$DBI];
my $sth = $db->prepare($text)
sub hash_query {
my($s, $text, $table, $config, @arg) = @_;
-
+
+ if($s->[$CONFIG]{Read_only} and $text !~ /^\s*select\s+/i) {
+ ::logError("Attempt to write read-only database $s->[$CONFIG]{name} with query '$text'");
+ return undef;
+ }
+
$text = $s->substitute_arg($text, @arg) if @arg;
my $key = $s->[$KEY];
sub html_query {
my($s, $text, $table, $config, @arg) = @_;
+
+ if($s->[$CONFIG]{Read_only} and $text !~ /^\s*select\s+/i) {
+ ::logError("Attempt to write read-only database $s->[$CONFIG]{name} with query '$text'");
+ return undef;
+ }
$text = $s->substitute_arg($text, @arg) if @arg;
sub set_query {
my($s, $text, $table, $config, @arg) = @_;
+
+ if($s->[$CONFIG]{Read_only} and $text !~ /^\s*select\s+/i) {
+ ::logError("Attempt to write read-only database $s->[$CONFIG]{name} with query '$text'");
+ return undef;
+ }
+
$config = {} unless ref $config;
$text = $s->substitute_arg($text, @arg) if @arg;
my $rc = $s->[$DBI]->do($text);
sub touch {return ''}
-# Now supported
+# Now supported, including qualification
sub each_record {
- my ($s) = @_;
+ my ($s, $qual) = @_;
+#::logError("qual=$qual");
my ($table,$key,$db,$cols,$config,$each) = @$s;
unless(defined $each) {
- $each = $db->prepare("select * from $table")
+ $each = $db->prepare("select * from $table" . ($qual || '') )
or die $DBI::errstr;
push @$s, $each;
$each->execute();
sub set_field {
my ($s, $key, $column, $value) = @_;
+
+ if($s->[$CONFIG]{Read_only}) {
+ ::logError("Attempt to set $s->[$CONFIG]{name}::${column}::$key in read-only table");
+ return undef;
+ }
$key = $s->[$DBI]->quote($key)
unless exists $s->[$CONFIG]{NUMERIC}{$s->[$KEY]};
$value = $s->[$DBI]->quote($value)
sub delete_record {
my ($s, $key) = @_;
+
+ if($s->[$CONFIG]{Read_only}) {
+ ::logError("Attempt to delete record '$key' from read-only database $s->[$CONFIG]{name}");
+ return undef;
+ }
$key = $s->[$DBI]->quote($key)
unless exists $s->[$CONFIG]{NUMERIC}{$s->[$KEY]};
$s->[$DBI]->do("delete from $s->[$TABLE] where $s->[$KEY] = $key");
# Table/DB_File.pm: access a table stored in a DB file hash
#
-# $Id: DB_File.pm,v 1.14 1999/02/15 08:51:48 mike Exp mike $
+# $Id: DB_File.pm,v 1.17 1999/06/07 08:08:20 mike Exp mike $
#
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
#
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
package Vend::Table::DB_File;
-$VERSION = substr(q$Revision: 1.14 $, 10);
+$VERSION = substr(q$Revision: 1.17 $, 10);
use strict;
use Fcntl;
use DB_File;
sub set_field {
my ($s, $key, $column, $value) = @_;
+ if($s->[$CONFIG]{Read_only}) {
+ ::logError("Attempt to set $s->[$CONFIG]{name}::${column}::$key in read-only table");
+ return undef;
+ }
my @row = $s->row($key);
$row[$s->column_index($column)] = $value;
$s->set_row($key, @row);
sub inc_field {
my ($s, $key, $column, $adder) = @_;
my($value);
+ if($s->[$CONFIG]{Read_only}) {
+ ::logError("Attempt to set $s->[$CONFIG]{name}::${column}::$key in read-only table");
+ return undef;
+ }
my @row = $s->row($key);
$value = $row[$s->column_index($column)] += $adder;
$s->set_row($key, @row);
sub delete_record {
my ($s, $key) = @_;
+ if($s->[$CONFIG]{Read_only}) {
+ ::logError("Attempt to delete row '$key' in read-only table $s->[$CONFIG]{name}");
+ return undef;
+ }
delete $s->[$TIE_HASH]{"k$key"};
1;
# Table/Import.pm: import a table
#
-# $Id: Import.pm,v 1.21 1999/02/15 08:51:52 mike Exp mike $
+# $Id: Import.pm,v 1.24 1999/06/07 08:08:28 mike Exp mike $
#
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
# Copyright 1996-1999 by Mike Heins <mikeh@minivend.com>
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
package Vend::Table::Import;
-$VERSION = substr(q$Revision: 1.21 $, 10);
+$VERSION = substr(q$Revision: 1.24 $, 10);
require Exporter;
@ISA = qw(Exporter);
# Table/InMemory.pm: store a table in memory
#
-# $Id: InMemory.pm,v 1.14 1999/02/15 08:51:53 mike Exp mike $
+# $Id: InMemory.pm,v 1.16 1999/06/07 08:08:31 mike Exp mike $
#
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
# Copyright 1996-1998 by Mike Heins <mikeh@minivend.com>
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
package Vend::Table::InMemory;
-$VERSION = substr(q$Revision: 1.14 $, 10);
+$VERSION = substr(q$Revision: 1.16 $, 10);
use strict;
# 0: column names
# Vend/TextSearch.pm: Search indexes with Perl
#
-# $Id: TextSearch.pm,v 1.22 1999/02/15 08:51:31 mike Exp mike $
+# $Id: TextSearch.pm,v 1.24 1999/06/07 08:07:53 mike Exp mike $
#
# ADAPTED FOR USE WITH MINIVEND from Search::TextSearch
#
@ISA = qw(Vend::Search);
-$VERSION = substr(q$Revision: 1.22 $, 10);
+$VERSION = substr(q$Revision: 1.24 $, 10);
use Search::Dict;
use strict;
#!/usr/bin/perl
#
-# $Id: UserDB.pm,v 1.16 1999/02/15 08:51:34 mike Exp mike $
+# $Id: UserDB.pm,v 1.20 1999/06/07 08:07:56 mike Exp mike $
#
# Copyright 1997-1999 by Michael J. Heins <mikeh@iac.net>
#
package Vend::UserDB;
-$VERSION = substr(q$Revision: 1.16 $, 10);
+$VERSION = substr(q$Revision: 1.20 $, 10);
$DEBUG = 0;
use vars qw! $VERSION $DEBUG @S_FIELDS @B_FIELDS @P_FIELDS %S_to_B %B_to_S!;
# Util.pm - Minivend utility functions
#
-# $Id: Util.pm,v 1.47 1999/02/15 08:51:36 mike Exp mike $
+# $Id: Util.pm,v 1.51 1999/06/07 08:08:04 mike Exp mike $
#
# Copyright 1995 by Andrew M. Wilcox <awilcox@world.std.com>
# Copyright 1996-1999 by Michael J. Heins <mikeh@iac.net>
use Fcntl;
use subs qw(logError logGlobal);
use vars qw($VERSION);
-$VERSION = substr(q$Revision: 1.47 $, 10);
+$VERSION = substr(q$Revision: 1.51 $, 10);
BEGIN {
eval {
-# $Id: ValidCC.pm,v 1.12 1998/12/10 12:52:22 mike Exp $
+# $Id: ValidCC.pm,v 1.13 1999/06/07 08:08:09 mike Exp mike $
#
# ValidCC.pm - validate credit card numbers
#
# Modified by Mike to make more forgiving in the parameters.
package Vend::ValidCC;
-$VERSION = substr(q$Revision: 1.12 $, 10);
+$VERSION = substr(q$Revision: 1.13 $, 10);
require 5.000;
require Exporter;
return $val;
}
-$SIG{PIPE} = sub { die_page("signal"); };
-$SIG{ALRM} = sub { server_not_running(); exit 1; };
+$SIG{PIPE} = sub { die("signal"); };
+$SIG{ALRM} = sub { die("not communicating with server\n"); exit 1; };
alarm $LINK_TIMEOUT;