1

But not a javascript error, I think its something internal to EE?

Bear with me as this is a strange error I'm seeing. I have a few pages in EE that are set type XML and they output XML dynamically using EE tags. I can click View Template next these pages and the XML loads great in a browser window. I validated the XML and it comes back with it not being valid XML. It does seem that there is a ton of blank space at the top of my outputted XML file after the xml declaration line. So, the fact that it is not validating might be the issue. (But let's not stop there with the details.)

Is there something special i need to remove the whitespace from the xml files? It does seem excessive.

Loading in a web browser works fine - check!

Loading via jquery.ajax shows an error when I am using Chrome and I look at the Response tab. So something odd is going on there.

--

Other details are when the page initial loads, the first xml page loads fine. Then i have these tabs on the page and when i click through them, the other pages fail to load. That's kind of odd.

--

This system of XML and jquery works fine on v2.5.2. We have now moved to v2.7.3. And for whatever reason, this stopped working.

We do use VZ Address, jQuery v1.11.

The other odd thing is that I dont get any javascript errors.

--

Anyone have any suggestions for settings that I should check?

--

UPDATE I found this thread on the EE forums.

Essentially, what it says is that each form that is submitted needs to send a XID. If you have a form you would want to add this line of code to your form.

<input type="hidden" name="XID" value="{XID_HASH}" />

I have a few forms that I'm going to add this too. But my main issue is adding it to the jQuery.ajax call and I guess I need to send it through to xml pages where i am loading xml data via ajax. I'll report back if this fixes my issue.

UPDATE #2

I wrote a function in js to get the XID value from my webpage, but this did not fix the problem. I still receive an error message when my jquery.ajax calls tries to load the XML data.

Here is what I added to the javascript to get the XID value:

function getXID(show) {
  var myxid = document.getElementById("xid").value;
  return myxid;
}

And then I call this function later on inside of another function:

params['XID'] = getXID(true);

It gets added as one of the params which is later passed to the jquery.ajax call.

I checked and I can see the XID param being sent to the jquery.ajax by looking in chrome network panel, i can see the query string it builds. So we are good there.

Here is my jQuery ajax call.

jQuery.ajax({
    url: url,
    type: 'POST',
    dataType: 'xml',
    data: params,
    success: callback
});

Update #3

Did some digging and I saw that its possible to disable csrf_protection by adding this line to the config.php file.

$config['disable_csrf_protection'] = 'y';

However, my config.php already had this line in it, which is similar.

$config['csrf_protection'] = FALSE;

Uploaded the config.php file and this made no difference.

I also added this to my config.php file and this did the trick:

$config['secure_forms'] = "n";

But I don't want to disable secure forms on my website because security is especially important on the website I am working on. Does it matter if the whole site is running under SSL? Our domain runs under SSL for the whole site.

Update #4 Picking at straws here now. I had read that XIDs in EE2.7.3 are single use. So, i made a page template that generates a unique XID and i'm doing a "GET" to grab that XID value and i'm putting that in my function. So i get a fresh XID each time the function runs.

function getXID(show) {
// var myxid = document.getElementById("xid").value;
//return myxid;
$.get( "/?/Site/unique-xid", function( data ) {
var myxid = data;
    console.log(myxid);

    return myxid; 

});
 }

This still doesnt work. What is problem here? Why doesnt this work?

Am I missing something here? Feeling defeated.

Update #5 We got this fixed running in Chrome and Firefox. IE, you silly fool, why won't you work right? So, here is the solution I have so far.

In EE, I made a template to output a valid XID. That page template looks like this:

<?php header("Cache-Control: no-cache, must-revalidate"); ?>
<?php echo trim(XID_SECURE_HASH); ?>

Then in my JS file, i update the function I had listed above to this code:

function getXID(show) {

    var myxid = null;
  var scriptUrl = "/?/Site/unique-xid";
     $.ajax({
        url: scriptUrl,
        type: 'GET',
        dataType: 'text',
        async: false,
        success: function(data) {
            myxid = data;
        } 
     });
     return myxid;
}

Then inside of another function I have this code, which run the function above and grabs that XID number and assigns it to the params array which is then sent to a $.ajax POST.

var params = {};

params['XID'] = getXID(true);

So, as far as i can see this solution works great in Chrome and Firefox. IE 11 is sort of random if it works or not. I installed the Telerik control and when i run that program everything in IE works great. When i exit Telerik and try the website, it sometimes crashes the browser and then IE stops responding. Not gonna lie there is alot going on here. The tabs trigger the functions which also load points into a Google Map.

So i read that IE has problems with AJAX "GET" requests and cache'ing problems. So i added that no-cache header in the XID template to correct that. I see in Fiddler i am getting that header i am sending.

It didnt solve the problem though. IE still flakes out.

Completed

Turns out the update #5 solution worked in all browsers. On my dev site there were some images that were trying to be loaded over https that it can't find and that was creating a delay for the points load.

I fixed these broken image issues on the preview site and then everything was running much faster. This was all inherited code so we are trying to fix this little by little.

I now have the solution running on our live site and appears to be working across the board in a variety of browsers. All good news.

2

I checked and I can see the XID param being sent to the jquery.ajax by looking in chrome network panel, i can see the query string it builds. So we are good there.

It sounds like you are sending the XID in GET instead of POST data. CSRF tokens must be present in the POST data if POST data is received by ExpressionEngine.

2.7.3:
POST: XID

2.8+:
POST: csrf_token
or POST: XID

  • yeah this is all very confusing. I think my problem is that XID can only be used once and then they expire? – Robbiegod Jun 13 '14 at 20:31
  • well, hmm. I am using POST in my jQuery. I did try "GET" but that broke the map even more. The map has tabs in it. When you click the tab it triggers the jquery to load points onto the map. Do the XIDs expire? I thought i had read that they are single use. So, i need a way to generate a fresh XID with each request. – Robbiegod Jun 13 '14 at 20:41
  • 1
    As of 2.8 they are multi-use, but in prior versions, yes, you will need a new token for each call. The successful POST should return the new token in the HTTP-X-EEXID header in 2.7.2, IIRC. – Derek Jones Jun 13 '14 at 21:54
  • i think i got it!!! woo hoo!!! – Robbiegod Jun 13 '14 at 22:32
  • Great! Can you mark this as the solution, or edit if necessary? Or if your chosen solution was different, you can post the answer below. – Derek Jones Jun 14 '14 at 0:36
0

EE v2.7.3 requires a XID value be sent with every form submission and also every ajax request. Here's how I was able to fix this and also make a solution that I can reuse.

XIDs are single use in EEv2.7.3. I created a template in my site that outputs the XID number and also allows it to not be cached, which was a problem for IE. To fix that I added a header so it doesn't cache the page.

The template code looks like this and is set to allow PHP.

<?php header("Cache-Control: no-cache, must-revalidate"); ?>
<?php echo trim(XID_SECURE_HASH); ?>

Then, I needed a function to grab the HASH value and return its value:

function getXID(show) {

    var myxid = null;
  var scriptUrl = "/?/Site/unique-xid";
     $.ajax({
        url: scriptUrl,
        type: 'GET',
        dataType: 'text',
        async: false,
        success: function(data) {
            myxid = data;
        } 
     });
     return myxid;
}

Then, with each link clicked on the map, i need to execute the function and send the HASH value along with the AJAX request that loads some XML and then plots points onto a Google Map. That code looks like this:

var params = {};

params['XID'] = getXID(true);

Finally the params array is sent via a ajax POST to get the xml file.

function downloadUrl(url, params, callback) {
    jQuery.ajax({
        url: url,
        type: 'POST',
        dataType: 'xml',
        data: params,
        success: callback
    });

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.