0.11_02 commit
authorTony Cook <tony@develop-help.com>
Wed, 28 Nov 2001 23:17:38 +0000 (23:17 +0000)
committertony <tony@45cb6cf1-00bc-42d2-bb5a-07f51df49f94>
Wed, 28 Nov 2001 23:17:38 +0000 (23:17 +0000)
19 files changed:
MANIFEST
Makefile
localinst.perl
schema/bse.sql
site/cgi-bin/admin/shopadmin.pl
site/cgi-bin/modules/BSE/DB/Mysql.pm
site/cgi-bin/modules/BSE/Mail/Sendmail.pm
site/cgi-bin/modules/BSE/Shop/Util.pm
site/cgi-bin/modules/Generate/Article.pm
site/cgi-bin/modules/Order.pm
site/cgi-bin/modules/Squirrel/Row.pm
site/cgi-bin/modules/Squirrel/Template.pm
site/cgi-bin/modules/Util.pm
site/cgi-bin/shop.pl
site/docs/bse.pod
site/docs/makedocs
site/htdocs/admin/index.html
site/templates/admin/edit_product.tmpl
site/templates/base.tmpl

index 2e6815b..a5357e8 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -20,26 +20,37 @@ site/cgi-bin/admin/makeIndex.pl
 site/cgi-bin/admin/move.pl
 site/cgi-bin/admin/reorder.pl
 site/cgi-bin/admin/shopadmin.pl
+site/cgi-bin/admin/userlist.pl
+site/cgi-bin/bse.cfg
 site/cgi-bin/modules/AdminUtil.pm
 # the 2 following will probably be renamed at some point
 site/cgi-bin/modules/Apache/Session/DBIreal.pm
 site/cgi-bin/modules/Apache/Session/Store/DBIreal.pm
 site/cgi-bin/modules/Article.pm
+site/cgi-bin/modules/ArticleFile.pm
+site/cgi-bin/modules/ArticleFiles.pm
 site/cgi-bin/modules/Articles.pm
 site/cgi-bin/modules/Constants.pm
 #site/cgi-bin/modules/Constants.tmpl
+site/cgi-bin/modules/BSE/Admin/StepParents.pm
 site/cgi-bin/modules/BSE/Custom.pm
 site/cgi-bin/modules/BSE/CustomBase.pm
-site/cgi-bin/modules/BSE/Admin/StepParents.pm
+site/cgi-bin/modules/BSE/Cfg.pm
 site/cgi-bin/modules/BSE/DB.pm
 site/cgi-bin/modules/BSE/DB/Mysql.pm
 site/cgi-bin/modules/BSE/DB/MSSQL.pm
+site/cgi-bin/modules/BSE/FileEditor.pm
 site/cgi-bin/modules/BSE/Mail.pm
 site/cgi-bin/modules/BSE/Mail/Sendmail.pm
 site/cgi-bin/modules/BSE/Mail/SMTP.pm
+site/cgi-bin/modules/BSE/Message.pm
+site/cgi-bin/modules/BSE/Session.pm
 site/cgi-bin/modules/BSE/Shop/Util.pm
 site/cgi-bin/modules/BSE/Sort.pm
+site/cgi-bin/modules/BSE/Template.pm
+site/cgi-bin/modules/BSE/UserReg.pm
 site/cgi-bin/modules/BSE/Util/SQL.pm
+site/cgi-bin/modules/BSE/Util/Tags.pm
 site/cgi-bin/modules/BSE/Util/Valid.pm
 #site/cgi-bin/modules/DatabaseHandle.pm    obsolete
 site/cgi-bin/modules/Generate.pm
@@ -56,6 +67,8 @@ site/cgi-bin/modules/OtherParent.pm
 site/cgi-bin/modules/OtherParents.pm
 site/cgi-bin/modules/Product.pm
 site/cgi-bin/modules/Products.pm
+site/cgi-bin/modules/SiteUser.pm
+site/cgi-bin/modules/SiteUsers.pm
 site/cgi-bin/modules/Squirrel/GPG.pm
 site/cgi-bin/modules/Squirrel/ImageEditor.pm
 site/cgi-bin/modules/Squirrel/PGP5.pm
@@ -67,6 +80,7 @@ site/cgi-bin/modules/Util.pm
 site/cgi-bin/printable.pl
 site/cgi-bin/search.pl
 site/cgi-bin/shop.pl
