1

Alright so let me first say that this particular project is very odd and it has snowballed considerably in the past few months.

I am not a master PHP programmer. What I am is a web developer with three years of experience who had only himself as a resource for the overwhelming majority of this project. Feel free to completely criticize what I have done here, I'm open to it. I'm looking for solutions.

Using:

Expression Engine 2.9.0

Expresso Store 2.3.1

Streeng

The client wanted a pseudo ecommerce solution that would sit on a server + CMS. However, they wanted this platform to be managed and fed by their AS400 Mainframe while also being completely PCI compliant. Expression Engine was a natural fit for most of these demands, and I also chose Expresso because of how easily it integrates with EE. It's a single ecosystem.

So when a customer goes to 'check out' an external file must be generated (in real time) with all of that customers information that he entered. His billing and shipping information + everything he ordered.

I use the hash to create a unique file name on the server.

The problem comes up when a customer puts " or / into one of the form fields. No matter what regex I use, the whole thing explodes the second the process template loads up. I've used various regex for this, but

~[\\/'<>|]~

is the most generally effective. I had a different version that was wrapped in single quotes and targeted " as well, but it failed. That's why you do not see it included in the code below.

I've also tried the nuclear approach with the following regex (just for testing purposes), but it still results in the same error each time:

~['\\\"\^\&\*\(\)\%\$\#\@\!\>\<,\.\/]+~

Eliminating these characters is important, because it will mess with the XML file creation process.. And I had to map that out in detail because they instructed me as to how the output should look (must look) for them to interpret the data.

Below is the 'process' template code, which is the final step in the checkout. This goes unseen to the customer except for a spinning processing wheel gif.

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Checkout Processing</title>
</head>
<body>
<div style="float: left; position: relative;left: 45%;">
   <div class="float: left; position: relative; left: -45%; height:50px; width:50px;">
   <img height="100" width="100" src="http://www.asus.com/support/images/support-loading.gif"/>
   </div>
</div>
{exp:store:checkout
    return="/checkout/thank_you"
}    
    {if no_items}
        {redirect="/products/"}
    {/if}

    {if shipping_name =="" OR billing_name =="" OR billing_address1 =="" OR shipping_address1 =="" OR order_email =="" OR billing_phone =="" OR shipping_phone =="" OR billing_postcode =="" OR shipping_postcode =="" OR billing_country =="" OR shipping_country =="" OR shipping_city =="" OR billing_city ==""}
        {redirect="/checkout/shipping_details"}
    {/if}
<?php exportSQL2(); ?> 

<?php
//This function triggers automatically when the page is loaded. It exports the order data into an xml file so that the Mainframe maybe pick it up and process.


   function exportSQL2()
   {

   $EE =& get_instance(); 
      $fnameData = $EE->db->query("SELECT billing_first_name, billing_last_name, shipping_first_name, shipping_last_name FROM exp_store_orders WHERE order_hash = '{order_hash}'")->row_array();

      $MainframeAccountName = "";

      if ('{member_id}' !="") {
      $MainframeAccountNameQuery = $EE->db->query("SELECT Mainframe_account_number FROM exp_members WHERE member_id = '{member_id}'")->row_array();
      $MainframeAccountName = $MainframeAccountNameQuery['Mainframe_account_number'];
      } 



      $billing_first_name= "{billing_first_name}"; 

      $billing_first_name= preg_replace("~[\\\\/'<>|]~", "", $billing_first_name);
      $billing_first_name= preg_replace('/[^\w ]/', '', $billing_first_name);

      {!--$billing_first_name= htmlspecialchars($billing_first_name, ENT_QUOTES); --}


      $billing_last_name= "{billing_last_name}";      
      $billing_last_name= preg_replace("~[\\\\/'<>|]~", "", $billing_last_name); 
      $billing_last_name= preg_replace('/[^\w ]/', '', $billing_last_name);

      $billing_address1= "{billing_address1}";      
      $billing_address1= preg_replace("~[\\\\/'<>|]~", "", $billing_address1); 
      $billing_address1= preg_replace('/[^\w ]/', '', $billing_address1);

      $billing_address2= "{billing_address2}";      
      $billing_address2= preg_replace("~[\\\\/'<>|]~", "", $billing_address2); 
      $billing_address2= preg_replace('/[^\w ]/', '', $billing_address2);

      $billing_city= "{billing_city}";      
      $billing_city= preg_replace("~[\\\\/'<>|]~", "", $billing_city); 
      $billing_city= preg_replace('/[^\w ]/', '', $billing_city);

      $billing_postcode= "{billing_postcode}";      
      $billing_postcode= preg_replace("~[\\\\/'<>|]~", "", $billing_postcode); 
      $billing_postcode= preg_replace('/[^\w ]/', '', $billing_postcode);

      $billing_phone= "{billing_phone}";      
      $billing_phone= preg_replace("~[\\\\/'<>|]~", "", $billing_phone); 
      $billing_phone= preg_replace('/[^\w ]/', '', $billing_phone);      

      $shipping_first_name= "{shipping_first_name}";      
      $shipping_first_name= preg_replace("~[\\\\/'<>|]~", "", $shipping_first_name); 
      $shipping_first_name= preg_replace('/[^\w ]/', '', $shipping_first_name);

      $shipping_last_name= "{shipping_last_name}";      
      $shipping_last_name= preg_replace("~[\\\\/'<>|]~", "", $shipping_last_name); 
      $shipping_last_name= preg_replace('/[^\w ]/', '', $shipping_last_name);

      $shipping_address1= "{shipping_address1}";      
      $shipping_address1= preg_replace("~[\\\\/'<>|]~", "", $shipping_address1); 
      $shipping_address1= preg_replace('/[^\w ]/', '', $shipping_address1);

      $shipping_address2= "{shipping_address2}";      
      $shipping_address2= preg_replace("~[\\\\/'<>|]~", "", $shipping_address2); 
      $shipping_address2= preg_replace('/[^\w ]/', '', $shipping_address2);

      $shipping_city= "{shipping_city}";      
      $shipping_city= preg_replace("~[\\\\/'<>|]~", "", $shipping_city); 
      $shipping_city= preg_replace('/[^\w ]/', '', $shipping_city);

      $shipping_postcode= "{shipping_postcode}";      
      $shipping_postcode= preg_replace("~[\\\\/'<>|]~", "", $shipping_postcode); 
      $shipping_postcode= preg_replace('/[^\w ]/', '', $shipping_postcode);

      $shipping_phone= "{shipping_phone}";      
      $project= preg_replace("~[\\\\/'<>|]~", "", $shipping_phone); 
      $shipping_phone= preg_replace('/[^\w ]/', '', $shipping_phone);


      $project= "{order_custom4}";      
      $project= preg_replace("~[\\\\/'<>|]~", "", $project); 
      $project= preg_replace('/[^\w ]/', '', $project);
      {!-- $project= preg_replace('/[^\w ]/', '', '{order_custom4}'); --} 
      {!-- $project= htmlspecialchars($project, ENT_QUOTES); --}


      $shipping_account= "{order_custom2}";      
      $shipping_account= preg_replace("~[\\\\/'<>|]~", "", $shipping_account); 
      $shipping_account= preg_replace('/[^\w ]/', '', $shipping_account);

      $shipping_carrier= "{order_custom3}";      
      $shipping_carrier= preg_replace("~[\\\\/'<>|]~", "", $shipping_carrier); 
      $shipping_carrier= preg_replace('/[^\w ]/', '', $shipping_carrier);

      $instruction= "{order_custom1}";      
      $instruction= preg_replace("~[\\\\/'<>|]~", "", $instruction); 
      $instruction= preg_replace('/[^\w ]/', '', $instruction);      

      if ('{shipping_method}'=="FREE - FedEx Ground") {
      $shipping_account="";
      $shipping_carrier="";
      }



      $dir = '/home/example/example.com/transfer/out';

{exp:streeng  find="'" replace=""}   
      $info ="
<order>
   <order_id>{order_id}</order_id>
   <member_id>{member_id}</member_id>
   <customer_number>".$MainframeAccountName."</customer_number>
   <hash>{order_hash}</hash>
   <date>{current_time format="%Y%m%d"}</date>
   <time>{current_time format="%H%i%s"}</time>
   <action>add</action>
   <email>{order_email}</email>
   <billing_first_name>".$billing_first_name."</billing_first_name>
   <billing_last_name>".$billing_last_name."</billing_last_name>
   <billing_company></billing_company>
   <billing_address1>".$billing_address1."</billing_address1>
   <billing_address2>".$billing_address2."</billing_address2>
   <billing_city>".$billing_city."</billing_city>
   <billing_state>{billing_state_name}</billing_state>
   <billing_postal>".$billing_postcode."</billing_postal>
   <billing_country>{billing_country_name}</billing_country>
   <billing_phone>".$billing_phone."</billing_phone>
   <shipping_first_name>".$shipping_first_name."</shipping_first_name>
   <shipping_last_name>".$shipping_last_name."</shipping_last_name>
   <shipping_company></shipping_company>
   <shipping_address1>".$shipping_address1."</shipping_address1>
   <shipping_address2>".$shipping_address2."</shipping_address2>
   <shipping_city>".$shipping_city."</shipping_city>
   <shipping_state>{shipping_state_name}</shipping_state>
   <shipping_postal>".$shipping_postcode."</shipping_postal>
   <shipping_country>{shipping_country_name}</shipping_country>
   <shipping_phone>".$shipping_phone."</shipping_phone>
   <shipping_account>".$shipping_account."</shipping_account>
   <shipping_carrier>".$shipping_carrier."</shipping_carrier>
   <shipping_method>{shipping_method}</shipping_method>
   <project>".$project."</project>
   <instruction>".$instruction."</instruction>{items}{exp:gwcode_categories entry_id="{entry_id}" excl_cat_id="28|29|30|31|32|33|34|35|36|37|43|40|38|2|27|3|50|51|52|53|48"  style="linear" limit="1"}  
   <sample>
      <pattern>{cat_name}</pattern>
      <color>{title}</color>
      <quantity>{item_qty}</quantity>
   </sample>{/exp:gwcode_categories}{/items}
</order>

      ";
{/exp:streeng}



      $file = $dir . '/{order_hash}.xml';
      file_put_contents($file, $info);    


      //Creates a backup of the file and stores it in the outArchive folder.
      copy('/home/example/example.com/transfer/out/{order_hash}.xml', '/home/example/example.com/transfer/backup/{order_hash}.xml');
     } 
   ?>     

    <div class="form-actions">
        <input type="submit" name="submit" value="Place Order" id="submit" class="btn btn-success" style="display:none !important;"  />
    </div>

<script type="text/javascript">
    window.onload = function submit()
    {
        document.getElementById("submit").click(); // Simulates button click
    }
</script>

{/exp:store:checkout}
</body>
</html>

The error:

Parse error: syntax error, unexpected '"' in /chroot/home/example/example.com/html/system/expressionengine/libraries/Functions.php(688) : eval()'d code on line 70
1

It is in general not a great idea to use PHP straight in the template, but that's a story for another day. It would be best to use Expresso Store's developer hooks like the "store_order_complete_end" hook to create and process the XML file on success.

Going with your example: Check the string you are building up in particular at the tag.

".$instruction."{items}{exp:gwcode_categories entry_id="{entry_id}" excl_cat_id="28|29|30|31|32|33|34|35|36|37|43|40|38|2|27|3|50|51|52|53|48" style="linear" limit="1"}

You are using double quotes inside double quotes without escaping it. Rather use single quotes around {entry_id} and the rest of your parameters, like entry_id='{entry_id}'.

Does that help?

  • You're completely correct about it not being a great idea. I know how much of a security vulnerability it is. Unfortunately I had to work with the resources I was given.. I'll look into the suggestion you've given me and let you know! Thank you very much. – user2543853 Oct 28 '14 at 22:30

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.