[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 413
  • Last Modified:

passing form data interferes with reading existing cookie

I am experiencing problems passing search form data using the code obtained from http://www.dynamicdrive.com/dynamicindex16/formremember2.htm.
For example, please follow the instructions below to witness the problem
1) Access url http://www.painetworks.com/cgi-bin/searchlocal.cgi?find=kid&method=and
2) Click on the green magnifying glass to the right of any two images to add them to a light-table. Note: cookies must be enabled in your browser
3) Click on the "My Light-table" link in the dark brown header bar at the top to view your light-table.
4) Change the URL by replacing searchlocal.cgi with searchlocalFORMRETAIN.cgi . Access this new URL. This new URL passes to a cgi script which creates the results page searchresultsFORMRETAIN.txt (see enclosed), which contains the passing form code obtained from dynamicdrive.com
5) Again, click on the "My Light-table" linki n the dark brown header bar at the top to again view your light-table.
6) Notice your light-table is no longer visible. The light-table cookie is corrupted . The image IDs in the cookie are separated by the numerals 20 and 20 appears at the end of the cookie, making the cookie unsearchable.

Somehow, in my opinion, the  javascript (formretain2.js see code below)is interferring with the light-table cookie.

Any ideas?
function getCookie(Name){ 
var re=new RegExp(Name+"=[^;]+", "i"); //construct RE to search for target name/value pair
if (document.cookie.match(re)) //if cookie found
return document.cookie.match(re)[0].split("=")[1] //return its value
return ""
}
 
function setCookie(name, value, days){
var expireDate = new Date()
//set "expstring" to either future or past date, to set or delete cookie, respectively
var expstring=expireDate.setDate(expireDate.getDate()+parseInt(days))
document.cookie = name+"="+value+"; expires="+expireDate.toGMTString()+"; path=/";
}
 
function rememberForm(formid){ //Main remember form values object
this.formref=document.getElementById(formid)? document.getElementById(formid) : document.forms[formid]
this.cookiename=formid
this.persistdays=180 //days to persist form values
this.fields=new Array()
this.cookiestr=""
var forminstance=this
rememberForm.dotask(this.formref, function(){forminstance.savevalues()}, "submit") //save form values onsubmit
rememberForm.dotask(window, function(){forminstance.recallvalues()}, "load") //populate form with saved values onload (body)
}
 
rememberForm.prototype.getfield=function(attr){ //get form field based on its ID or name attribute
var fieldref=document.getElementById(attr)? document.getElementById(attr) : this.formref[attr]
return fieldref
}
 
rememberForm.prototype.persistfields=function(){ //get form fields to persist values for
for (var i=0; i<arguments.length; i++){
this.fields[i]=this.getfield(arguments[i])
this.fields[i].fname=arguments[i] //store name or id of field in custom property
}
}
 
rememberForm.prototype.savevalues=function(){ //get form values and store in cookie
for (var i=0; i<this.fields.length; i++){
if (this.fields[i].type=="text")
this.cookiestr+=this.fields[i].fname+":"+escape(this.fields[i].value)+"#"
}
if (typeof this.togglebox!="undefined"){ //if "remember values checkbox" is defined
this.persistdays=(this.togglebox.checked)? this.persistdays : -1 //decide whether to save form values
this.cookiestr=(this.togglebox.checked)? this.cookiestr+"toggleboxid:on;" : this.cookiestr
}
else //if checkbox isn't defined, just remove final "#" from cookie string
this.cookiestr=this.cookiestr.substr(0, this.cookiestr.length-1)+";"
setCookie(this.cookiename, this.cookiestr, this.persistdays)
}
 
rememberForm.prototype.recallvalues=function(){ //populate form with saved values
var cookievalue=getCookie(this.cookiename)
if (cookievalue!=""){ //parse cookie, where cookie looks like: field1:value1#field2:value2...
var cookievaluepair=cookievalue.split("#")
for (var i=0; i<cookievaluepair.length; i++){
if (cookievaluepair[i].split(":")[0]!="toggleboxid" && this.getfield(cookievaluepair[i].split(":")[0]).type=="text")
this.getfield(cookievaluepair[i].split(":")[0]).value=unescape(cookievaluepair[i].split(":")[1])
else //else if name in name/value pair is "toggleboxid"
this.togglebox.checked=true
}
}
}
 
rememberForm.prototype.addtoggle=function(attr){
this.togglebox=this.getfield(attr)
}
 