+site/cgi-bin/user.pl
 site/data/stopwords.txt
 site/docs/TODO.html
 site/docs/TODO.pod
@@ -80,6 +94,8 @@ site/docs/bse.html
 site/docs/bse.pod
 site/docs/bugs.html
 site/docs/bugs.pod
+site/docs/config.html
+site/docs/config.pod
 site/docs/makedocs
 site/docs/search.html
 site/docs/shop.html
@@ -89,8 +105,10 @@ site/docs/templates.pod
 site/htdocs/a/.htaccess
 site/htdocs/admin/advanced.html
 site/htdocs/admin/index.html
+site/htdocs/admin/help/file.html
 site/htdocs/css/admin.css
 site/htdocs/css/style-main.css
+site/htdocs/images/admin/help.gif
 site/htdocs/images/admin/move_down.gif
 site/htdocs/images/admin/move_up.gif
 site/htdocs/images/store/browse_more.gif
@@ -110,8 +128,6 @@ site/htdocs/js/validate.js
 #  site/htdocs/shop created by the Makefile
 site/templates/1/shop_multicat.tmpl
 site/templates/1/sitemap.tmpl
-site/templates/admin/add_product.tmpl
-site/templates/admin/article_img.tmpl
 site/templates/base.tmpl
 site/templates/cart_base.tmpl
 site/templates/catalog.tmpl
@@ -126,6 +142,8 @@ site/templates/common/embedded_subsect.tmpl
 site/templates/common/news_item.tmpl
 site/templates/common/sidebar.tmpl
 site/templates/common/sidebar_section.tmpl
+site/templates/admin/add_product.tmpl
+site/templates/admin/article_img.tmpl
 site/templates/admin/catalog.tmpl  # embedded in the shopadmin catalog/product display
 site/templates/admin/edit_0.tmpl
 site/templates/admin/edit_1.tmpl
@@ -135,6 +153,7 @@ site/templates/admin/edit_4.tmpl
 site/templates/admin/edit_5.tmpl
 site/templates/admin/edit_catalog.tmpl
 site/templates/admin/edit_product.tmpl
+site/templates/admin/filelist.tmpl
 site/templates/admin/order_detail.tmpl
 site/templates/admin/order_list.tmpl
 site/templates/admin/order_list_filled.tmpl
@@ -163,4 +182,11 @@ site/templates/search_base.tmpl
 site/templates/shop_help.tmpl
 site/templates/shop_sect.tmpl
 site/templates/shopitem.tmpl
+site/templates/user/logon_base.tmpl
+site/templates/user/options_base.tmpl
+site/templates/user/register_base.tmpl
+site/templates/user/userpage_base.tmpl
+site/templates/user/lostpassword_base.tmpl
+site/templates/user/lostemailsent_base.tmpl
+site/templates/user/lostpwdemail_base.tmpl
 site/util/initial.pl
index c4d20b8..a330cc6 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-VERSION=0.11
+VERSION=0.11_02
 DISTNAME=bse-$(VERSION)
 DISTBUILD=$(DISTNAME)
 DISTTAR=../$(DISTNAME).tar
index c54f2ad..0c3aab5 100644 (file)
@@ -29,6 +29,7 @@ system "rm -f $instbase/htdocs/{*.html,a/*.html,shop/*.html,images/*.jpg}"
 
 system "cp -rf $dist/site/cgi-bin $instbase"
   and die "Cannot copy cgi-bin";
+unlink "$instbase/cgi-bin/bse.cfg";
 
 system "cp -rf $dist/site/htdocs $instbase"
   and die "Cannot copy htdocs";
index 0023da0..964b60b 100644 (file)
@@ -189,8 +189,13 @@ create table orders (
   -- order was cancelled
   cancelled integer not null default 0,
 
+  -- user id of the person who made the order
+  -- an empty string if there's no user
+  userId varchar(40) not null,
+
   primary key (id),
-  index order_cchash(ccNumberHash)
+  index order_cchash(ccNumberHash),
+  index order_userId(userId, orderDate)
 );
 
 DROP TABLE IF EXISTS order_item;
