site/cgi-bin/admin/add.pl
site/cgi-bin/admin/admin.pl
site/cgi-bin/admin/adminusers.pl
+site/cgi-bin/affiliate.pl
site/cgi-bin/admin/changepw.pl
site/cgi-bin/admin/datadump.pl
site/cgi-bin/admin/generate.pl
#site/cgi-bin/modules/BSE/TB/Subscription.pm
#site/cgi-bin/modules/BSE/TB/Subscriptions.pm
site/cgi-bin/modules/BSE/Template.pm
-#site/cgi-bin/modules/BSE/UI/AdminDispatch.pm
-#site/cgi-bin/modules/BSE/UI/Dispatch.pm
-#site/cgi-bin/modules/BSE/UI/SubAdmin.pm
+site/cgi-bin/modules/BSE/UI/AdminDispatch.pm
+site/cgi-bin/modules/BSE/UI/Affiliate.pm
+site/cgi-bin/modules/BSE/UI/Dispatch.pm
+site/cgi-bin/modules/BSE/UI/SubAdmin.pm
site/cgi-bin/modules/BSE/UserReg.pm
site/cgi-bin/modules/BSE/Util/DynSort.pm
site/cgi-bin/modules/BSE/Util/Iterate.pm
site/cgi-bin/shop.pl
site/cgi-bin/user.pl
site/data/stopwords.txt
+site/docs/BSE::UI::Affiliate.html
site/docs/Generate.html
site/docs/Generate::Article.html
site/docs/Generate::Catalog.html
site/docs/add.html
site/docs/access.html
site/docs/access.pod
+site/docs/affiliate.html
site/docs/bse.html
site/docs/bse.pod
site/docs/bugs.html
site/templates/admin/users/edit_orders.tmpl
site/templates/admin/users/list.tmpl
site/templates/admin/xbase.tmpl
+site/templates/affiliate.tmpl
site/templates/base.tmpl
site/templates/cart_base.tmpl
site/templates/catalog.tmpl
site/templates/user/unsuball_base.tmpl
site/templates/user/unsubone_base.tmpl
site/templates/user/userpage_base.tmpl
+site/templates/xbase.tmpl
site/util/gen.pl
site/util/initial.pl
site/util/mysql.str
-VERSION=0.14_24
+VERSION=0.14_25
DISTNAME=bse-$(VERSION)
DISTBUILD=$(DISTNAME)
DISTTAR=../$(DISTNAME).tar
flags varchar(80) not null default '',
+ customText1 text,
+ customText2 text,
+ customText3 text,
+ customStr1 varchar(255),
+ customStr2 varchar(255),
+ customStr3 varchar(255),
+
primary key (id),
unique (userId)
);
BEGIN { $ENV{DISPLAY} = '192.168.32.15:0.0' }
use strict;
use FindBin;
-use lib "$FindBin::Bin/../modules";
+use lib "$FindBin::Bin/modules";
use BSE::DB;
use BSE::Request;
use BSE::Template;
my $req = BSE::Request->new;
my $result = BSE::UI::Affiliate->dispatch($req);
BSE::Template->output_result($req, $result);
+
+__END__
+=head1 NAME
+
+affiliate.pl - set the affiliate code for new orders or display a user info page
+
+=head1 SYNOPSIS
+
+# display a user's information or affiliate page
+http://your.site.com/cgi-bin/affiliate.pl?id=I<number>
+
+# set the stored affiliate code and refresh to the top of the site
+http://your.site.com/cgi-bin/affiliate.pl?a_set=1&id=I<code>
+
+=head1 DESCRIPTION
+
+This is implemented by L<BSE::UI::Affiliate>, please see that for
+complete documentation.
+
+=head1 AUTHOR
+
+Tony Cook <tony@develop-help.com>
+
+=cut
select ar.* from article ar, other_parents op
where op.childId = ar.id and op.parentId = ?
EOS
+# originally "... and ? between op.release and op.expire"
+# but since the first argument was a string, mysql treated the comparisons
+# as string comparisons
'Articles.visibleStepKids' => <<EOS,
select ar.* from article ar, other_parents op
where op.childId = ar.id
- and op.parentId = ? and ? between op.release and op.expire
+ and op.parentId = ?
+ and date_format(?, '%Y%m%d') between date_format(op.release, '%Y%m%d') and date_format(op.expire, '%Y%m%d')
EOS
'Articles.ids'=>'select id from article',
'select * from site_users where userId = ?',
getSiteUserByPkey =>
'select * from site_users where id = ?',
- addSiteUser => 'insert site_users values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
- replaceSiteUser => 'replace site_users values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+ addSiteUser => 'insert site_users values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+ replaceSiteUser => 'replace site_users values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
'SiteUsers.removeSubscriptions'=>
'delete from subscribed_users where userId = ?',
'SiteUsers.removeSub'=>
sub can_remove {
my ($self, $req, $article, $articles, $rmsg) = @_;
- require OrderItems;
- my @items = OrderItems->getBy(productId=>$article->{id});
+ require BSE::TB::OrderItems;
+ my @items = BSE::TB::OrderItems->getBy(productId=>$article->{id});
if (@items) {
$$rmsg = "There are orders for this product. It cannot be deleted.";
return;
print STDERR "Sent cookie: $cookie\n" if $debug;
}
$saved = $session;
+
+ if ($cfg->entry('debug', 'dump_session')) {
+ require Data::Dumper;
+ print STDERR Data::Dumper->Dump([ $session ], [ 'session' ]);
+ }
}
sub change_cookie {
@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';
+ require BSE::TB::Orders;
+ require BSE::TB::OrderItems;
my %order;
# so we can quickly check for columns
- my @columns = Order->columns;
+ my @columns = BSE::TB::Order->columns;
my %columns;
@columns{@columns} = @columns;
if ($user) {
for my $prod (@$cart_prods) {
my $sub = $prod->subscription_required;
- unless ($user->is_subscribed($sub)) {
+ if ($sub && !$user->subscribed_to($sub)) {
return ("you must be subscribed to $sub->{title} to purchase one of these products", "shop/subrequired");
}
$sub = $prod->subscription;
- if ($sub->renew_only) {
+ if ($sub && $sub->renew_only) {
unless ($user->is_subscribed_grace) {
return ("you must be subscribed to $sub->{title} to use this renew only product", "sub/renewsubonly");
}
}
- if ($sub->new_only) {
+ if ($sub && $sub->new_only) {
if ($user->is_subscribed_grace) {
return ("you must not be subscribed to $sub->{title} already to use this new subscription only product", "sub/newsubonly");
}
package BSE::UI::Affiliate;
use strict;
-
use base qw(BSE::UI::Dispatch);
+use BSE::Util::Tags qw(tag_hash);
+use DevHelp::HTML;
my %actions =
(
- setaff => 1,
+ set => 1,
+ set2 => 1,
show => 1,
none => 1,
);
sub actions { \%actions }
-sub default_action { 'none' }
+sub default_action { 'show' }
+
+=head1 NAME
+
+BSE::UI::Affiliate - set the affiliate code for new orders or display a user info page
+
+=head1 SYNOPSIS
+
+# display a user's information or affiliate page
+
+http://your.site.com/cgi-bin/affiliate.pl?id=I<number>
+
+# set the stored affiliate code and refresh to the top of the site
+
+http://your.site.com/cgi-bin/affiliate.pl?a_set=1&id=I<code>
+
+# set the stored affiliate code and refresh to I<url>
+
+http://your.site.com/cgi-bin/affiliate.pl?a_set=1&id=I<code>&r=I<url>
+
+=head1 DESCRIPTION
+
+This is the implementation of L<affiliate.pl>.
+
+=head1 TARGETS
+
+=over
+
+=item a_set
+
+This is called to set the affiliate code.
-sub req_setaff {
+Requires that an C<id> parameter be supplied with the affiliate code
+which is stored in the user session. This is then stored in the order
+record if the user creates an order before the cookie expires. This
+id can be any string, it need not be a user on the current site.
+
+Optionally, you can supply a C<r> parameter which will be refreshed to
+after the affiliate code is set. If this is not supplied there will
+be a refresh to either C<default_refresh> in C<[affiliate]> in
+C<bse.cfg> or to the top of the site.
+
+If your site url and site secureurl are different then there will be
+an intermediate refresh to C<a_set2> to set the affiliate code on the
+other side of the site. C<a_set2> will then refresh to your supplied
+C<r> parameter or its default.
+
+You can also configure which referer header values are permitted in
+bse.cfg. See L<config/[affiliate]> for more information.
+
+=cut
+
+sub req_set {
my ($class, $req) = @_;
my $cgi = $req->cgi;
- my $cgi = $req->cfg;
+ my $cfg = $req->cfg;
my $id = $cgi->param('id');
defined($id) && $id =~ /^\w+$/
for my $entry (@allowed) {
$entry = lc $entry;
- if ($length($entry) < $domain &&
+ if (length($entry) <= length($domain) &&
$entry eq substr($domain, -length($entry))) {
++$found;
last;
}
}
$found
- or return $class->req_none($req, "$domain not in the permitted list of referers");
+ or return $class->req_none($req, "$referer not in the permitted list of referers");
}
else {
$require_referer
}
my $url = $cgi->param('r');
- $url ||= $cgi->entry('affiliate', 'default_refresh');
- $url ||= $cgi->entryVar('site', 'url');
+ $url ||= $cfg->entry('affiliate', 'default_refresh');
+ $url ||= $cfg->entryVar('site', 'url');
$req->session->{affiliate_code} = $id;
+ # set it on the other side too, if needed
+ my $baseurl = $cfg->entryVar('site', 'url');
+ my $securl = $cfg->entryVar('site', 'secureurl');
+
+ if ($baseurl eq $securl) {
+ return BSE::Template->get_refresh($url, $cfg);
+ }
+ else {
+ # which host are we on?
+ # first get info about the 2 possible hosts
+ my ($baseprot, $basehost, $baseport) =
+ $baseurl =~ m!^(\w+)://([\w.-]+)(?::(\d+))?!;
+ $baseport ||= $baseprot eq 'http' ? 80 : 443;
+
+ # get info about the current host
+ my $port = $ENV{SERVER_PORT} || 80;
+ my $ishttps = exists $ENV{HTTPS} || exists $ENV{SSL_CIPHER};
+ my $protocol = $ishttps ? 'https' : 'http';
+
+ my $onbase = 1;
+ if (lc $ENV{SERVER_NAME} ne lc $basehost
+ || lc $protocol ne $baseprot
+ || $baseport != $port) {
+ print STDERR "not on base host ('$ENV{SERVER_NAME}' cmp '$basehost' '$protocol cmp '$baseprot' $baseport cmp $port\n";
+ $onbase = 0;
+ }
+
+ my $setter = $onbase ? $securl : $baseurl;
+ $setter .= "$ENV{SCRIPT_NAME}?a_set2=1&id=".escape_uri($id);
+ $setter .= "&r=".escape_uri($url);
+ return BSE::Template->get_refresh($setter, $cfg);
+ }
+}
+
+=item a_set2
+
+Sets the affiliate code for the "other" side of the site.
+
+This should only be linked to by the C<a_set> target.
+
+This does no referer checks.
+
+=cut
+
+# yes, this completely removes any point of the referer checks, but
+# since referer checks aren't a security issue anyway, it doesn't
+# matter
+
+sub req_set2 {
+ my ($class, $req) = @_;
+
+ my $cgi = $req->cgi;
+ my $cfg = $req->cfg;
+ my $id = $cgi->param('id');
+
+ defined($id) && $id =~ /^\w+$/
+ or return $class->req_none($req, "Missing or invalid id");
+
+ $req->session->{affiliate_code} = $id;
+
+ my $url = $cgi->param('r');
+ $url ||= $cfg->entry('affiliate', 'default_refresh');
+ $url ||= $cfg->entryVar('site', 'url');
+
return BSE::Template->get_refresh($url, $cfg);
}
-# display the affiliate page for a given user
-# this doesn't set the affiliate code (should it?)
+=item a_show
+
+Display the affiliate page based on a user id number.
+
+This is the default target, so you do not need to supply a target
+parameter.
+
+The page is displayed based on the C<affiliate.tmpl> template.
+
+The basic user side tags are available, as well as the C<siteuser> tag
+which gives access to the site user's record.
+
+Be careful about which information you display.
+
+=cut
+
sub req_show {
my ($class, $req) = @_;
defined $id
or return $class->req_none($req, "No identifier supplied");
require SiteUsers;
- require BSE::TB::Subscriptions;
- my $user = SiteUsers->getBy(userId => $id);
+ my $user = SiteUsers->getByPkey($id);
$user
or return $class->req_none($req, "Unknown user");
- my $subid = $cfg->entry('affiliate', 'subscription_required');
- if ($subid) {
- my $sub = BSE::TB::Subscriptions->getByPkey($subid)
- || BSE::TB::Subscriptions->getBy(text_id => $subid)
- or return $class->req_none($req, "Configuration error: Unknown subscription id");
+# require BSE::TB::Subscriptions;
+# my $subid = $cfg->entry('affiliate', 'subscription_required');
+# if ($subid) {
+# my $sub = BSE::TB::Subscriptions->getByPkey($subid)
+# || BSE::TB::Subscriptions->getBy(text_id => $subid)
+# or return $class->req_none($req, "Configuration error: Unknown subscription id");
+# }
+
+ my %acts;
+ %acts =
+ (
+ BSE::Util::Tags->basic(undef, $req->cgi, $req->cfg),
+ siteuser => [ \&tag_hash, $user ],
+ );
+
+ return $req->dyn_response('affiliate', \%acts);
+}
-
- }
+sub req_none {
+ my ($class, $req, $msg) = @_;
+
+ print STDERR "Something went wrong: $msg\n" if $msg;
+
+ # just refresh to the home page
+ my $url = $req->cfg->entry('site', 'url');
+ return BSE::Template->get_refresh($url, $req->cfg);
}
+=back
+
+=head1 AUTHOR
+
+Tony Cook <tony@develop-help.com>
+
+=cut
+
+
1;
my $user = $self->_get_user($session, $cgi, $cfg, 'userpage')
or return;
- require 'Orders.pm';
+ require BSE::TB::Orders;
my @orders = sort { $b->{orderDate} cmp $a->{orderDate}
|| $b->{id} <=> $a->{id} }
- Orders->getBy(userId=>$user->{userId});
+ BSE::TB::Orders->getBy(userId=>$user->{userId});
$message ||= $cgi->param('message') || '';
my $must_be_paid = $cfg->entryBool('downloads', 'must_be_paid', 0);
BSE::Util::Tags->
make_dependent_iterator(\$order_index,
sub {
- require 'OrderItems.pm';
- @items = OrderItems->
+ require BSE::TB::OrderItems;
+ @items = BSE::TB::OrderItems->
getBy(orderId=>$orders[$_[0]]{id});
},
'item', 'items', \$item_index),
my $orderid = $cgi->param('order')
or return _refresh_userpage($cfg, $msgs->('noorderid', "No order id supplied"));
- require 'Orders.pm';
- my $order = Orders->getByPkey($orderid)
+ require BSE::TB::Orders;
+ my $order = BSE::TB::Orders->getByPkey($orderid)
or return _refresh_userpage($cfg, $msgs->('nosuchorder',
"No such orderd $orderid", $orderid));
unless (length $order->{userId}
}
my $itemid = $cgi->param('item')
or return _refresh_userpage($cfg, $msgs->('noitemid', "No item id supplied"));
- require 'OrderItems.pm';
+ require BSE::TB::OrderItems;
my ($item) = grep $_->{id} == $itemid,
- OrderItems->getBy(orderId=>$order->{id})
+ BSE::TB::OrderItems->getBy(orderId=>$order->{id})
or return _refresh_userpage($cfg, $msgs->(notinorder=>"Not part of that order"));
require 'ArticleFiles.pm';
my @files = ArticleFiles->getBy(articleId=>$item->{productId})
return BSE::TB::Subscriptions->getByPkey($id);
}
+sub subscription {
+ my ($self) = @_;
+
+ my $id = $self->{subscription_id};
+ return if $id == -1;
+
+ require BSE::TB::Subscriptions;
+ return BSE::TB::Subscriptions->getByPkey($id);
+}
+
1;
prompt otherPrompt profession otherProfession previousLogon
billFirstName billLastName billStreet billSuburb billState
billPostCode billCountry instructions billTelephone billFacsimile
- billEmail adminNotes disabled flags/;
+ billEmail adminNotes disabled flags
+ customText1 customText2 customText3
+ customStr1 customStr2 customStr3/;
}
sub removeSubscriptions {
makedocs.html
gen.html
standard.html
+BSE::UI::Affiliate.html
+affiliate.html
\ No newline at end of file
=head1 CHANGES
+=head2 0.14_25
+
+=over
+
+=item *
+
+a few modules were still using Orders/OrderItems instead of
+BSE::TB::...
+
+=item *
+
+work around a discrepancy in the way mysql handles dates, step child
+records marked to be released on a given date should now be released
+on that date rather than the next day
+
+=item *
+
+added affiliate.pl, which can display an affiliate page or set the
+saved affiliate code.
+
+=item *
+
+extra fields have been added to the site users table to allow for
+custom data on the affiliate page.
+
+=item *
+
+a new debug flag dump_session has been added. if this is true then a
+data dump of the session hash is performed after it is retrieved from
+the database.
+
+=item *
+
+some of the order processing code checked incorrectly for
+subscriptions (which don't exist yet anyway).
+
+=back
+
=head2 0.14_24
This release includes some structural changes to article editing,
Reports cookies received from the browser and sent to the browser to
STDERR (hence to the error log on Apache.)
+=item dump_session
+
+If nonzero the session hash is dumped to STDERR after it is retrived
+from the database.
+
=back
=head2 [uri]
[help style user]
icon=/images/help.gif
+=head2 [affiliate]
+
+=over
+
+=item allowed_referer
+
+A semi-colon (;) separated list of referer domains that are allowed to
+link to the C<a_set> target of L<affiliate.pl>.
+
+If the user's browser supplies a referer header then it will be
+checked against this list.
+
+=item require_referer
+
+If this is set then the C<a_set> target of L<affiliate.pl> will
+require that the user's browser supply a Referer header.
+
+=item default_refresh
+
+If no C<r> parameter is supplied to the C<a_set> target of
+L<affiliate.pl> then this is used as the default refresh.
+
+Default: the site base url.
+
+=back
+
=head1 AUTHOR
Tony Cook <tony@develop-help.com>
'upgrade_mysql.html',
'makedocs.html',
'standard.html',
+ 'affiliate.html',
+ 'BSE::UI::Affiliate.html',
);
my @exts = qw(.pod .pm .pl);
--- /dev/null
+<:wrap xbase.tmpl title=>"Affiliate page":>
+<p>This is a placeholder affiliate page for user <:siteuser userId:>.</p>
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
+<html><head><title><:cfg site name:> - <:param title:></title>
+<link rel="stylesheet" href="/css/style-main.css" />
+</head>
+<body>
+<:wrap here:>
+</body></html>
#paths.local_templates=/home/tony/dev/bse/base/altadmin/
site.secureadmin=0
+
+debug.dump_session=0