CF7: send submitted data to another URL as JSON

If you need to send data from a Contact Form 7 (CF7) form to another URL you can use this simple PHP script. Just add it in your WordPress functions.php file inside your theme.

// define the URL where data should be submitted, this constant can be stored in your `wp-config.php` file
define('CF7_TO_API_URL', 'https://...........');

function action_wpcf7_mail_sent( $contact_form ) { 
    // you can limit this script to certains forms, just change the IDs (111,222,333) and uncomment line 10 and 47
    // if (in_array($WPCF7_ContactForm->id(), [111,222,333])) {
        $wpcf7      = WPCF7_ContactForm::get_current();
        $submission = WPCF7_Submission::get_instance();

        if ($submission) {
            $data = $submission->get_posted_data();
            $url = $submission->get_meta( 'url' ); // url where the submit come from

            $postId = url_to_postid($url); // from the url we get the post ID
            $postType = get_post_type($postId); // from post ID we get the post type
            $title = get_the_title($postId); // and the title

            $output = [
                "firstname" => $data['firstname'],
                "lastname" => $data['lastname'],
                "email" => $data['email'],
                "phone" => $data['phone'], // add all needed fields

                "source" => $url,
                "is_product" => $postType === 'product', // ex: we want to know if the page was a product (custom post)
                "product_name" => $postType === 'product' ? $title : '', // if it is a product tell me the product name (title)

                "want_newsletter" => $data['newsletter'] === 1  ||   $data['newsletter'] === "1" // ex. for checkbox    
            ];

            $options = array(
                'http' => array(
                    'method'  => 'POST', // you can change the method (GET, POST)
                    'content' => json_encode( $output ), // php array as json
                    'header'=>  "Content-Type: application/json\r\n" .
                        "Accept: application/json\r\n"
                )
            );
              
            $context  = stream_context_create( $options );
            $result = file_get_contents( CF7_TO_API_URL, false, $context );
            $response = json_decode( $result ); // you can use/output the response from 
        }
    // }
}; 
         
// add the action 
add_action( 'wpcf7_mail_sent', 'action_wpcf7_mail_sent', 10, 1 ); 

Crypto Miner (Coinhive) in YouTube Ads

During normal browsing on YouTube, at some point, the antivirus Avast reported something that was not good.

From the Chrome Inspector it appears that one of the ads is infected and tries to load a crypto miner from Coinhive

Everything has been reported to Google, now I await the answer.

Simple Ajax validation for WordPress Registration Form

Just install and WordPress registration form will use ajax validation (no reload). Continue reading “Simple Ajax validation for WordPress Registration Form”

javascript: the beginning and end of an image along its center

Javascript snippet that detects the beginning and end of an image along its center, alpha supported.

Parameters: image id (without ‘#’)

Returns an object with:
– start (first non trasparent/not white pixel from center top)
– end (first not trasparent/not white pixel from center bottom)
– image width
– image height

 

function getRealImageYStartEnd($imageId){
    var img = document.getElementById($imageId);
    var canvas = document.createElement('canvas');
    canvas.width = img.width;
    canvas.height = img.height;
    canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);

    var context = canvas.getContext('2d');
    var middle = Math.floor(img.width/2);
    var startImage = 0;
    var endImage = img.height;

    for (i = 0; i < img.height; i++){
        var data = context.getImageData(Math.floor(img.width/2), i, 1, 1).data;
        if (data[0] !== 0 &amp;&amp; data[1] !== 0 &amp;&amp; data[1] !== 0 &amp;&amp; data[3] !== 0){
            startImage = i;
            break;
        }
    }

    for (i = img.height; i >= 0; i--){
        var data = context.getImageData(Math.floor(img.width/2), i, 1, 1).data;
        if (data[0] !== 0 &amp;&amp; data[1] !== 0 &amp;&amp; data[1] !== 0 &amp;&amp; data[3] !== 0){
            endImage = i;
            break;
        }
    }

    return {start: startImage, end: endImage, width: img.width, height: img.height};
}

WordPress 4.8.3 + ACF + get_posts with meta_query

Here in Papion headquarters we love using ACF.
Advanced Custom Fields is one of the best WordPress plugins for custom field management.

Recently, with the new WordPress 4.8.3, a change was made in the prepare query to the database.

Instead of characters like % now we have placeholders like {1872368126381726387126381276381726318723} (for more information see code).

It does not involve any major issues, except when we use ACF in combination with get_posts and metaquery to search for post based on repeater fields that have meta_key in fieldgrup_%_field format like “fieldgrup_0_field”, “fieldgrup_1_field”, etc.

One of the solutions ACF proposes is (source)

 
function my_posts_where( $where ) {
  $where = str_replace("meta_key = 'locations_%", "meta_key LIKE 'locations_%", $where);
  
  return $where;
}

add_filter('posts_where', 'my_posts_where');

However, with the update, instead of the “%” character, we find ourselves with a numeric placeholder, so this code should be changed so that the comparison is done with the query without placeholders:

function my_posts_where( $where ) {
  $where = str_replace("meta_key = 'locations_%", "meta_key LIKE 'locations_%", $where);
  
  return $where;
}

add_filter('posts_where', 'my_posts_where');

Iubenda, check consent given in javascript

Logo Iubenda

Simple script to check if user have given consent to Iubenda privacy/cookie policy. Function will return true if user has given consent, false otherwise.