@@ -235,4 +240,76 @@ create table other_parents (
   primary key(id),
   unique (parentId, childId),
   index (childId, childDisplayOrder)
+);
+
+-- initially we just do paid for files, later we may add unpaid for files
+-- there's some database support here to support unpaid for files
+-- but it won't be implemented yet
+drop table if exists article_files;
+create table article_files (
+  id integer not null auto_increment,
+  articleId integer not null,
+
+  -- the name of the file as displayed
+  displayName varchar(80) not null default '',
+
+  -- the filename as stored in the repository
+  filename varchar(80) not null default '',
+
+  -- how big it is
+  sizeInBytes integer not null,
+
+  -- a description of the file
+  description varchar(255) not null default '',
+
+  -- content type
+  contentType varchar(80) not null default 'application/octet-stream',
+
+  -- used to control the order the files are displayed in
+  displayOrder integer not null,
+
+  -- if non-zero this item is for sale
+  -- it has no public URL and can only be downloaded via a script
+  forSale integer not null default 0,
+
+  -- we try to make the browser download the file rather than display it
+  download integer not null default 0,
+
+  -- when it was uploaded
+  whenUploaded datetime not null,
+
+  primary key (id)
+);
+
+-- contains web site users
+-- there will be a separate admin users table at some point
+drop table if exists site_users;
+create table site_users (
+  id integer not null auto_increment,
+
+  userId varchar(40) not null,
+  password varchar(40) not null,
+  email varchar(40) not null,
+
+  keepAddress integer not null default 1,
+  whenRegistered datetime not null,
+  lastLogon datetime not null,
+
+  -- used to fill in the checkout form
+  name1 varchar(127),
+  name2 varchar(127),
+  address varchar(127),
+  city varchar(127),
+  state varchar(40),
+  postcode varchar(40),
+  telephone varchar(80),
+  facsimile varchar(80),
+  country varchar(127),
+
+  -- the user wants to receive the site newsletter if any
+  -- this should default to NO
+  wantLetter integer not null default 0,
+
+  primary key (id),
+  unique (userId)
 );
\ No newline at end of file
index 261ed81..51fceea 100755 (executable)
@@ -1,4 +1,6 @@
 #!/usr/bin/perl -w
+# -d:ptkdb
+BEGIN { $ENV{DISPLAY} = '192.168.32.97:0.0'; }
 
 use strict;
 use FindBin;
@@ -15,47 +17,18 @@ use OrderItem;
 use Constants qw($TMPLDIR);
 use Squirrel::Template;
 use Squirrel::ImageEditor;
-use Constants qw(:shop :session $SHOPID $PRODUCTPARENT $SECURLBASE 
+use Constants qw(:shop $SHOPID $PRODUCTPARENT $SECURLBASE 
                  $SHOP_URI $CGI_URI $IMAGES_URI $AUTO_GENERATE);
-use CGI::Cookie;
-require $SESSION_REQUIRE;
 use Images;
 use Articles;
 use BSE::Sort;
 use BSE::Cfg;
+use BSE::Session;
+use BSE::Util::Tags;
 
-my %cookies = fetch CGI::Cookie;
-my $sessionid;
-$sessionid = $cookies{sessionid}->value if exists $cookies{sessionid};
+my $cfg = BSE::Cfg->new();
 my %session;
-
-my $dh = BSE::DB->single;
-eval {
-  tie %session, $SESSION_CLASS, $sessionid,
-    {
-     Handle=>$dh->{dbh},
-     LockHandle=>$dh->{dbh}
-    };
-};
-if ($@ && $@ =~ /Object does not exist/) {
-  # try again
-  undef $sessionid;
-  tie %session, $SESSION_CLASS, $sessionid,
-    {
-     Handle=>$dh->{dbh},
-     LockHandle=>$dh->{dbh}
-    };
-}
-
-unless ($sessionid) {
-  # save the new sessionid
-  print "Set-Cookie: ",CGI::Cookie->new(-name=>'sessionid', -value=>$session{_session_id}),"\n";
-}
-# this shouldn't be necessary, but it stopped working and this fixed it
-# <sigh>
-END {
-  untie %session;
-}
+BSE::Session->tie_it(\%session, $cfg);
 
 param();
 
@@ -115,7 +88,6 @@ if ($imageEditor->action($CGI::Q)) {
   exit;
 }
 
-my $cfg = BSE::Cfg->new();
 use BSE::FileEditor;
 my $file_editor = 
   BSE::FileEditor->new(session=>\%session, cgi=>$CGI::Q, cfg=>$cfg,
@@ -512,6 +484,12 @@ sub product_form {
     $title .= ' / ' if $title;
     unshift(@work, map [ $_->{id}, $title.$_->{title} ], @kids);
   }
+  my @files;
+  if ($product->{id}) {
+    require 'ArticleFiles.pm';
+    @files = ArticleFiles->getBy(articleId=>$product->{id});
+  }
+  my $file_index;
 
   my @templates;
   push(@templates, "shopitem.tmpl")
@@ -597,6 +575,8 @@ HTML
        $acts{$func} or return "** unknown function '$func' $args **";
        display_date($acts{$func}->($args));
      },
+     BSE::Util::Tags->
+     make_iterator(\@files, 'file', 'files', \$file_index),
     );
 
   page($template, \%acts);
