Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Simple cookie script please

Posted on 1999-07-01
17
Medium Priority
?
538 Views
Last Modified: 2008-03-03
I want to put a coupon on the internet that can only be seen  once to stop people printing it out again and again. Sure they can delete the cookie, but most people won't know how or have anti cookie software.

The step by step procedure is

1) Viewer sees a page on our site.
2) They click on a graphic link to see a discount coupon
3) Viewer is prompted to enter their first name
4) A dialog box appears and viewer is prompted "are you sure? Y/N (in case they type it wrong)
5) A pop-up window with the coupon appears displaying the viewer's name, plus the date and time displayed.
6) Viewer can print off coupon if they choose
6) If the viewer returns again and tries to see the coupon again, they are directed to a different page.

Thank you.

The last time I asked a question, Michel kindly helped me out. You can see his code in operation at http://www.moneysaver.com.au
0
Comment
Question by:mindwave
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
  • 5
17 Comments
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 1288559
Hmm the page at

http://bne003i.webcentral.com.au/catalogue/kma/_cmdlogin?name=guest&viewmode=HEADER&branchlevel=0&itemsperpage=20&maxpages=1000

was not reachable...

If it is worth someone's time to print off the coupon, the will bypass the script.

Did you mean that most people do not know how and not many people have anti cookie software???

How many of the steps do you need help with?

If I am not the one that answers this question, will the person who does, kindly reuse any cookie script already on mindwave's site?

Michel
0
 
LVL 6

Accepted Solution

by:
tecbuilder earned 3200 total points
ID: 1288560
Without knowing any more than what you stated in your question this is what I came up with that worked for me.  One other option is to frames to remember what the user's name and current date is rather than passing this information through the URL.  If you would prefer the frames solution, let me know and I would be happy to supply the necessary changes.  Note that if you would use frames, one frame is set to 1 pixel in width making it virtually undectable while the other fram takes up the remaining width of the window.

tecbuilder

-----------------------------------------------------------------------------------------------------------------

[mainpage.html]
<HTML>
<BODY>
<!-- Step 1:  User is already at your site -->

<!-- Step 2 -->
<A HREF="coupon1.html">Get Coupon 1</A>
</BODY>
</HTML>

[coupon1.html]
<html>
<head>
<script language="javascript">
<!-- begin script

// getCookie() and setCookie() is based on the public domain cookie
// code produced by Bill Dortch, with some minor modifications to Get_Cookie().
// FixCookieDate() came from an unknown source.

function FixCookieDate (date) {
  var base = new Date(0);
  var skew = base.getTime(); // dawn of (Unix) time - should be 0
  if (skew > 0)  // Except on the Mac - ahead of its time
    date.setTime (date.getTime() - skew);
}

function getCookie(byname) {
  byname=byname+"=";
  nlen = byname.length;
  fromN = document.cookie.indexOf(byname)+0;
  if((fromN) != -1)
    {fromN +=nlen
    toN=document.cookie.indexOf(";",fromN)+0;
    if(toN == -1) {toN=document.cookie.length;}
    return unescape(document.cookie.substring(fromN,toN));
  }
  return null;
}

function SetCookie (name,value,expires,path,domain,secure) {
  document.cookie = name + "=" + escape (value) +
    ((expires) ? "; expires=" + expires.toGMTString() : "") +
    ((path) ? "; path=" + path : "") +
    ((domain) ? "; domain=" + domain : "") +
    ((secure) ? "; secure" : "");
}

<!-- Step 4 -->
// Get user's name.
function ValidateName(name) {
  var strConfirm = "You have entered your name as '" + name + "'. Click Ok if this is correct."
  if (confirm(strConfirm)) {
    var expdate = new Date();
    var currentdate = new Date();
      
    // Correct for Mac date bug - call only once for given Date object!
    FixCookieDate(expdate);
    FixCookieDate(currentdate);

    expdate.setTime(expdate.getTime() + (30 * 24 * 60 * 60 * 1000)); // 30 days from now
    SetCookie("coupon1", currentdate, expdate);
    // change height and width to appropriate size of window needed.
   var strVariables = "?Hi " + name + "<BR>Today Is: " + currentdate.toLocaleString();
    cpnWindow = window.open("printcoupon.html"+strVariables, "MyWindow", "resizable,location,height=200,width=300");
  }
}

