Inserting different variables in JavaScript

13 posts by 4 authors in: Forums > CMS Builder
Last Post: February 24, 2014   (RSS)

By ross - January 20, 2014

Hi Jerry

Thanks for posting!

Could you attach your example files along with the schemas for all the sections in CMS Builder required? I'd like to have a quick play around with the code locally to see what I am able to come up with.

Thanks!

-----------------------------------------------------------
Cheers,
Ross Fairbairn - Consulting
consulting@interactivetools.com

Hire me! Save time by getting our experts to help with your project.
Template changes, advanced features, full integration, whatever you
need. Whether you need one hour or fifty, get it done fast with
Priority Consulting: http://www.interactivetools.com/consulting/

By gkornbluth - January 20, 2014 - edited: January 20, 2014

Hi Ross,

Here are the files that I think you'll need.

There are entries in the About and the Studio Art records and as I mentioned above, only the entries from the about record gets passed to the $output in the menucontents file.

Thanks for taking an interest in this.

Jerry Kornbluth

The first CMS Builder reference book is now available on-line!







Take advantage of a free 3 month trial subscription, only for CMSB users, at: http://www.thecmsbcookbook.com/trial.php

By gkornbluth - January 20, 2014 - edited: January 20, 2014

Hi Ross,

It didn't change much but I found and fixed one small error in the js.php file (the new one is uploaded)

Jerry

The first CMS Builder reference book is now available on-line!







Take advantage of a free 3 month trial subscription, only for CMSB users, at: http://www.thecmsbcookbook.com/trial.php

By Chris - January 27, 2014 - edited: January 27, 2014

Hi Jerry,

I find this kind of thing much easier to do by constructing data structures (in this case, an array of arrays) in PHP, then using json_encode() to turn them into JavaScript. This way you don't have to worry about trailing commas, concatenating all the quotes and commas, or escaping things.

foreach ($navigation_menu_entriesRecords as $record) {
 
  // determine div class
  $divClass = "";
  if ($record['use_submenu'] == '1') { $divClass = "anylinkmenu"; }
 
  // determine variable name
  $entry = strtolower($record['entry']);
 
  // determine item list    
  $items = array();
  if ($record['submenu_link_1_url']) { $items[] = array($record['submenu_link_1_text'], $record['submenu_link_1_url']); }
  if ($record['submenu_link_2_url']) { $items[] = array($record['submenu_link_2_text'], $record['submenu_link_2_url']); }
  if ($record['submenu_link_3_url']) { $items[] = array($record['submenu_link_3_text'], $record['submenu_link_3_url']); }
  if ($record['submenu_link_4_url']) { $items[] = array($record['submenu_link_4_text'], $record['submenu_link_4_url']); }
  if ($record['submenu_link_5_url']) { $items[] = array($record['submenu_link_5_text'], $record['submenu_link_5_url']); }
  if ($record['submenu_link_6_url']) { $items[] = array($record['submenu_link_6_text'], $record['submenu_link_6_url']); }
 
  // output javascript
  echo "var $entry = {divclass:'$divClass', inlinestyle:'width:150px; background:#DAD2D0', linktarget:''};\n";
  echo "$entry.items = " . json_encode($items) . ";\n";
}