Semplice script per verificare se l’utente ha dato il consenso alla privacy / cookie policy di Iubenda. La funzione restituirà true se l’utente ha dato il consenso, altrimenti falso.

Event style use:

function iubendaConsentGiven(){
  var pairs = document.cookie.split(";");
  var cookies = {};
  for (var i=0; i<pairs.length; i++){
    var pair = pairs[i].split("=");
	if(pair[0].indexOf('_iub_cs-s') !== -1 || pair[0].indexOf('_iub_cs') !== -1 ) {
    	return true;
    }
  }
  return false;
}
var checkCookie = true;
var checkCookieInterval = setInterval(function(){
	if(iubendaConsentGiven()){
		console.log('ok');
		clearInterval(checkCookieInterval);
    }
}, 1000);

G Suite: Gmail and Inbox crashing. Solved

Just installed G Suite, launched Gmail / Inbox and … crash? Seems that it is related to the fact that G Suite cannot use Chrome process.

So tried to install Chrome ( G Suite version ), everything seems ok and working now. Solved.

09-29 23:06:14.531 9281 9281 I WebViewFactory: Loading com.android.chrome version 61.0.3163.98 (code 316309852)
09-29 23:06:14.580 9281 9281 I cr_LibraryLoader: Time to load native libraries: 4 ms (timestamps 8515-8519)
09-29 23:06:14.592 9281 9281 I chromium: [INFO:library_loader_hooks.cc(136)] Chromium logging enabled: level = 0, default verbosity = 0
09-29 23:06:14.592 9281 9281 I cr_LibraryLoader: Expected native library version number "61.0.3163.98", actual native library version number "61.0.3163.98"
09-29 23:06:14.610 9281 9437 W cr_ChildProcLH: Create a new ChildConnectionAllocator with package name = com.android.chrome, sandboxed = true
09-29 23:06:14.625 9281 9437 E bta : bzc Uncaught Android Crash on thread Chrome_ProcessLauncherThread with tid 3396 on version 1.56.168919525.release
09-29 23:06:14.625 9281 9437 E bta : java.lang.RuntimeException: Could not get application info.
09-29 23:06:14.625 9281 9437 E bta : at org.chromium.base.process_launcher.ChildConnectionAllocator.create(ChildConnectionAllocator.java:11)
09-29 23:06:14.625 9281 9437 E bta : at org.chromium.content.browser.ChildProcessLauncherHelper.getConnectionAllocator(ChildProcessLauncherHelper.java:71)
09-29 23:06:14.625 9281 9437 E bta : at org.chromium.content.browser.ChildProcessLauncherHelper$2.run(ChildProcessLauncherHelper.java:8)
09-29 23:06:14.625 9281 9437 E bta : at android.os.Handler.handleCallback(Handler.java:751)
09-29 23:06:14.625 9281 9437 E bta : at android.os.Handler.dispatchMessage(Handler.java:95)
09-29 23:06:14.625 9281 9437 E bta : at android.os.Looper.loop(Looper.java:154)
09-29 23:06:14.625 9281 9437 E bta : at android.os.HandlerThread.run(HandlerThread.java:61)
09-29 23:06:14.628 9281 9281 I cr_BrowserStartup: Initializing chromium process, singleProcess=false
09-29 23:06:14.629 9281 9437 E AndroidRuntime: FATAL EXCEPTION: Chrome_ProcessLauncherThread
09-29 23:06:14.629 9281 9437 E AndroidRuntime: Process: com.google.android.apps.inbox, PID: 9281
09-29 23:06:14.629 9281 9437 E AndroidRuntime: java.lang.RuntimeException: Could not get application info.
09-29 23:06:14.629 9281 9437 E AndroidRuntime: at org.chromium.base.process_launcher.ChildConnectionAllocator.create(ChildConnectionAllocator.java:11)
09-29 23:06:14.629 9281 9437 E AndroidRuntime: at org.chromium.content.browser.ChildProcessLauncherHelper.getConnectionAllocator(ChildProcessLauncherHelper.java:71)
09-29 23:06:14.629 9281 9437 E AndroidRuntime: at org.chromium.content.browser.ChildProcessLauncherHelper$2.run(ChildProcessLauncherHelper.java:8)
09-29 23:06:14.629 9281 9437 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:751)
09-29 23:06:14.629 9281 9437 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:95)
09-29 23:06:14.629 9281 9437 E AndroidRuntime: at android.os.Looper.loop(Looper.java:154)
09-29 23:06:14.629 9281 9437 E AndroidRuntime: at android.os.HandlerThread.run(HandlerThread.java:61)

XSS scripting and pgp.mit.edu

What is a XSS attack?

Cross-site scripting (XSS) is a type of computer security vulnerability typically found in web applications. XSS enables attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy.

source Wikipedia

 

If you use Thunderbird and plugins like Enigmail you have the option to import all PGP keys related to email addresses that are present in your address book.

First of all you need is to specify a key server, like pgp.mit.edu, then the plugin, for every single email address, will look for corresponding PGP key and will prompt you if you want to import results.

But, some times, the key is not what you’ll expect.

Some entries contains invalid data, and to be more specific, can contain malicious code.

If you request these entries in the lookup form, the output html can contain this code and execute javascript functions, redirects, XSS attacks, ecc.

In conclusion

Keep your eyes open, and avoid mass import of PGP keys.


  • 2017-08-01: reported to bug-pks@mit.edu