<!-- Check to see if user has already received a coupon within a certain period of time. -->
function canGetCoupon() {
  today = new Date();
  var CouponDate = new Date(getCookie("coupon1"));
  if (CouponDate != null && CouponDate <= today) { window.location.href="test.html" }      
}
// end script -->
</SCRIPT>
</head>
<body onLoad="canGetCoupon()">
<!-- If the user has not received a coupon within a certain period of -->
<!-- time the following code will execute. -->

<!-- Step 3 -->
<FORM NAME="Coupon">
Please enter your first name:
<INPUT TYPE="Text" NAME="UserName" SIZE="30" MAXLENGTH="30">
<P>
<INPUT TYPE="Button" VALUE="Submit" onClick="ValidateName(this.form.UserName.value);return false">
</FORM>
</body>
</html>

[printcoupon.html]
<HTML>
<BODY>
<!-- Steps 5 and 6 -->
<SCRIPT LANGUAGE="JavaScript">
<!--
var mySearch=self.location.search;
mySearch=mySearch.substring(1,mySearch.length);
alert(mySearch);
document.write("<FONT SIZE='2'>"+mySearch+"</FONT>");
//-->
</SCRIPT>
<BR>
<IMG SRC="coupon1.jpg" HEIGHT=100 WIDTH=275 ALT="">
<P>
<CENTER><A HREF="javascript:self.print()">Print this coupon</A></CENTER>
</BODY>
</HTML>

0
 
LVL 6

Expert Comment

by:tecbuilder
ID: 1288561
I just realized that I omitted a couple lines of my debugging code.

the line in [coupon1.html]

cpnWindow = window.open("printcoupon.html"+strVariables, "MyWindow", "resizable,location,height=200,width=300");

should be

cpnWindow = window.open("printcoupon.html"+strVariables, "MyWindow", "height=200,width=300");

The line in [printcoupon.html]

alert(mySearch)

should be deleted.

Another thing I thought of where frames would be a benefit is that you would not have to have the scripts in each coupon page that a person can get a coupon from.  The hidden frame would contain these scripts which would/could greatly reduce future re-coding and problems.

tecbuilder
0
The top UI technologies you need to be aware of

An important part of the job as a front-end developer is to stay up to date and in contact with new tools, trends and workflows. That’s why you cannot miss this upcoming webinar to explore the latest trends in UI technologies!

 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 1288562
Techbuilder: What is that "1 pixel frame is virtually undetectable???"

This IS undetectable unless the user looks at view source or view info:

<FRAMESET ROWS="100%,*">
<FRAME SRC="blabla.html">
<FRAME SRC="javascript:' '">
</FRAMESET>

Michel
0
 
LVL 6

Expert Comment

by:tecbuilder
ID: 1288563
The reason for the 1 pixel was because once upon at long time ago I was told that either Netscape or IE (don't remember which or which version) had a problem with setting one of the frames to 0 width.  So I have always set one frame to 1 pixel and the other to *.

tecbuilder
0
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 1288564
Well - the 0,* will make NS show a 3-4 pixel wide strip
I have used the 100%,*  for 3 years without complaint

Michel
0
 

Author Comment

by:mindwave
ID: 1288565
I think I've set this up ok, however, when I check how this works on Navigator 3 gold I get an error message

Javascript error: file:/coupon1.html, line 54:

illegal URL method 'printcoupon.html?Hi Jonathan
Today Is:',

Also, if the visitor returns the next day, will they be able to see the coupon the next day?

How to I change the variables for

A) how long the coupon can be seen
b) how long the cookies lasts on the users computer.

I know this is probably obvious, but I'm not sure how to modify the script to change these date variable.

Thank you for you help to date.

We're almost there!
0
 

Author Comment

by:mindwave
ID: 1288566
I've put up a page with the script.

The problem I have is that it bypassed the page where you enter your name and goes straight to the page that says you are denied access.

I think this is due to the dates not being specified correctly in the cookie scripts.

See the problem by trying to view the Strathfield $10 coupon at
http://www.moneysaver.com.au/newsletters/start

It looks like it will work well once I can get this part ok and hopefully it will work in Nav 3 as well.
0
 

Author Comment

by:mindwave
ID: 1288567
Adjusted points to 750
0
 
LVL 6

Expert Comment

by:tecbuilder
ID: 1288568
Hi mindwave, I found the errors that you found with NS3.x and I fixed them.  The code below should replace the pages that I originally posted.  I was going to just post the updated code, but felt it would be a lot easier to just replace all.  Please let me know if you have any problems.

There a couple of things to note and answers to your questions:
1)The 'DeleteCookie' function and the reference to it in coupon1.html can be deleted once you get everything up and running.  However, during testing leave it in so that it will reset the date.  Otherwise, it will treat you like a regular user.

