Commit 9567ee7d authored by Julian Pustkuchen's avatar Julian Pustkuchen
Browse files

Issue #3236280 by John_B, Anybody: Drupal 7 version

parents 7821c006 2f6ee857
Loading
Loading
Loading
Loading
+25 −20
Original line number Diff line number Diff line
INTRODUCTION
------------
FriendlyCaptcha for Drupal
====================

The FriendlyCaptcha module uses the FriendlyCaptcha web service to
improve the CAPTCHA system. For
more information on what FriendlyCaptcha is, please visit:
    https://friendlycaptcha.com

The Friendly Captcha module uses the Friendly Captcha web service.
For more information about Friendly Captcha is, please visit:
https://friendlycaptcha.com/

REQUIREMENTS
DEPENDENCIES
------------

This module requires the following modules:
* FriendlyCaptcha module depends on the CAPTCHA module.
  https://www.drupal.org/project/captcha

 * [Captcha](https://www.drupal.org/project/captcha)

INSTALLATION
------------

 * Install as you would normally install a contributed Drupal module. Visit
   https://www.drupal.org/node/1897420 for further information.

 * Copy the friendly-challenge javascript library to /libraries/friendly-challenge
 * Copy the friendly-challenge javascript library to your libraries folder,
   typically sites/all/libraries/friendly-challenge
   URL: https://unpkg.com/friendly-challenge@0.8.11/widget.min.js
   (resulting in: /libraries/friendly-challenge/widget.min.js)
   (resulting in: sites/all/libraries/friendly-challenge/widget.min.js)

   Hint: Depending on your composer template / installation method the libraries 
   folder might be found in /web or /htdocs.

CONFIGURATION
-------------
@@ -31,15 +29,22 @@ CONFIGURATION
1. Enable FriendlyCaptcha and CAPTCHA modules in:
       admin/modules

2. You'll now find the configuration tab in the CAPTCHA
2. You'll now find a FriendlyCaptcha tab in the CAPTCHA
   administration page available at:
       admin/config/people/captcha/friendlycaptcha

3. Register your web site at
       https://app.friendlycaptcha.com/account
       https://friendlycaptcha.com

4. Input the sitekey and API Key into the Friendly Captcha settings.
4. Input the optional site key and required private API key into the FriendlyCaptcha settings.

5. Visit the Captcha administration page and set where you
   want the FriendlyCaptcha form to be presented:
       admin/config/people/captcha

THANK YOU
---------

 * Thank you goes to the FriendlyCaptcha team for all their
   help, support and their amazing Captcha solution
       https://friendlycaptcha.com
+47 −0
Original line number Diff line number Diff line
<?php

/**
 * @file
 * Provides the Friendly Captcha administration settings.
 */

/**
 * Form callback; administrative settings for Friendlycaptcha.
 */
function friendlycaptcha_admin_settings()
{
    $form['friendlycaptcha_general_settings'] = array(
        '#type' => 'fieldset',
        '#title' => t('General settings'),
    );
    $form['friendlycaptcha_general_settings']['friendlycaptcha_site_key'] = array(
        '#type' => 'textfield',
        '#title' => t('Site key'),
        '#default_value' => variable_get('friendlycaptcha_site_key', ''),
        '#maxlength' => 40,
        '#description' => t('The site key given to you when you <a href="@url">register for FriendlyCaptcha</a>.', array('@url' => 'https://friendlycaptcha.com/signup/')),
        '#required' => TRUE,
    );
    $form['friendlycaptcha_general_settings']['friendlycaptcha_api_key'] = array(
        '#type' => 'textfield',
        '#title' => t('API key'),
        '#default_value' => variable_get('friendlycaptcha_api_key', ''),
        '#maxlength' => 80,
        '#description' => t('The secret API key given to you when you <a href="@url">register for FriendlyCaptcha</a>.', array('@url' => 'https://friendlycaptcha.com/signup/')),
        '#required' => TRUE,
    );
    $form['friendlycaptcha_api_endpoint'] = [
        '#default_value' => variable_get('friendlycaptcha_api_endpoint', ''),
        '#options' => [
            'global' => t('Global API-Endpoint'),
            'eu' => t('EU API-Endpoint'),
            'eu_fallback' => t('EU API-Endpoint with fallback to Global APO-Endpoint if not available'),
        ],
        '#description' => t('Select the Friendly Captcha API endpoint for your site. Both, the EU API-Endpoint (and "with fallback to Global API-Endpoint if not available") require a paid account'),
        '#required' => TRUE,
        '#title' => t('API endpoint'),
        '#type' => 'select',
    ];

    return system_settings_form($form);
}
 No newline at end of file

friendlycaptcha.info

0 → 100644
+8 −0
Original line number Diff line number Diff line
name = Friendly Captcha
description = Protect your website from spam and abuse while letting real people pass through with ease.
core = 7.x
package = Spam control
dependencies[] = captcha
dependencies[] = libraries
configure = admin/config/people/captcha/friendlycaptcha
php = 7.4
+17 −0
Original line number Diff line number Diff line
<?php

/**
 * @file
 * Installation file for FriendlyCaptcha module.
 */

/**
 * Implements hook_uninstall().
 */
function friendlycaptcha_uninstall()
{
    variable_del('friendlycaptcha_site_key');
    variable_del('friendlycaptcha_api_key');
    variable_del('friendlycaptcha_api_endpoint');
}

friendlycaptcha.module

0 → 100644
+193 −0
Original line number Diff line number Diff line
<?php

/**
 * Implements hook_help().
 */
function friendlycaptcha_help($path, $arg)
{
    switch ($path) {
        case 'admin/config/people/captcha/friendlycaptcha':
            return t('<a href="@url">FriendlyCaptcha</a> is a free and paid service to protect your website from spam and abuse.');
  }
}

/**
 * Implements hook_libraries_info().
 *
 * Defines external libraries.
 */
function friendlycaptcha_libraries_info()
{
    $libraries = array();

    $libraries['friendly-challenge'] = array(
        'name' => 'Friendlycaptcha widget',
        'version' => '0.1.0',
        'vendor url' => 'https://friendlycaptcha.com',
        'download url' => 'https://unpkg.com/friendly-challenge@0.8.11/widget.min.js',
        'files' => array(
            'js' => array(
                'widget.min.js' => array(
                    'type' => 'file',
                    'group' => JS_LIBRARY,
                    'every_page' => TRUE,
                ),
            ),
        ),
        'error message' => t('Friendlycaptcha widget library missing.'),
    );
    return $libraries;
}

/**
 * Implements hook_menu().
 */
function friendlycaptcha_menu()
{
    $items['admin/config/people/captcha/friendlycaptcha'] = array(
        'title' => 'FriendlyCaptcha',
        'description' => 'Administer the FriendlyCaptcha web service.',
        'page callback' => 'drupal_get_form',
        'page arguments' => array('friendlycaptcha_admin_settings'),
        'access arguments' => array('administer friendlycaptcha'),
        'type' => MENU_LOCAL_TASK,
        'file' => 'friendlycaptcha.admin.inc',
        'weight' => 1,
    );

    return $items;
}

/**
 * Implements hook_permission().
 */
function friendlycaptcha_permission()
{
    return array(
        'administer friendlycaptcha' => array(
            'title' => t('Administer FriendlyCaptcha'),
            'description' => t('Administer FriendlyCaptcha settings'),
        ),
    );
}

/**
 * Implements hook_captcha().
 */
function friendlycaptcha_captcha($op, $captcha_type = '')
{
    global $language;

    switch ($op) {
        case 'list':
            return array('FriendlyCaptcha');

        case 'generate':
            $captcha = array();
            if ($captcha_type == 'FriendlyCaptcha') {
                $friendlycaptcha_site_key = variable_get('friendlycaptcha_site_key', '');
                $friendlycaptcha_api_endpoint = variable_get('friendlycaptcha_api_endpoint', '');
                if ($friendlycaptcha_api_endpoint === 'eu') {
                    $friendlycaptcha_puzzle_endpoint = 'https://eu-api.friendlycaptcha.eu/api/v1/puzzle';
                } elseif ($friendlycaptcha_api_endpoint === 'eu_fallback') {
                    $friendlycaptcha_puzzle_endpoint = 'https://eu-api.friendlycaptcha.eu/api/v1/puzzle,https://api.friendlycaptcha.com/api/v1/siteverify';
                }

                // Build the FriendlyCaptcha captcha form if site_key and secret_key are
                // configured. Captcha requires TRUE to be returned in solution.
                $captcha['solution'] = TRUE;
                $captcha['captcha_validate'] = 'friendlycaptcha_captcha_validation';
                $captcha['form']['captcha_response'] = array(
                    '#type' => 'hidden',
                    '#value' => '1',
                );

                // As the validate callback does not depend on sid or solution, this
                // captcha type can be displayed on cached pages.
                $captcha['cacheable'] = TRUE;

                // Include friendlycaptcha friendly-challenge library.
                if (($library = libraries_detect('friendly-challenge')) && !empty($library['installed'])) {
                  $path = libraries_get_path('friendly-challenge');
                }
                if (!empty($path) && file_exists($path . '/widget.min.js')) {
                  $friendlycaptcha_src = $path . '/widget.min.js';
                }

                $attributes = [
                    'class' => 'frc-captcha',
                    'data-sitekey' => $friendlycaptcha_site_key,
                ];
                $attributes = array_filter($attributes);

                $captcha['form']['friendlycaptcha_widget'] = [
                    '#markup' => '<div' . $attributes . '></div>',
                    '#suffix' => t('<noscript>' . t('You need Javascript for CAPTCHA verification to submit this form.') . '</noscript>'),
                    '#attached' => [
                        'js' => [
                            $friendlycaptcha_src,
                        ],
                    ],
                ];

                $captcha['form']['friendlycaptcha_widget'] = array(
                    '#markup' => '<div' . drupal_attributes($attributes) . '></div>',
                );

                // @todo: #1664602: D7 does not yet support "async" in drupal_add_js().
                drupal_add_js(drupal_get_path('module', 'friendlycaptcha') . '/js/friendlycaptcha.setup.js', 'file');
                $data = array(
                    '#tag' => 'script',
                    '#value' => '',
                    '#attributes' => array(
                        'src' => url($friendlycaptcha_src, array('query' => array('hl' => $language->language))),
                        'async' => 'async',
                        'defer' => 'defer',
                    ),
                );
                drupal_add_html_head($data, 'friendlycaptcha_api');
            } else {
                // Fallback to Math captcha as FriendlyCaptcha is not configured.
                $captcha = captcha_captcha('generate', 'Math');
            }
    }
    return $captcha;
}

/**
 * CAPTCHA Callback; Validates the friendlycaptcha code.
 */
function friendlycaptcha_captcha_validation($solution, $response, $element, $form_state)
{
    $friendlycaptcha_site_key = variable_get('friendlycaptcha_site_key', '');
    $friendlycaptcha_api_key = variable_get('friendlycaptcha_api_key', '');
    $solution = $_POST["frc-captcha-solution"];
    if (empty($solution) || empty($friendlycaptcha_api_key)) {
        return FALSE;
    }
    $post = [
        'solution' => $solution,
        'secret' => $friendlycaptcha_api_key,
        'sitekey' => $friendlycaptcha_site_key,
    ];
    $ch = curl_init("https://api.friendlycaptcha.com/api/v1/siteverify");
    $data = 'solution=' . $solution . '&secret=' . $friendlycaptcha_api_key;

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

    $response = curl_exec($ch);
    curl_close($ch);


    $json = json_decode($response, TRUE);

    if (isset($json['success']) && $json['success'] == TRUE) {
        return TRUE;
    }
    watchdog('friendlycaptcha', '@status_code @data', ['@status_code' => $response->code, '@data' => print_r($response, TRUE)], WATCHDOG_NOTICE, $link = NULL);

    return FALSE;
}

Loading