//Call this function if you wish to clear the user's cookie of any saved values for this form instantly
rememberForm.prototype.clearcookie=function(){
setCookie(this.cookiename, "", -1)
}
 
rememberForm.dotask=function(target, functionref, tasktype){
var tasktype=(window.addEventListener)? tasktype : "on"+tasktype
if (target.addEventListener)
target.addEventListener(tasktype, functionref, false)
else if (target.attachEvent)
target.attachEvent(tasktype, functionref)
}

Open in new window

searchresults.txt
searchresultsFORMRETAIN.txt
0
painet01
Asked:
painet01
  • 22
  • 17
1 Solution
 
Göran AnderssonCommented:
There is nothing wrong with the cookie, it's not corrupted at all. The problem is that you have two different versions of the getCookie function, one that unescapes the value and one that doesn't.

When you include the formretain script that contains the second version of the getCookie function, you get the original url encoded value like "ez2231%20es0418%20" instead of a decoded value like "ez2231 es0418 ".

The escape code "%20" is used to represtent a space in an url encoded value. For some reason your code removes the "%" from the value, leaving only the character code "20" to be seen.

So, there are some possible solutions:

1. Use only the version of the getCookie function that decodes the value.

2. Don't use a separator that needs url encoding, so that either version of the function returns the same value.

3. Change the function in the formretain script so that it also decodes the value.

4. Replace every occurance of "%20" in the value with a space, so that it works with either an encoded or a decoded value.
0
 
painet01Author Commented:
3. Change the function in the formretain script so that it also decodes the value.

Would you have s code snippet that I could insert in the formretain2 script? Where would it go? I did not do the original web design and have limited skills at perl and javascript.
0
 
painet01Author Commented:
4. Replace every occurance of "%20" in the value with a space, so that it works with either an encoded or a decoded value.

How would this be done. Please provide example code.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
Göran AnderssonCommented:
The getCookie function in the formretain code is actually not very good. It doesn't make sure that the name matches the complete name of the cookie, so if you have two cookie values named "image" and "age", you may get the "image" cookie when you ask for the "age" cookie...

The regular expression should begin looking for the beginning of the string or the ; separator, to make sure that the entire name is matched.

Then the function does the match twice, once to check if there is a match, then again to get the actual value. Also it doesn't make a group for the value in the regular expression, so it needs a split to extract the value from the matched string.

This will match the complete name, and decode the value:
function getCookie(name) {
   var re = new RegExp('(?:^|;)' + name + '=([^;]+)', 'i');
   var m = document.cookie.match(re);
   return m == null ? '' : unescape(m[1]);
}

Open in new window

0
 
Göran AnderssonCommented:
To replace every occurance in a string, you use the replace method with a regular expression:

value = value.replace(/%20/g, ' ');

It's the "g" (for global) after the regular expression that makes it replace every occurance, instead of only the first which is the default behaviour of the replace function.
0
 
Göran AnderssonCommented:
Note: I recommend that you use method number 1, i.e. remove the getCookie and setCookie functions from the formretain script (or make a special version without them), so that the code uses the functions that you already have.
0
 
painet01Author Commented:
In formretain2.js , I replaced

function getCookie(Name){
var re=new RegExp(Name+"=[^;]+", "i"); //construct RE to search for target name/value pair
if (document.cookie.match(re)) //if cookie found
return document.cookie.match(re)[0].split("=")[1] //return its value
return ""
}

with

function getCookie(name) {
   var re = new RegExp('(?:^|;)' + name + '=([^;]+)', 'i');
   var m = document.cookie.match(re);
   return m == null ? '' : unescape(m[1]);
}

I did not get the results I needed. Perhaps if you revised formretain2.js and searchresultsFORMRETAIN.txt and returned them to me a solution might be realised.

Thanks in advance...looks like it's close
0
 
Göran AnderssonCommented:
The formretain2.js file still contains the old code. Did you upload it to the server?
0
 
painet01Author Commented:
Yes, I did upload the revised formretain2.js, then tried it, noticed it did not work, then went back to the original. I will upload the revised version now. Sorry for the inconvenience.
0
 
Göran AnderssonCommented:
I tried it, and it works in Firefox but not in IE. The format of the cookie is different in IE, it adds an extra space after the separating semicolon.

Use this code:
function getCookie(name) {
   var re = new RegExp('(?:^|; ?)' + name + '=([^;]+)', 'i');
   var m = document.cookie.match(re);
   return m == null ? '' : unescape(m[1]);
}

