[interchange-cvs] interchange - markj modified 2 files

interchange-cvs at icdevgroup.org interchange-cvs at icdevgroup.org
Mon Apr 6 12:23:22 UTC 2009


User:      markj
Date:      2009-04-06 12:23:22 GMT
Modified:  lib/Vend Config.pm Dispatch.pm
Log:
New directive SourceCookie - support for persistent affiliate tracking.
Initial framework developed by Peter Ajamian <peter at pajamian.dhs.org>.

Setting SourceCookie defines the relevant attributes of a cookie to be
maintained in conjunction with the usual session-only parameter
$Session->{source}. Its usage eliminates the duration of the user's session as
the limiting factor for applying credit to a referal.

SourceCookie and SourcePriority would be expected to typically work in tandem,
and thus the same cookie defined in both contexts. However, there is no such
requirement to do so. Defining SourceCookie by itself merely makes the cookie
available any time the core source routines set or manipulate
$Session->{source}. That cookie may, or may not, be leveraged as an element in
SourcePriority, which itself may look to a cookie not maintained by
SourceCookie.

SourceCookie supports the following attributes:

* name (required)
* expire (any format supported for [set-cookie])
* domain
* path
* secure
* autoreset

autoreset is a boolean that, when true, will cause each request from the client
to reset the cookie in the response, effectively refreshing the expiration time
relative to the current time. Uses, for example, might include a desire to
ensure that the source cookie last "forever" (autoreset + sufficiently long
expire period) or for more obscure uses such as "Affiliate should last [value
of expire] from the last request".

Attributes may be positional in order of (name expire domain path secure), but
it is recommended that they be expressed as key=value pairs for clarity.

Example using both SourcePriority and SourceCookie together in catalog.cfg:

SourcePriority mv_pc mv_source cookie-MV_SOURCE
SourceCookie name=MV_SOURCE expire="180 days"

Revision  Changes    Path
2.245                interchange/lib/Vend/Config.pm


rev 2.245, prev_rev 2.244
Index: Config.pm
===================================================================
RCS file: /var/cvs/interchange/lib/Vend/Config.pm,v
retrieving revision 2.244
retrieving revision 2.245
diff -u -r2.244 -r2.245
--- Config.pm	27 Mar 2009 11:09:48 -0000	2.244
+++ Config.pm	6 Apr 2009 12:23:22 -0000	2.245
@@ -1,6 +1,6 @@
 # Vend::Config - Configure Interchange
 #
-# $Id: Config.pm,v 2.244 2009-03-27 11:09:48 markj Exp $
+# $Id: Config.pm,v 2.245 2009-04-06 12:23:22 markj Exp $
 #
 # Copyright (C) 2002-2009 Interchange Development Group
 # Copyright (C) 1996-2002 Red Hat, Inc.
@@ -54,7 +54,7 @@
 use Vend::Data;
 use Vend::Cron;
 
-$VERSION = substr(q$Revision: 2.244 $, 10);
+$VERSION = substr(q$Revision: 2.245 $, 10);
 
 my %CDname;
 my %CPname;
@@ -716,7 +716,8 @@
 	['BounceReferrals',  'yesno',            'no'],
 	['OrderCleanup',     'routine_array',    ''],
 	['SessionCookieSecure', 'yesno',         'no'],
-        ['SourcePriority', 'array_complete', 'mv_pc mv_source'],
+	['SourcePriority', 'array_complete', 'mv_pc mv_source'],
+	['SourceCookie', sub { &parse_ordered_attributes(@_, [qw(name expire domain path secure)]) }, '' ],
 
 	];
 
@@ -4779,6 +4780,32 @@
 	return $c;
 }
 
