Jump to content
charco

Regex breaks down when it encounters a º sign or an &

Recommended Posts

Hi there. I have a javascript code that packages an array as a string and sends it to a php mailer, which then separates the string into an array for mailing using a preg_split regular expression that searches for a comma followed by an html tag.

$myWrongArray = preg_split("/,(?=<)/",$myVar); // lookahead splits the string when the comma is before a tag (the opening bracket < )
//The look ahead is (?=<), which interrogates the next character and if it is the angle bracket, <, the preg_split function operates.

Everything works great EXCEPT when the string contains a degree sign or an &, in which case the array is returned up to the degree or & and then stops.

I can’t for the life of me understand it. Any ideas?

Share this post


Link to post
Share on other sites

The problem is somewhere else.

What's the rest of your code? And at what point are you seeing that the entries are cut off?

Share this post


Link to post
Share on other sites

An array is sent from javascript to the php mailer via a (relatively long) string.

The string contains html tags and also it has commas in the middle of some of the array members.

To split the string back into an array for the php mailer I use the regex with a look forward, as explained above.

Everything works perfectly UNLESS the string contains a degree sign, º, or an ampersand, &, in which case the php output simply does not show any more of the array. It doesn't break the program, but the array after the degree sign, º, or an ampersand, &, is no longer shown.

For example if javascript sends:

var wrongArray = "<p>This is my question 1,</p><p>This is my question 2,</p><p>This is my question 3,</p><p>This is my question 4,</p>";

Gets sent using the postIt() function below

function postIt() {   
var http = new XMLHttpRequest();
var url = "../mail/testSum.php";
var params = "realname="+myName+"&rightAnswers="+correct+"&percentageScore="+percentage+"&wrongArray="+wstore+"&asked="+numq+"&mins="+minutes+"&secs="+seconds+"&deliver="+destination+"&testName="+test;
http.open("GET", url+"?"+params, true);
http.onreadystatechange = function() {                //Call a function when the state changes.
    if(http.readyState == 4 && http.status == 200) {
        //alert(http.responseText);
    }
}
http.send(null);
}

This is then received by the php mailer:

$myVar=$_GET["wrongArray"];

which is then split into an array using preg_split()

$myWrongArray = preg_split("/,(?=<)/",$myVar);

The resulting array is output to the email message in the middle of an unordered list:

foreach($myWrongArray as $my_Array){
    $message .= "\r\n\r\n<li style='font-family:verdana;font-size:12px;color:teal'>".$my_Array."</li>";  
}

 

The whole php looks like this:
 

<?php

error_reporting(E_ALL);

$data1=$_GET["realname"];
$data2=$_GET["rightAnswers"];
$data3=$_GET["asked"];
$data4=$_GET["mins"];
$data5=$_GET["secs"];
$data6=$_GET["percentageScore"];
$data7=$_GET["deliver"];
$data8=$_GET["testName"];
$myVar=$_GET["wrongArray"];

$emailList = "xxx@gmail.com".","."xxyy@gmail.com";

$myWrongArray = preg_split("/,(?=<)/",$myVar);

$sendTo = $data7;
$subject = $data8." summary results for ".$data1;

$headers = "MIME-Version: 1.0" . "\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\n";
$headers .= "bcc: $emailList\r\n";
$headers .= "From: " . $data1. "<" . "results@ibchem.com".">\r\n";
$headers .= "Reply-To: " . $data7 . "\r\n";
$headers .= "Return-path: " . $data7. "\r\n";

// now we can add the content of the message to a body variable
$message = "<html><head><title>Online test - ".$data8."</title></head><body>";
$message .= "<p style='font-family:verdana;font-size:12px;color:blue'>".$data1.", you have attempted ".$data3. " questions";

$message .= " in ".$data4." minutes and ".$data5." seconds";

$message .= " and scored a total of ".$data2.".</p>";
$message .= " <p style='font-family:verdana;font-size:12px;color:blue'>Final percentage = ".$data6."%</p>\r\n\r\n";
$message .= "<p style='font-family:verdana;font-size:12px;color:blue'>The following questions were answered incorrectly: </p><hr /><ul>";

foreach($myWrongArray as $my_Array){
    $message .= "\r\n\r\n<li style='font-family:verdana;font-size:12px;color:teal'>".$my_Array."</li>";  
}

//$message = strip_tags($message);
$message .= "</ul><hr /></body></html>";

// finally, send the email
mail($sendTo, $subject, $message, $headers);

?>

 

Share this post


Link to post
Share on other sites

OK, I think that I'm getting closer.

It's not the array or the preg_split that's the problem, it's the html email which is not rendering the degree symbol, or any other unusual character.

I am using:
 

// put the headers in place

$headers = "MIME-Version: 1.0" . "\n";
$headers .= "Content-type:text/html;charSet=utf-8" . "\n";
$headers .= "bcc: $emailList\r\n";
$headers .= "From: " . $data1. "<" . "xxx@gmail.com".">\r\n";
$headers .= "Reply-To: " . $data7 . "\r\n";
$headers .= "Return-path: " . $data7. "\r\n";