@@ -655,7 +635,7 @@ sub order_list_low {
   my %acts;
   %acts =
     (
-     order=> sub { CGI::escapeHTML($orders[$order_index]{$_[0]}) },
+     order=> sub { CGI::escapeHTML($orders_work[$order_index]{$_[0]}) },
      iterate_orders_reset =>
      sub {
        @orders_work = 
@@ -663,8 +643,8 @@ sub order_list_low {
        $order_index = -1;
      },
      iterate_orders => sub { ++$order_index < @orders_work },
-     money => sub { sprintf("%.2f", $orders[$order_index]{$_[0]}/100.0) },
-     date => sub { display_date($orders[$order_index]{$_[0]}) },
+     money => sub { sprintf("%.2f", $orders_work[$order_index]{$_[0]}/100.0) },
+     date => sub { display_date($orders_work[$order_index]{$_[0]}) },
      script => sub { $ENV{SCRIPT_NAME} },
      title => sub { $title },
      ifHaveParam => sub { defined param($_[0]) },
index 193ddae..91e50a6 100644 (file)
@@ -62,9 +62,10 @@ EOS
    Orders => 'select * from orders',
    getOrderByPkey => 'select * from orders where id = ?',
    getOrderItemByOrderId => 'select * from order_item where orderId = ?',
-   addOrder => 'insert orders values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
-   replaceOrder => 'replace orders values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+   addOrder => 'insert orders values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+   replaceOrder => 'replace orders values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
    addOrderItem => 'insert order_item values(null,?,?,?,?,?,?,?)',
+   getOrderByUserId => 'select * from orders where userId = ?',
 
    OtherParents => 'select * from other_parents',
    getOtherParentByChildId => <<EOS,
@@ -80,6 +81,19 @@ EOS
    replaceOtherParent=>'replace other_parents values(?,?,?,?,?,?,?)',
    'OtherParents.anylinks' => 
    'select * from other_parents where childId = ? or parentId = ?',
+
+   addArticleFile =>
+   'insert into article_files values (null,?,?,?,?,?,?,?,?,?,?)',
+   replaceArticleFile =>
+   'replace article_files values (?,?,?,?,?,?,?,?,?,?,?)',
+   deleteArticleFile => 'delete from article_files where id = ?',
+   getArticleFileByArticleId =>
+   'select * from article_files where articleId = ? order by displayOrder desc',
+   
+   getSiteUserByUserId =>
+   'select * from site_users where userId = ?',
+   addSiteUser => 'insert site_users values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+   replaceSiteUser => 'replace site_users values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
   );
 
 sub _single
index dd5e929..b66b57b 100644 (file)
@@ -28,7 +28,7 @@ sub send {
   $args{headers} =~ /^\s/
     and return $self->_error("headers starts with whitespace");
 
-  open MAIL, "| $SHOP_SENDMAIL -t -odi"
+  open MAIL, "| $SHOP_SENDMAIL -t -oi -odq"
     or return $self->_error("Cannot open pipe to sendmail");
   print MAIL <<EOS;
 From: $args{from}
index 0b75c48..e8bf44e 100644 (file)
@@ -3,7 +3,7 @@ use strict;
 use vars qw(@ISA @EXPORT_OK);
 @ISA = qw/Exporter/;
 @EXPORT_OK = qw/shop_cart_tags cart_item_opts nice_options shop_nice_options
-                total shop_total load_order_fields basic_tags/;
+                total shop_total load_order_fields basic_tags need_logon/;
 use Constants qw/:shop/;
 use BSE::Util::SQL qw(now_sqldate);
 use BSE::Custom;
@@ -139,16 +139,16 @@ sub load_order_fields {
       or do { $$error = "Please enter a credit card number"; return 0 };
   }
 
+  my @cart = @{$session->{cart}};
+  @cart or 
+    do { $$error = 'You have no items in your shopping cart'; return 0 };
+
   require 'Orders.pm';
   require 'Order.pm';
   require 'OrderItems.pm';
   require 'OrderItem.pm';
 
   my %order;
-  my @cart = @{$session->{cart}};
-  @cart or 
-    do { $$error = 'You have no items in your shopping cart'; return 0 };
-
   # so we can quickly check for columns
   my @columns = Order->columns;
   my %columns; 
@@ -195,6 +195,15 @@ sub load_order_fields {
   $order->{orderDate} = $today;
   $order->{total} += BSE::Custom->total_extras(\@cart, \@products, 
                                             $session->{custom});
+
+  require 'BSE/Cfg.pm';
+  my $cfg = BSE::Cfg->new;
+  if (need_logon($cfg, \@cart, \@products, $session)) {
+    $$error = "Your cart contains some file-based products.  Please register or logon";
+    return 0;
+  }
+
+
   # blank anything else
   for my $column (@columns) {
     defined $order->{$column} or $order->{$column} = '';
@@ -234,4 +243,22 @@ sub basic_tags {
     );
 }
 
+sub need_logon {
+  my ($cfg, $cart, $cart_prods, $session) = @_;
+
+  my $reg_if_files = $cfg->entryBool('shop', 'register_if_files', 1);
+  if (!$session->{userid} && $reg_if_files) {
+    require 'ArticleFiles.pm';
+    # scan to see if any of the products have files
+    for my $prod (@$cart_prods) {
+      my @files = ArticleFiles->getBy(articleId=>$prod->{id});
+      if (grep $_->{forSale}, @files) {
+       return 1;
+      }
+    }
+  }
+  
+  return 0;
+}
+
 1;
index 6e2cd6a..daf4cf3 100644 (file)
@@ -8,6 +8,8 @@ use vars qw(@ISA);
 use Generate;
 use CGI (); # for escapeHTML()
 use Util qw(generate_button);
+use BSE::Util::Tags;
+use ArticleFiles;
 @ISA = qw/Generate/;
 
 my $excerptSize = 300;
@@ -110,6 +112,8 @@ sub baseActs {
     Images->getBy('articleId', $article->{id});
   my $image_index = -1;
   my $had_image_tags = 0;
+  my @files = sort { $b->{displayOrder} <=> $a->{displayOrder} }
+    ArticleFiles->getBy(articleId=>$article->{id});
 
   # separate these so the closures can see %acts
   my %acts =
@@ -351,6 +355,7 @@ HTML
      },
      ifImage => sub { $_[0] >= 1 && $_[0] <= @images },
      ifImages => sub { @images },
+     BSE::Util::Tags->make_iterator(\@files, 'file', 'files'),
     );
 
   if ($article->{link} =~ /^\w+:/) {
index 1de7411..fe7f208 100644 (file)
@@ -15,7 +15,7 @@ sub columns {
            total wholesaleTotal gst orderDate
            ccNumberHash ccName ccExpiryHash ccType
            filled whenFilled whoFilled paidFor paymentReceipt
-           randomId cancelled/;
+           randomId cancelled userId/;
 }
 
 1;
index 3b745dc..c3ed096 100644 (file)
@@ -55,7 +55,7 @@ sub new {
       my $sth = $dh->stmt("add$class")
        or confess "No add$class member in DatabaseHandle";
       my $ret = $sth->execute(@values[1..$#values]);
-      $ret != 0
+      $ret && $ret != 0
        or confess "Could not add $class(undef, @values[1..$#values]) to database: ",$sth->errstr;
       $self->{$primary[0]} = $dh->insert_id($sth);
     }
index 0aa5242..820205c 100644 (file)
@@ -85,15 +85,20 @@ sub iterate {
 sub cond {
   my ($self, $name, $args, $true, $false, $acts, $orig) = @_;
 
-  if (exists $acts->{"if$name"}) {
-    return $acts->{"if$name"}->($args) ? $true : $false;
-  }
-  elsif (exists $acts->{lcfirst $name}) {
-    return $acts->{lcfirst $name}->($args) ? $true : $false;
-  }
-  else {
-    return $orig;
-  }
+  my $result =
+    eval {
+      if (exists $acts->{"if$name"}) {
+       return $acts->{"if$name"}->($args) ? $true : $false;
+      }
+      elsif (exists $acts->{lcfirst $name}) {
+       return $acts->{lcfirst $name}->($args) ? $true : $false;
+      }
+      else {
+       return $orig;
+      }
+    };
+  $@ && return $orig;
+  return $result;
 }
 
 sub replace_template {
index 16b6e3a..d37acb5 100644 (file)
@@ -143,7 +143,11 @@ sub generate_shop {
 sub generate_extras {
   my ($articles) = @_;
 
-  open EXTRAS, "$TMPLDIR/extras.txt"
+  use BSE::Cfg;
+  my $cfg = BSE::Cfg->new;
+  my $template_dir = $cfg->entry('paths', 'templates') || $TMPLDIR;
+
+  open EXTRAS, "$template_dir/extras.txt"
     or return;
   my @extras;
   while (<EXTRAS>) {
@@ -160,8 +164,9 @@ sub generate_extras {
     my ($in, $out) = @$row;
     my %acts;
     %acts = $gen->baseActs($articles, \%acts);
-    my $templ = Squirrel::Template->new(%TEMPLATE_OPTS);
-    my $content = $templ->show_page($TMPLDIR, $in, \%acts);
+    my $templ = Squirrel::Template->new(%TEMPLATE_OPTS, 
+                                       template_dir=>$template_dir);
+    my $content = $templ->show_page($template_dir, $in, \%acts);
     my $outname = $CONTENTBASE . $out . ".work";
     my $finalname = $CONTENTBASE . $out;
     open OUT, "> $outname"
@@ -174,6 +179,41 @@ sub generate_extras {
     rename $outname, $finalname
       or die "Cannot rename $outname to $finalname: $!";
   }
+
+  # more extras
+  my %entries = $cfg->entries('pregenerate');
+  if (keys %entries) {
+    require 'Generate/Article.pm';
+    my $gen = Generate::Article->new;
+    for my $out (keys %entries) {
+      my ($presets, $input) = split ',', $entries{$out}, 2;
+      my %article = map { $_, '' } Article->columns;
+      $article{displayOrder} = 1;
+      $article{id} = -5;
+      $article{parentid} = -1;
+      for my $field (Article->columns) {
+       if ($cfg->entry("$presets settings", $field)) {
+         $article{$field} = $cfg->entryVar("$presets settings", $field);
+       }
+      }
+      my %acts;
+      %acts = $gen->baseActs($articles, \%acts, \%article);
+      my $templ = Squirrel::Template->new(%TEMPLATE_OPTS, 
+                                         template_dir=>$template_dir);
+      my $content = $templ->show_page($template_dir, $input, \%acts);
+      my $outname = $template_dir .'/'.$out.'.work';
+      my $finalname = $template_dir . '/'. $out;
+      open OUT, "> $outname"
+       or die "Cannot open $outname for write: $!";
+      print OUT $content
+       or die "Cannot write content to $outname: $!";
+      close OUT
+       or die "Cannot close $outname: $!";
+      unlink $finalname;
+      rename $outname, $finalname
+       or die "Cannot rename $outname to $finalname: $!";
+    }
+  }
 }
 
 sub generate_all {
index 546bccf..886a5ca 100755 (executable)
@@ -5,16 +5,17 @@ use lib "$FindBin::Bin/modules";
 use CGI ':standard';
 use Products;
 use Product;
-use Constants qw(:shop :session $TMPLDIR %EXTRA_TAGS $CGI_URI);
+use Constants qw(:shop $TMPLDIR %EXTRA_TAGS $CGI_URI $URLBASE);
 use Squirrel::Template;
 use Squirrel::ImageEditor;
 use CGI::Cookie;
 use BSE::Custom;
 use BSE::Mail;
 use BSE::Shop::Util qw/shop_cart_tags cart_item_opts nice_options total 
-                       basic_tags load_order_fields/;
-
-require $SESSION_REQUIRE;
+                       basic_tags load_order_fields need_logon/;
+use BSE::Session;
+use BSE::Cfg;
+use Util qw/refresh_to/;
 
 my $subject = $SHOP_MAIL_SUBJECT;
 
@@ -39,42 +40,9 @@ my $from = $SHOP_FROM;
 my $toName = $SHOP_TO_NAME;
 my $toEmail= $SHOP_TO_EMAIL;
 
-# Lifetime (in hours _OR_ minutes) of the shopping cart cookie.
-# Value can be in minutes (append an 'm') or hours (append an 'h').
-my $lifetime = '+3h';
-my $path = $CGI_URI . '/';
-
-# maximum age of shopping cart cookie
-my $max_cookie_age = "+3h";
-
-my %cookies = fetch CGI::Cookie;
-my $sessionid;
-$sessionid = $cookies{sessionid}->value if exists $cookies{sessionid};
+my $cfg = BSE::Cfg->new();
 my %session;
-
-my $dh = BSE::DB->single;
-eval {
-  tie %session, $SESSION_CLASS, $sessionid,
-    {
-     Handle=>$dh->{dbh},
-     LockHandle=>$dh->{dbh}
-    };
-};
-if ($@ && $@ =~ /Object does not exist/) {
-  # try again
-  undef $sessionid;
-  tie %session, $SESSION_CLASS, $sessionid,
-    {
-     Handle=>$dh->{dbh},
-     LockHandle=>$dh->{dbh}
-    };
-}
-unless ($sessionid) {
-  # save the new sessionid
-  print "Set-Cookie: ",
-    CGI::Cookie->new(-name=>'sessionid', -value=>$session{_session_id}, 
-                    -expires=>$lifetime),"\n";
-}
+BSE::Session->tie_it(\%session, $cfg);
 
 # this shouldn't be necessary, but it stopped working elsewhere and this
 # fixed it
@@ -259,6 +227,19 @@ sub checkout {
   @cart or return show_cart();
 
   my @cart_prods = map { Products->getByPkey($_->{productId}) } @cart;
+
+  if (need_logon($cfg, \@cart, \@cart_prods, \%session)) {
+    refresh_to("$URLBASE/cgi-bin/user.pl?message=".
+              CGI::escape("Some of the products in your cart include downloadable files.  Please logon or register before checkout."));
+    return;
+  }
+
+  my $user;
+  if ($session{userid}) {
+    require 'SiteUsers.pm';
+    $user = SiteUsers->getBy(userId=>$session{userid});
+  }
+
   $session{custom} ||= {};
   my %custom_state = %{$session{custom}};
 
@@ -298,7 +279,8 @@ sub checkout {
      },
      count => sub { scalar @cart },
      message => sub { $message },
-     old => sub { $olddata ? param($_[0]) : '' },
+     old => sub { CGI::escapeHTML($olddata ? param($_[0]) : 
+                   $user && defined $user->{$_[0]} ? $user->{$_[0]} : '') },
      iterate_options_reset => sub { $option_index = -1 },
      iterate_options => sub { ++$option_index < @options },
      option => sub { CGI::escapeHTML($options[$option_index]{$_[0]}) },
@@ -431,6 +413,12 @@ sub prePurchase {
   }
   $order{orderDate} = $today;
 
+  if (need_logon($cfg, \@cart, \@products, \%session)) {
+    refresh_to("$URLBASE/cgi-bin/user.pl?message=".
+              CGI::escape("Some of the products in your cart include downloadable files.  Please logon or register before checkout."));
+    return;
+  }
+
   $order{total} += BSE::Custom->total_extras(\@cart, \@products, 
                                             $session{custom});
   ++$session{changed};
@@ -607,6 +595,13 @@ sub purchase {
     $order{wholesale} += $item->{wholesalePrice} * $item->{units};
     $order{gst} += $item->{gst} * $item->{units};
   }
+
+  if (need_logon($cfg, \@cart, \@products, \%session)) {
+    refresh_to("$URLBASE/cgi-bin/user.pl?message=".
+              CGI::escape("Some of the products in your cart include downloadable files.  Please logon or register before checkout."));
+    return;
+  }
+
   $order{orderDate} = $today;
   $order{total} += BSE::Custom->total_extras(\@cart, \@products, 
                                             $session{custom});
@@ -620,6 +615,13 @@ sub purchase {
   $order{filled} = 0;
   $order{paidFor} = 0;
 
+  if ($session{userid}) {
+    $order{userId} = $session{userid};
+  }
+  else {
+    $order{userId} = '';
+  }
+
   # this should be hard to guess
   $order{randomId} = md5_hex(time().rand().{}.$$);
 
index d27e3ed..ef63f14 100644 (file)
@@ -10,6 +10,58 @@ Maybe I'll add some other bits here.
 
 =head1 CHANGES
 
+=head2 0.11_02
+
+Another test release:
+
+=over
+
+=item *
+
+actually tested the form filling with the user's defaults
+
+=item *
+
+modify localinst.perl to remove the default bse.cfg
+
+=item *
+
+have the checkout function return if the user needs to register (shop.pl)
+
+=item *
+
+check in a few more places if the user needs to register (shop.pl)
+
+=item *
+
+changed names of fields in SiteUsers to match the checkout form
+
+=item *
+
+added telephone and facsimile fields to the user options
+
+=back
+
+=head2 0.11_01
+
+Test release:
+
+=over
+
+=item *
+
+supports files attached to products for sale
+
+=item *
+
+user registration
+
+=item *
+
+we now have a config file
+
+=back
+
 =head2 0.11
 
 Looks like all known problems are fixed.  Time to do a semi-major
index f5803af..222ef21 100644 (file)
@@ -18,6 +18,7 @@ my @targets =
    'add.html',
    'shopadmin.html',
    'TODO.html',
+   'config.html',
   );
 
 my @exts = qw(.pod .pm .pl);
index a453a53..1a51de8 100644 (file)
@@ -82,6 +82,16 @@ pages</a></td>
     <td colspan="2"><a 
 href="/cgi-bin/admin/makeIndex.pl">Regenerate search index</a></td>
  
+</tr>
+  <tr> 
+    <td width="15">&nbsp;</td>
+    <td>&nbsp;</td>
+</tr>
+  <tr> 
+    <td colspan="2"><a 
+href="/cgi-bin/admin/userlist.pl">Download member list</a></td>
 </tr>
   <tr> 
     <td width="15">&nbsp;</td>
index b2047a6..2db0fb0 100644 (file)
               <input type="file" name="thumbnail"> <:ifProduct thumbImage:><img src="/images/<:product thumbImage:>"><input type=checkbox name="remove_thumb"> Remove<:or:><:eif:>
             </td>
           </tr>
+          <tr>
+            <th nowrap align="left"><a name="files"></a>Files:</th>
+            <td nowrap bgcolor="#FFFFFF">
+<:if Files:>
+              <table>
+               <tr>
+                 <th>Filename</th>
+                 <th>Size</th>
+                 <th>Type</th>
+                 <th>Download?</th>
+               </tr>
+<:iterator begin files:>
+                <tr>
+                 <td><:file displayName:></td>
+                 <td align="center"><:file sizeInBytes:></td>
+                 <td><:file contentType:></td>
+                 <td><:ifFile download:>Yes<:or:>No<:eif:></td>
+               </tr>
+<:iterator end files:>
+             </table>
+<:or Files:>
+              No files are attached to this article.
+<:eif Files:>
+             <a href="<:script:>?filelist=1&id=<:product id:>"><b>Manage Files</b></a>
+            </td>
+          </tr>
         </table>
       </td>
     </tr>
index 2ae4a6d..ebe2df1 100644 (file)
             </table>
             <br>
             <:eif Level2:><:iterator separator level1:><:iterator end level1:> 
+<script language="JavaScript">
+<!--
+// extract the userid cookie, if any, and either present a logon form,
+// or a logoff button
+var cookies = document.cookie;
+var start = cookies.indexOf("userid=");
+var userid = '';
+if (start != -1) {
+  start += 7;
+  var end = cookies.indexOf(';', start);
+  if (end == -1) end = cookies.length;
+  userid = cookies.substring(start, end);
+}
+if (userid != '') {
+  document.write('<form action="/cgi-bin/user.pl" method="post">');
+  document.write('<table><tr><td colspan="2" align="center"><input type="submit" name="logoff" value="Logoff" /></td></tr></table></form>');
+}
+else {
+  document.write('<form action="/cgi-bin/user.pl" method="post">');
+  document.write('<table><tr><th><font face="Verdana, Arial, Helvetica, sans-serif" size="-2">User:</font></th><td><font face="Verdana, Arial, Helvetica, sans-serif" size="-2"><input type="text" name="userid" size="10" /></font></td></tr>');
+  document.write('<tr><th><font face="Verdana, Arial, Helvetica, sans-serif" size="-2">Password:</font></th><td><font face="Verdana, Arial, Helvetica, sans-serif" size="-2"><input type="password" name="password" size="10" /></font></td></tr>');
+  document.write('<tr><td align="left"><font face="Verdana, Arial, Helvetica, sans-serif" size="-2"><input type="submit" name="logon" value="Logon" /></font></td><td align="right"><font face="Verdana, Arial, Helvetica, sans-serif" size="-2"><input type="submit" name="show_register" value="Register" /></font></td></tr></table></form>');
+}
+//-->
+</script>
             <:embed 5:> </td>
         </tr>
       </table>