Open in new window

0
 
painet01Author Commented:
I checked the light-table with the revised code in formretain2.js. Now, no images can be added to the light-table cookie.
0
 
painet01Author Commented:
WOW...this is turning into a bigger solution than I imagined. Here's what I get

1) Firefox 3.0.6 on OSX 10.4.11
does not work...no space between image IDs in cookie

2) Firefox 2.0.0.20 on OSX 10.3.9
does not work...no space between image IDs in cookie

3) Safari 3.1.1 on OSX 10.4.11
get an error message that "there are no images on light-table" even though images were added to light-table

4) IE5 on OS 9.2.2
Images can not be added to light-table

I understand that the formretain script will only work on FF1+ IE5+ Opera 7+. However, it must not compromise any of the light-table scripts on all browsers, including those above.

I would be willing to pay up to $100.00 offline for a solution.email painet@stellarnet.com with contact details if interested. I hope this type of transaction is appropriate.

regards,

mark
0
 
painet01Author Commented:
My uneducated guess is that the formretain feature must be incorporated (rewritten) into the original searchresults.txt doc as the light-table feature was/is?
searchresults.txt
0
 
Göran AnderssonCommented:
That's because the parameters for the setCookie function is different in the formretain script. It expects a day offset instead of a date string as third parameter.

Use this to make the function accept either a date or a day offset as third parameter, so that it works with both your code and the formretain code:
function setCookie(name, value, days){
   var expire;
   if (/^\d+$/.test(days)) {
      var d = new Date();
      d.setDate(expireDate.getDate() + parseInt(days));
      expire = d.toGMTString();
   } else {
      expire = days;
   }
   document.cookie = name+"="+value+"; expires="+expire+"; path=/";
}

Open in new window

0
 
Göran AnderssonCommented:
> I would be willing to pay up to $100.00 offline for a solution.email painet@stellarnet.com with
> contact details if interested. I hope this type of transaction is appropriate.

The rules of this site does not allow that.
0
 
painet01Author Commented:
I get the same results as before. I cleared all private Data, including Cookies on all the browsers listed above and tried searchlocalFORMRETAIN.cgi again.
0
 
Göran AnderssonCommented:
Right... The value has to be encoded when it's put in the cookie. I missed that.
function setCookie(name, value, days){
   var expire;
   if (/^\d+$/.test(days)) {
      var d = new Date();
      d.setDate(expireDate.getDate() + parseInt(days));
      expire = d.toGMTString();
   } else {
      expire = days;
   }
   document.cookie = name+"="+escape(value)+"; expires="+expire+"; path=/";
}

Open in new window

0
 
painet01Author Commented:
First of all, the passing form data function no longer works in all browsers.

1) Light-table cookies work properly on Firefox 2.0.0.20 (OSX 10.3.9) & Firefox 3.0.6(OSX 10.4.11)
2) Can not add images to light-table on IE5 (OS 9.2.2) and IE5.2 (OSX 10.3.9 & OSX 10.4.11)
3) Safari 3.1.1 (OSX 10.4.11) shows no images in light-table even though images can be added.
0
 
painet01Author Commented:
I assume you are on a PC and everything works properly for you? Form Data is passed and light-tables work properly?
0
 
Göran AnderssonCommented:
Yes, I have tried it in Firefox, IE, Opera and Chrome, and it works.

The basic problem is that you are trying to combine two scripts that use functions with the same name. If you can't get it to work with the same functions, you have to rename the getCookie and setCookie in one of the scripts, and change every call to those functions in that script to use the renamed functions.
0
 
painet01Author Commented:
Do you know which script uses a function with the same name? I deleted the reference to another formretain script (formretain.js) which had function get_cookie(Name). This was a script to remember the search form data and display it if the page was revisited. This script duplicates the features of formretain2.js and is not needed.

However, the script still does not pass the form data.

Are you refering to a server side duplication of script function names? Because the only other server based script used is cookie.js at http://www.painetworks.com/search/data/cookie.js
I changed the function function getCookie (name) to function getCookie (nehme) in every incidence and then tried the script. Not only would the form data not pass, it would not read the light-table cookie. I changed cookie.js back to original.