json_encode() also helps to protect you from potential cross-site scripting attacks if your database is compromised somehow because quotes (etc.) will be escaped for you. (Note that the use of $record['entry'] above as a variable name is a potential attack vector, it would be better if the code was refactored to use hardcoded variable names, but I don't want to change anything outside of the scope of the code you posted above.)

Oh, and those 6 lines could be turned into a loop counting from 1 to 6, but I wanted to keep the code structure similar to yours.

Hope this helps!

P.S. I suspect your original bug was due to not the $sub# variables not being reset to an empty string at the beginning of each loop iteration.

All the best,
Chris

By gkornbluth - January 27, 2014 - edited: January 27, 2014

Chris,

Thank you for the suggestions and the work you put into this.

Tomorrow, after I get the basics working, I'll address the variable issue.

Best,

Jerry Kornbluth

The first CMS Builder reference book is now available on-line!







Take advantage of a free 3 month trial subscription, only for CMSB users, at: http://www.thecmsbcookbook.com/trial.php

Hi Chris,

Thank you, that code worked perfectly.

Are you saying that  a variable with the name 'entry' is a problem, or that the idea of using a variable at all presents a security issue.

And,at the risk of asking too much, how would you modify the code you offered to work with a loop that returned values for each text and url entry in each record in the navigation menu entry table?

Best,

Jerry

The first CMS Builder reference book is now available on-line!







Take advantage of a free 3 month trial subscription, only for CMSB users, at: http://www.thecmsbcookbook.com/trial.php

By Chris - January 29, 2014

Hi Jerry,

These are some pretty advanced security considerations, so if you occasionally skip doing an htmlencode() on a field, this isn't relevant at all (because the same attacks could be done on any non-htmlencoded fields.)

Consider if you had a record with the "entry" field set to the following:

foo = "bar"; alert("XSS Attack!"); foo

The resulting Javascript code you'd be generating would be:

var foo = "bar"; alert("XSS Attack!"); foo = {divclass:...

The security concern is that, if someone is able to gain access to create or modify your navigation_menu records, they can set the "entry" field to some arbitrary Javascript and attack your users by making requests on their behalf (for example, by using AJAX to submit to an Edit My Profile form on your site, changing their email address to an email address the attacker controls, then sending a Reset Password request.) It's generally a good idea to guard against all potential attacks, and to treat all data as potentially compromised (even if it comes from your database which only you (hopefully) control!)

The guard against this problem is relatively simple: only output potentially compromised data into strings (not as variable names), so instead of composing a bunch of variable names, just build up an object instead:

var about = ...;
var eco_art = ...;
var public_art = ...;

vs.

var menus = {};
menus['about'] = ...;
menus['eco_art'] = ...;
menus['public_art'] = ...;

Assuming you json_encode() those strings, there would be no way for bad data to break out of its intended use as an object key.

I didn't look into how your variables are used (about, eco_art, public_art, etc.), so I'm not sure how much else in your code would need to be changed to work with an object instead of a bunch of variables.

Does that answer your question?

All the best,
Chris

Hi Chris,

I'm sure it all makes sense but it's a bit over my head.

The variables are used to define the navigation menu entries.

Each entry may or may not have drop down menus associated with them.

They variable names come from the 'entry' field in the navigation_menu_entries table. One record for each navigation menu main category.

I was hoping to keep the menu dynamic so that when a record was added it created a new nav menu main category.

If a drop down is required for the new entry, then the use_submenu field in the record is set to 1 (yes) and the link information for each of the drop down sub menus is added to that record's submenu_link_text and submenu_link_url fields.

Hope that makes sense.

Jerry Kornbluth

The first CMS Builder reference book is now available on-line!







Take advantage of a free 3 month trial subscription, only for CMSB users, at: http://www.thecmsbcookbook.com/trial.php

Hi Jerry,

I think something like this might work:

foreach ($navigation_menu_entriesRecords as $record) {
  
  // determine div class
  $divClass = "";
  if ($record['use_submenu'] == '1') { $divClass = "anylinkmenu"; }
  
  // determine variable name
  $entry = strtolower($record['entry']);
  
  // determine item list    
  $items = array();
  if($record['use_submenu']']){
    if ($record['submenu_link_1_url']) { $items[] = array($record['submenu_link_1_text'], $record['submenu_link_1_url']); }
    if ($record['submenu_link_2_url']) { $items[] = array($record['submenu_link_2_text'], $record['submenu_link_2_url']); }
    if ($record['submenu_link_3_url']) { $items[] = array($record['submenu_link_3_text'], $record['submenu_link_3_url']); }
    if ($record['submenu_link_4_url']) { $items[] = array($record['submenu_link_4_text'], $record['submenu_link_4_url']); }
    if ($record['submenu_link_5_url']) { $items[] = array($record['submenu_link_5_text'], $record['submenu_link_5_url']); }
    if ($record['submenu_link_6_url']) { $items[] = array($record['submenu_link_6_text'], $record['submenu_link_6_url']); }
  }
  
  // output javascript
  echo "var $entry = {divclass:'$divClass', inlinestyle:'width:150px; background:#DAD2D0', linktarget:''};\n";
  echo "$entry.items = " . json_encode($items) . ";\n";
}

So I've added an if statement around the code that creates the sub menu links. If the use_submenu check box is ticked, then the code will run that creates an array of sub menu items. Otherwise an empty json object will be created.

Let me know if this doesn't work.

Thanks!

Greg

Greg Thomas







PHP Programmer - interactivetools.com