2) The expiration date can be changed in coupon1.html.  I have a comment where this occurs that currently sets the expiration date for 30 days from the current date.  To find where it is that you make the change scroll down until you find the comment " // Set the expiration date for 30 days from the current date."  The line beneath this comment contains an equation with the value of 30 (days).  Change the 30 to some other number.

3) I am not sure what you mean by setting the variable for how long the coupon can be seen.

4) If the visitor tries to come back to the coupon a second later they will not have access to the coupon.  They get one shot at getting the coupon for the specified period of time (expiration date) and that's it.

5) The test.html that was in the original coupon1.html file can be changed to any filename.  I have renamed it in the code to be sorry.html.  If you should want to use some other filename, do a find on sorry.html and replace it with your name.


[printcoupon.html]
<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
<!--
function GetCookie(byname) {
  byname=byname+"=";
  nlen = byname.length;
  fromN = document.cookie.indexOf(byname)+0;
  if((fromN) != -1)
    {fromN +=nlen
    toN=document.cookie.indexOf(";",fromN)+0;
    if(toN == -1) {toN=document.cookie.length;}
    return unescape(document.cookie.substring(fromN,toN));
  }
  return null;
}

//-->
</SCRIPT>
</HEAD>
<BODY>
<!-- Steps 5 and 6 -->
<SCRIPT LANGUAGE="JavaScript">
<!--
var username = GetCookie("UserName");
var currentdate = new Date();
document.write("<FONT SIZE='2'>Hi "+username+"<BR>"+currentdate.toLocaleString()+"</FONT>");
//-->
</SCRIPT>
<BR>
<IMG SRC="coupon1.jpg" HEIGHT=100 WIDTH=275 ALT="">
<P>
<CENTER><A HREF="javascript:self.print()">Print this coupon</A></CENTER>
</BODY>
</HTML>

[coupon1.html]
<html>
<head>
<script language="javascript">
<!-- begin script

// getCookie() and setCookie() is based on the public domain cookie
// code produced by Bill Dortch, with some minor modifications to GetCookie().
// FixCookieDate() came from an unknown source.

function FixCookieDate (date) {
  var base = new Date(0);
  var skew = base.getTime(); // dawn of (Unix) time - should be 0
  if (skew > 0)  // Except on the Mac - ahead of its time
    date.setTime (date.getTime() - skew);
}

function GetCookie(byname) {
  byname=byname+"=";
  nlen = byname.length;
  fromN = document.cookie.indexOf(byname)+0;
  if((fromN) != -1)
    {fromN +=nlen
    toN=document.cookie.indexOf(";",fromN)+0;
    if(toN == -1) {toN=document.cookie.length;}
    return unescape(document.cookie.substring(fromN,toN));
  }
  return null;
}

function SetCookie (name,value,expires,path,domain,secure) {
  document.cookie = name + "=" + value +
    ((expires) ? "; expires=" + expires.toGMTString() : "") +
    ((path) ? "; path=" + path : "") +
    ((domain) ? "; domain=" + domain : "") +
    ((secure) ? "; secure" : "");
}
// This function is only needed while you are getting things setup.
function DeleteCookie(name,path,domain) {
  if (GetCookie(name)) document.cookie = name + "=" +
     ( (path) ? ";path=" + path : "") +
     ( (domain) ? ";domain=" + domain : "") +
     ";expires=Thu, 01-Jan-70 00:00:01 GMT";
}
<!-- Step 4 -->
// Get user's name.
function ValidateName(name) {
  var strConfirm = "You have entered your name as '" + name + "'. Click Ok if this is correct."
  if (confirm(strConfirm)) {
    var expdate = new Date();

    // Correct for Mac date bug - call only once for given Date object!
    FixCookieDate(expdate);

    // Set the expiration date for 30 days from the current date.
    expdate.setTime(expdate.getTime() + (30 * 24 * 60 * 60 * 1000)); // 30 days from now

    SetCookie("coupon1", expdate, expdate);
    // Temporarily store the person's name.  This cookie will automatically be
    // deleted when person closes browser window.
    SetCookie("UserName", name);
    // change height and width to appropriate size of window needed.
   cpnWindow = window.open("printcoupon.html", "MyWindow", "height=200,width=300");
  }
}