+# Parse ordered or named attributes just like in a usertag.  Needs to have the routine specified as follows:
+# ['Foo', sub { &parse_ordered_attributes(@_, [qw(foo bar baz)]) }, 'foo bar baz'],
+# If called directly in the normal fashion then you cannot specify the attribute order, but you can
+# still use it for parsing named attributes.  The results are stored as a hashref (think $opt)
+sub parse_ordered_attributes {
+	my ($var, $value, $order) = @_;
+
+	return {} if $value !~ /\S/;
+
+	my @settings = Text::ParseWords::shellwords($value);
+	my %opt;
+	if ($settings[0] =~ /=/) {
+		%opt = map { (split /=/, $_, 2)[0, 1] } @settings;
+	}
+
+	elsif (ref $order eq 'ARRAY') {
+		@opt{@$order} = @settings;
+	}
+
+	else {
+		config_error("$var only accepts named attributes.");
+	}
+
+	return \%opt;
+}
+
 # Designed to parse catalog subroutines and all vars
 sub save_variable {
 	my ($var, $value) = @_;



1.111                interchange/lib/Vend/Dispatch.pm


rev 1.111, prev_rev 1.110
Index: Dispatch.pm
===================================================================
RCS file: /var/cvs/interchange/lib/Vend/Dispatch.pm,v
retrieving revision 1.110
retrieving revision 1.111
diff -u -r1.110 -r1.111
--- Dispatch.pm	23 Mar 2009 13:34:19 -0000	1.110
+++ Dispatch.pm	6 Apr 2009 12:23:22 -0000	1.111
@@ -1,6 +1,6 @@
 # Vend::Dispatch - Handle Interchange page requests
 #
-# $Id: Dispatch.pm,v 1.110 2009-03-23 13:34:19 mheins Exp $
+# $Id: Dispatch.pm,v 1.111 2009-04-06 12:23:22 markj Exp $
 #
 # Copyright (C) 2002-2009 Interchange Development Group
 # Copyright (C) 2002 Mike Heins <mike at perusion.net>
@@ -26,7 +26,7 @@
 package Vend::Dispatch;
 
 use vars qw($VERSION);
-$VERSION = substr(q$Revision: 1.110 $, 10);
+$VERSION = substr(q$Revision: 1.111 $, 10);
 
 use POSIX qw(strftime);
 use Vend::Util;
@@ -1220,8 +1220,6 @@
 	}
 }
 