The only other javascripts are from Quantcast (http://edge.quantserve.com/quant.js), and Statcounter (http://www.statcounter.com/counter/counter.js)

Bewildered it would work on PC browsers and not MAC
0
 
Göran AnderssonCommented:
In the file /search/data/cookie.js you have the functions getCookie and setCookie. In the file /formretain2.js you have functions that also are named getCookie and setCookie. When you include both files in a page, one definition of the functions overwrites the other.

If the functions would have worked exactly the same, it would not be a problem, but they don't. The code in each file relies on the version of the functions from the same file, so when you include both the scripts in the same page, one doesn't work.

The easiest way to put both scripts in the same page is to change the conflicting function names in one of them, and change all the calls to the functions in that file accordingly.
0
 
painet01Author Commented:
>conflicting function names

Please give me an example

>calls to the functions

Please give me an example

These terms are foreign to me
0
 
Göran AnderssonCommented:
>> conflicting function names
> Please give me an example

getCookie and setCookie

>> calls to the functions
> Please give me an example

var cookievalue=getCookie(this.cookiename)
0
 
painet01Author Commented:
>>> conflicting function names
>> Please give me an example
>
>getCookie and setCookie
>
>>> calls to the functions
>> Please give me an example
>
>var cookievalue=getCookie(this.cookiename)

Would an acceptable solution be to rename getCookie and setCookie to getCookie1 and setCookie1, respectively, in one of the scripts, say formretain2.js?

And then change the calls to those functions accordingly, as for the example above
var cookievalue=getCookie1(this.cookiename)

Are you certain the search form keywords are being passed to the results page on your browsers? If so, do you have an explanation why the script works on PCs and not Macs? Afterall, it's just javascript!

0
 
Göran AnderssonCommented:
Yes, that would work fine.

I'm not certain that the form keywords are being passed, I don't know exactly when they should be passed, and which pages should support that.
0
 
painet01Author Commented:
If you perform a search of keywords (such as big dog) on any page, such as
http://www.painetworks.com/cgi-bin/searchlocal.cgi?find=kid&method=and
the words "big dog" should appear in the search box on the results/next page.
0
 
painet01Author Commented:
0
 
painet01Author Commented:
I guess the true function of the script (to pass form data) got lost in the shuffle over the light-table cookie issue. The script DID pass form data correctly before we started changing the formretain2.js script.
0
 
Göran AnderssonCommented:
Then change it back until it works (with the new function names). The script might depend on that the functions work in a specific way, even if that way isn't something that would be considered correct...
0
 
painet01Author Commented:

Would an acceptable solution be to rename getCookie and setCookie to getCookie1 and setCookie1, respectively, in one of the scripts, say formretain2.js?

And then change the calls to those functions accordingly, as for the example above
var cookievalue=getCookie1(this.cookiename)

Please answer this previous question to get me started in the right direction
0
 
painet01Author Commented:
>Yes, that would work fine.

Was this your answer to my previous question. If so, I missed it...my bad.
0
 
Göran AnderssonCommented:
Yes, that was the reply to the "Would an acceptable solution..." question. :)
0
 
painet01Author Commented:

>Then change it back until it works (with the new function names). The script might >depend on that the functions work in a specific way, even if that way isn't something that >would be considered correct...

Script now works (passes form data) without compromising integrity of the light-table.

Would you please check all your PC browsers (Firefox, IE, Opera and Chrome) and give me your feedback [form passes correctly and light-table works] for final solution.
0
 
Göran AnderssonCommented:
I tested the page in Firefox 3.0.6, IE 7, IE 8 beta, Opera 9.62 and Chrome 1.0.154.48, and both the light table code and form retain code works.

However, I get some other errors that you might want to look at:

In the page at line 103 use a standard value instead of an IE specific value; change:
cursor: hand;
into:
cursor: pointer;

In /search/panstyle3.css line 17 you have a space in a color value, change:
color:# 2591A8;
into:
color:#2591A8;

The body tag has the event onload="DoNotCache()", but the DoNotCache function doesn't exist.
0
 
painet01Author Commented:
Thanks for the corrections...I notice line 103 has both cursor: hand; and cursor: pointer;. Should I just delete cursor: hand;?

HC=cursor: hand;
HC=cursor: pointer;
0
 
painet01Author Commented:
Thanks for the corrections...I notice line 103 has both cursor: hand; and cursor: pointer;. Should I just delete cursor: hand;?

HC=cursor: hand;
HC=cursor: pointer;
0
 
painet01Author Commented:
Thank you for your patience
0
 
Göran AnderssonCommented:
Yes, "hand" and "pointer" has the same meaning, so just keep the "pointer" value.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 22
  • 17
Tackle projects and never again get stuck behind a technical roadblock.
Join Now