<!-- Check to see if user has already received a coupon within a certain period of time. -->
function canGetCoupon() {
// Delete or comment the following line once you have your site running.
//      DeleteCookie("coupon1");

  var CouponDate = GetCookie("coupon1");
  today = new Date();
  if (CouponDate != null && (CouponDate > today)) { window.location.href="sorry.html" }
}
// end script -->
</SCRIPT>
</head>
<body onLoad="canGetCoupon()">
<!-- If the user has not received a coupon within a certain period of -->
<!-- time the following code will execute. -->

<!-- Step 3 -->
<FORM NAME="Coupon">
Please enter your first name:
<INPUT TYPE="Text" NAME="UserName" SIZE="30" MAXLENGTH="30">
<P>
<INPUT TYPE="Button" VALUE="Submit"
onClick="ValidateName(this.form.UserName.value);return false">
</FORM>
</body>
</html>

[sorry.html]
<HTML>
<BODY>
Sorry but you can not get another copy of this coupon at this time.
<P>
<A HREF="main.html">Go back to main page</A>
</BODY>
</HTML>

tecbuilder
0
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 1288569
1. self.print() is only supported by NS4+ and IE5+

2. there might be no username printed in netscape 4.06+ since printing spawns a new browser process whith a temporary domain for the page so the cookie origin will be different than when it was set.
You might get a
"Hi undefined"
instead of
"Hi mindwave"

Michel
0
 

Author Comment

by:mindwave
ID: 1288570
The code is up at http://www.moneysaver.com.au/newsletters/0799 and you'll see it working when you click on a Strathfield or Godfreys coupon.

If as Michel says self.print() is only supported by NS4+ and IE5+ what do I have to do to include browser controls on the smaller popup windows so the user can print off the coupon from Explorer 4?

When I'm ready to stop people seeing the coupon twice, I just delete the one line
// DeleteCookie("coupon1");

Is that right?

Also, I only have Navigator 4.08 and it seems to work ok. It doesn't seem to work on Navigator 3. It jumps straight onto the sorry.htm without letting me see the coupon and I haven't deleted the one line mentioned above!

Any ideas?


0
 
LVL 6

Expert Comment

by:tecbuilder
ID: 1288571
For browsers that cannot do self.print() and browsers that have disabled JavaScript you will need to insert a comment to tell those people to use File | Print from the menu to print the coupon.  You will have to provide access to the menubar.  To open a window with the menubar use the following:

cpnWindow = window.open("printcoupon1.htm", "MyWindow", "menubar=yes,height=460,width=620");

How to display to the user the method they can use to print can be done in 3 ways:
1) Add the comment just below (or anywhere else you like) the "I agree to these terms & wish to print this coupon" link.  This is the safest and simplest fix.  The reason is that no matter what, you have covered all situations.
2) Include code that determines which browser and version the person is using and supply the "I agree to these terms & wish to print this coupon" link or the comment.  You will also need to include a piece of code for browser's that have disabled JavaScript.  This would look like:

Include this script in the header.
<SCRIPT language="JavaScript">
<!--
// *** BROWSER SNIFFER ***
// Code snipped from Netscape's browser sniffer code.
// Note: On IE5, these return 4, so use is_ie5up to detect IE5.
var is_major = parseInt(navigator.appVersion);
var is_minor = parseFloat(navigator.appVersion);

// Note: Opera and WebTV spoof Navigator.  We do strict client detection.
// If you want to allow spoofing, take out the tests for opera and webtv.
var is_nav  = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
      && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
      && (agt.indexOf('webtv')==-1));
var is_ie   = (agt.indexOf("msie") != -1);
var is_nav4up = (is_nav && (is_major >= 4));
var is_ie4up  = (is_ie  && (is_major >= 4));
//-->
</SCRIPT>

Include the code below in the body where you want it to display.
<SCRIPT language="JavaScript">
<!--
if (is_nav4up || is_ie4up) { document.write("A HREF='javascript:self.print')I agree to these terms & wish to print this coupon</A>") }
else { document.write("Select File | Print from the menu to print this coupon.") }
//-->
</SCRIPT>
<NOSCRIPT>
Select File | Print from the menu to print this coupon.
</NOSCRIPT>

The text contained within the NOSCRIPT tag will not show up unless JavaScript.
3) Create a different page for those browser's that can use self.print() and those browsers that cannot user self.print().  Then using the browser sniffer code above you would call the necessary page. For example:

if (is_nav4up || is_ie4up) {
  couponpage="printcoupon1.html";
  cpnWindow = window.open("printcoupon1.htm", "MyWindow", "height=460,width=620");
}
else {
  couponpage="FP_printcoupon1.html"
cpnWindow = window.open("fileprint_printcoupon1.htm", "MyWindow", "menubar=yes,height=460,width=620");
}