-my %source_keys_hide;
-
 sub dispatch {
 	my($http) = @_;
 	$H = $http;
@@ -1443,50 +1441,114 @@
 
 	$Vend::Session->{'arg'} = $Vend::Argument = ($CGI::values{mv_arg} || undef);
 
-	my $new_source;
+	my ($new_source, $already_expired);
       SOURCEPRIORITY: {
-	  if ($CGI::values{mv_pc} and $CGI::values{mv_pc} eq 'RESET') {
-	      $Vend::Session->{source} = '';
-	      last SOURCEPRIORITY;
-	  }
-
-	  foreach (@{$Vend::Cfg->{SourcePriority}}) {
-	      if ($_ eq 'mv_pc') {
-		  if ($CGI::values{mv_pc} and $CGI::values{mv_pc} =~ /\D/) {
-		      $new_source = $Vend::Session->{source} = $CGI::values{mv_pc};
-		      last SOURCEPRIORITY;
-		  }
-	      }
-
-	      elsif ($_ =~ /^cookie-(.+)/) {
-		  my $cookie = Vend::Util::read_cookie($1);
-		  if (length $cookie) {
-		      $Vend::Session->{source} = $cookie;
-		      last SOURCEPRIORITY;
-		  }
-	      }
-
-	      elsif ($_ eq 'session') {
-		  if ($sessionid) {
-		      last SOURCEPRIORITY;
-		  }
-	      }
-
-	      elsif (/^session-(.+)/) {
-		  if (length $Vend::Session->{$1}) {
-		      last SOURCEPRIORITY;
-		  }
-	      }
-
-	      else {
-		  if (length $CGI::values{$_}) {
-		      $new_source = $Vend::Session->{source} = $CGI::values{$_};
-		      last SOURCEPRIORITY;
-		  }
-	      }
-	  }
-      } #SOURCEPRIORITY
-
+     if ($CGI::values{mv_pc} and $CGI::values{mv_pc} eq 'RESET') {
+         $Vend::Session->{source} = '';
+ 
+         # Expire cookie, if applicable.
+         if ( length ($Vend::Cfg->{SourceCookie}{name}) ) {
+             my $sc = $Vend::Cfg->{SourceCookie};
+             Vend::Util::set_cookie(
+                $sc->{name},
+                '',
+                1,
+                @{$sc}{qw(domain path secure)}
+            );
+            $already_expired = 1;
+         }
+ 
+         last SOURCEPRIORITY;
+     }
+
+#::logDebug('$Session->{source} before SourcePriority loop: %s', $Vend::Session->{source});
+     foreach (@{$Vend::Cfg->{SourcePriority}}) {
+#::logDebug("Looking at $_");
+         if ($_ eq 'mv_pc') {
+#::logDebug('$CGI::values{mv_pc} is %s', $CGI::values{mv_pc});
+            if ($CGI::values{mv_pc} and $CGI::values{mv_pc} =~ /\D/) {
+                $new_source = $Vend::Session->{source} = $CGI::values{mv_pc};
+                last SOURCEPRIORITY;
+            }
+         }
+
+         elsif (/^cookie-(.+)/) {
+             my $cookie_source = Vend::Util::read_cookie($1);
+#::logDebug("Cookie $1 is $cookie_source");
+             if (length $cookie_source) {
+                 $Vend::Session->{source} = $cookie_source;
+                 last SOURCEPRIORITY;
+            }
+         }
+
+         elsif ($_ eq 'session') {
+#::logDebug('$sessionid is %s', $sessionid);
+            if ($sessionid) {
+                last SOURCEPRIORITY;
+            }
+         }
+
+         elsif (/^session-(.+)/) {
+#::logDebug('$Session->{%s} is %s', $1, $Vend::Session->{$1});
+            if (length $Vend::Session->{$1}) {
+                last SOURCEPRIORITY;
+            }
+         }
+
+         else {
+#::logDebug('$CGI::values{%s} is %s', $_, $CGI::values{$_});
+            if (length $CGI::values{$_}) {
+                $new_source = $Vend::Session->{source} = $CGI::values{$_};
+                last SOURCEPRIORITY;
+            }
+         }
+     }
+    } #SOURCEPRIORITY
+#::logDebug('$Session->{source} after SourcePriority loop: %s', $Vend::Session->{source});
+
+    # Set a cookie if applicable.
+    if (
+        # Obviously must be true
+        length ($Vend::Cfg->{SourceCookie}{name})
+        and
+
+        # and, we didn't already clear it in SOURCEPRIORITY
+        ! $already_expired
+        and
+
+            # any time we have a new source, we want to
+            # reset--even if it's unchanged from the last
+            # value to reset the expiration
+            length ($new_source)
+            ||
+
+            # or, our cookie is different from $Session->{source},
+            # whatever the reason
+            Vend::Util::read_cookie($Vend::Cfg->{SourceCookie}{name})
+                ne
+            $Vend::Session->{source}
+            ||
+
+            # or
+            (
+                # there's something in source worth preserving,
+                length ($Vend::Session->{source})
+                &&
+
+                # and we want the expiration reset with every access,
+                $Vend::Cfg->{SourceCookie}{autoreset}
+            )
+    ) {
+
+        my $sc = $Vend::Cfg->{SourceCookie};
+#::logDebug('Resetting SourceCookie %s to %s', $sc->{name}, $Vend::Session->{source});
+        Vend::Util::set_cookie(
+            $sc->{name},
+            $Vend::Session->{source},
+            @{$sc}{qw(expire domain path secure)}
+        );
+    }
+ 
 	if ($new_source and $CGI::request_method eq 'GET' and $Vend::Cfg->{BounceReferrals}) {
 		my $path = $CGI::path_info;
 		$path =~ s:^/::;







More information about the interchange-cvs mailing list