// now we can add the content of the message to a body variable

$message = "<!DOCTYPE html>";
$message .= "<html><head><title>Online test - ".$data8."</title></head><body>";
$message .= "<p style='font-family:verdana;font-size:12px;color:blue'>".$data1.", you have attempted ".$data3. " questions";

$message .= " in ".$data4." minutes and ".$data5." seconds";

$message .= " and scored a total of ".$data2.".</p>";
$message .= " <p style='font-family:verdana;font-size:12px;color:blue'>Final percentage = ".$data6."%</p>\r\n\r\n";
$message .= "<p style='font-family:verdana;font-size:12px;color:blue'>The following questions were answered incorrectly: </p><hr /><ul>";

foreach($myWrongArray as $my_Array){
    $message .= "\r\n\r\n<li style='font-family:verdana;font-size:12px;color:teal'>".$my_Array."</li>";  
}

$message .= "</ul><hr /></body></html>";

// finally, send the email
mail($sendTo, $subject, $message, $headers);

Can anyone see why the email is not showing the degree character?

Share this post


Link to post
Share on other sites

An ampersand will cause problems if you inject the value into a query string. Use encodeURIComponent. Or better yet, don't send such free-form data through the query string and POST it instead. Which is what you should be doing anyways because the request causes something to happen on the backend (sending an email) and that should not be triggerable through a simple GET request.

For the degree sign, do other non-standard symbols break? Accented characters? Greek or Cyrillic? Fancy symbols not on the keyboard? Check your character encodings.

Share this post


Link to post
Share on other sites

So, if I'm understanding correctly, you have this HTML

<p>This is my question 1,</p><p>This is my question 2,</p><p>This is my question 3,</p><p>This is my question 4,</p>

And you want to turn it into this?

Array (
    [0] => "This is my question 1"
    [0] => "This is my question 2"
    [0] => "This is my question 3"
    [0] => "This is my question 4"
)

If that's the case, then you can just load it into a DOMDocument, something like this.

$dom = new DOMDocument;
$dom->loadHTML("<p>This is my question 1,</p><p>This is my question 2,</p><p>This is my question 3,</p><p>This is my question 4,</p>");
$paragraphs = $dom->getElementsByTagName('p');
$paragraph_values = array();
foreach ($paragraphs as $p) {
    $paragraph_values[] = $p->nodeValue
}

 

Share this post


Link to post
Share on other sites

No, I have no problem with the array.

I want php to be able to use special characters in the emails. But º and & stop the message from completing.

Share this post


Link to post
Share on other sites
7 hours ago, charco said:

No, I have no problem with the array.

I want php to be able to use special characters in the emails. But º and & stop the message from completing.

So does that mean what I said has helped you fix, or at least find, the source of the problem?

Share this post


Link to post
Share on other sites

I have identified that the source of the problem to be using GET rather than POST when passing data from javascript to php via AJAX.

I am almost there, but there are still problems between the AJAX parcelling and the PHP unpacking.

The javascript generates me an array in a function using:

wstore.push(question+"<p style='color:teal'> Answer = "+ans+dim+"</p>");

To store the question and the answer in an array called wstore. So that everytime a question is answered incorrectly it goes into the array.

When the quiz is finished the array is sent (as a string) to PHP for processing.

function postIt() {
            var wrongArray = JSON.stringify(wstore);
   $.ajax({
        type: "POST",
        url: '../mail/testSum.php',
        data: {wrongArray : wrongArray},
        cache: false,
        success: function(){
            //alert("OK");
        }
    });
}

In PHP the string is stored in a PHP variable:

$myVar=$_POST["wrongArray"];

And then split back into an Array, using pregsplit to identify the commas that appear before a html tag

$myWrongArray = preg_split("/,(?=<)/",$myVar);

This is then displayed in the message for sending:

foreach($myWrongArray as $my_Array){
    $message .= "\r\n\r\n<li style='font-family:verdana;font-size:12px;color:teal'>".$my_Array."</li>";  
}

.. but it does not show as an unordered list :(

I don't know where to go from here ... The output email is almost correct, but retains square brackets (from somewhere) and "," between questions (see image):

 

 

 

 

Screenshot_2019-10-11 Mail - Graeme Kenneth Hall - Outlook.png

Share this post


Link to post
Share on other sites

It looks like your output is a single string ...

$output = '["1.Question text 1 blah blah","2.Question text 2 blah blah","3.Question text 3 blah blah","4.Question text 4 blah blah"]';

… (a json-encoded array) which is why you get a single <li> item.

However, you should get the required result if you ...

$questions = json_decode($output, true);

echo "<ul>";
foreach ($questions as $q) {
    echo "<li>$q</li>";
}
echo "</ul>";

image.png.15bc8a44563869ad26b8f270f6e4b837.png

Share this post


Link to post
Share on other sites

Yes, that's it!

I gave it a go and it is EXACTLY the answer.

Thank you all contributors very much for your patience.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.