Concerning the DeleteCoupon function:
As long as the DeleteCoupon("coupon1") statement is active (exists or not commented) in the function canGetCoupon() you will allow be able to print the coupon over and over and over.  When I test I will uncomment the statement so that I can see how things are supposed to and then comment the statement to have the process work properly.


Concerning NS3.x problems:
NS3.x has some problems with dates that are not seen in NS4.x.  The fix was some modifications to a couple of functions.  NS4.x can evaluate dates as dates.  NS3.x for some reason doesn't.  So I had to save the dates as a value equal to the number of milliseconds since Jan 1, 1970 00:00:00.  Once I did that everything worked.  I tested the functions below using NS3.04 and NS4.61.

Replace your current functions with these.

function ValidateName(name) {
  var strConfirm = "You have entered your name as '" + name + "'. Click Ok if this is correct."
  if (confirm(strConfirm)) {
    var expdate = new Date();

    // Correct for Mac date bug - call only once for given Date object!
    FixCookieDate(expdate);

    // Set the expiration date for 30 days from the current date.
    expdate.setTime(expdate.getTime() + (30 * 24 * 60 * 60 * 1000)); // 30 days from now

// Convert to number of milliseconds since January 1, 1970  00:00:00      
    valexpdate=expdate.getTime();
    SetCookie("coupon1", valexpdate, expdate);

    // Temporarily store the person's name.  This cookie will automatically be
    // deleted when person closes browser window.
    SetCookie("UserName", name);
    // change height and width to appropriate size of window needed.
   cpnWindow = window.open("printcoupon.html", "MyWindow", "height=200,width=300");
  }
}

<!-- Check to see if user has already received a coupon within a certain period of time. -->
function canGetCoupon() {
// Delete or comment the following line once you have your site running.
  DeleteCookie("coupon1");
  var valCouponDate=GetCookie("coupon1");
  if (valCouponDate == null) { var valCouponDate=0 }

// Get current date
  var today=new Date();
// Convert to number of milliseconds since January 1, 1970  00:00:00      
  valToday=today.getTime();
      
  if (valCouponDate > valToday) { window.location="sorry.html" }
}

tec
0
 

Author Comment

by:mindwave
ID: 1288572
Dear Tecbuilder,

I couldn't get the browser sniffing code to switch whether or not people see the self-print script or not, but I've put the rest of the code together and it seems to work well.

Thank you for your wonderful help.

If you want to have a final look, the page with coupons and your script is at
http://www.moneysaver.com.au/newsletters/0799/

(Also, thank you Michel as well.)

Best wishes


Jonathan (MindWave)
 
0
 
LVL 6

Expert Comment

by:tecbuilder
ID: 1288573
You are very welcome.  I went back through the original browser sniffing code and found tucked inbetween a couple of comments an additional line of code.

var agt=navigator.userAgent.toLowerCase();

Add this line just before the following lines:
var is_major = parseInt(navigator.appVersion);
var is_minor = parseFloat(navigator.appVersion);

That should take care of the problem you were running into.

I did visit your site and everything looks very nice.

tec
0
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 1288574
You also might want to use this mod I suggested:

Replace

var is_ie   = (agt.indexOf("msie") != -1);

with

// Michel Plungjan/abk mods - 990618
  iePos = agt.indexOf("msie ");
  this.ie   = (iePos != -1);
  if (this.ie) {
    this.minor = parseFloat(agt.substring(iePos+5,agt.indexOf(';',iePos+5)));
    this.major = parseInt(this.minor);
  } else {
    this.major = parseInt(navigator.appVersion);
    this.minor = parseFloat(navigator.appVersion);
  }

Michel
0
 
LVL 6

Expert Comment

by:tecbuilder
ID: 1288575
Michel, what is the code replacement doing that isn't already being done?  Does it more accurately determine the type of IE browser?  I'm not understanding why to replace 1 line of code with 8.  Also, I believe 'this.minor' and 'this.major' would need to be renamed to 'is_minor' and 'is_major' respectively, to work with the existing script.

tec
0

Featured Post

Build and deliver software with DevOps

A digital transformation requires faster time to market, shorter software development lifecycles, and the ability to adapt rapidly to changing customer demands. DevOps provides the solution.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article demonstrates how to create a simple responsive confirmation dialog with Ok and Cancel buttons using HTML, CSS, jQuery and Promises
This article discusses how to implement server side field validation and display customized error messages to the client.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

704 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question