Browse Source

Added recaptch widget

master
Artyom Beilis 12 years ago
parent
commit
384456cbdd
2 changed files with 200 additions and 0 deletions
  1. +140
    -0
      contrib/server_side/recaptcha/recaptcha.cpp
  2. +60
    -0
      contrib/server_side/recaptcha/recaptcha.h

+ 140
- 0
contrib/server_side/recaptcha/recaptcha.cpp View File

@@ -0,0 +1,140 @@
//
// Copyright (C) 2012 Artyom Beilis
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include "recaptcha.h"
#include <cppcms/http_context.h>
#include <cppcms/http_request.h>
#include <cppcms/steal_buf.h>
#include <curl/curl.h>
#include <curl/easy.h>

namespace cppcms_util {

namespace {
class curl_init{
public:
curl_init() {curl_global_init(CURL_GLOBAL_ALL);};
} init;
};

extern "C" {
static size_t cppcms_util_widget_write_function(void *ptr, size_t size, size_t nmemb, void *stream)
{
if(stream){
std::ostream *out = static_cast<std::ostream *>(stream);
out->write(static_cast<char const *>(ptr),size * nmemb);
return size*nmemb;
}
return 0;
}
}

recaptcha::~recaptcha()
{
}

recaptcha::recaptcha()
{
}

void recaptcha::private_key(std::string const &key)
{
private_ = key;
}

void recaptcha::public_key(std::string const &key)
{
public_ = key;
}




void recaptcha::load(cppcms::http::context& context)
{
response_ = context.request().post("recaptcha_response_field");
challenge_ = context.request().post("recaptcha_challenge_field");
remote_address_ = context.request().remote_addr();
}

bool recaptcha::validate()
{
CURL *curl = 0;;
CURLcode res=CURLE_OK;
cppcms::util::stackbuf<> sb;
std::ostream ss(&sb);

char const *content_type="Content-Type: application/x-www-form-urlencoded; charset=UTF-8";
std::string post_data;
post_data.reserve(256);
post_data += "privatekey=";
post_data += private_;
post_data += "&remoteip=";
post_data += cppcms::util::urlencode(remote_address_);
post_data += "&challenge=";
post_data += cppcms::util::urlencode(challenge_);
post_data += "&response=";
post_data += cppcms::util::urlencode(response_);
curl = curl_easy_init();
if(!curl)
throw booster::runtime_error("Failed to allocate CURL object");
curl_slist *headerlist = curl_slist_append(NULL,content_type);
/* what URL that receives this POST */
curl_easy_setopt(curl, CURLOPT_URL, "http://www.google.com/recaptcha/api/verify");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,cppcms_util_widget_write_function);
curl_easy_setopt(curl, CURLOPT_WRITEDATA,static_cast<void *>(&ss));
res = curl_easy_perform(curl);

/* always cleanup */
curl_easy_cleanup(curl);

/* free slist */
curl_slist_free_all (headerlist);
if(res!=CURLE_OK || strncmp(sb.c_str(),"true\n",5) != 0) {
valid(false);
return false;
}
valid(true);
return true;
}

void recaptcha::render_input(cppcms::form_context& context)
{
if(context.widget_part()!=cppcms::form_context::first_part)
return;
context.out() <<
"<script type='text/javascript' "
"src='http://www.google.com/recaptcha/api/challenge?k=" << public_ << "'></script>\n"
"<noscript>\n"
"<iframe src='http://www.google.com/recaptcha/api/noscript?k=" << public_ << "' \n"
" height='300' width='500' frameborder='0'></iframe><br>\n"
"<textarea name='recaptcha_challenge_field' rows='3' cols='40'></textarea>\n"
"<input type='hidden' name='recaptcha_response_field' value='manual_challenge'>\n"
"</noscript>\n";

}


void recaptcha::render(cppcms::form_context& context)
{
auto_generate(&context);
context.widget_part(first_part);
render_input(context);
context.widget_part(second_part);
render_input(context);

}


} // namespace cppcms_util

+ 60
- 0
contrib/server_side/recaptcha/recaptcha.h View File

@@ -0,0 +1,60 @@
//
// Copyright (C) 2012 Artyom Beilis
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef CPPCMS_UTIL_RECAPTCHA_H
#define CPPCMS_UTIL_RECAPTCHA_H

#include <cppcms/form.h>

namespace cppcms_util {
///
/// \brief Recaptcha Widget
///
/// This is a simple widgets that allows to embed recaptcha
/// into CppCMS form.
///
/// It requires linking with libcurl
///
/// In order to use add it into the form, note, you need to
/// setup both private and public keys before you use it.
///
/// Upon validation the recaptcha widget would try to acces
/// google services to perform the validation
///
/// You can check if the recaptcha result is valid by checking
/// that form validates and specifically calling recaptcha::valid()
/// after validation
///
class recaptcha : public cppcms::widgets::base_widget {
public:
recaptcha();
virtual ~recaptcha();
///
/// Set Public Key - Required
///
void public_key(std::string const &key);
///
/// Set Private Key - Required
///
void private_key(std::string const &key);

// Widget support functions
virtual void render(cppcms::form_context &context);
virtual void render_input(cppcms::form_context &context);
virtual void load(cppcms::http::context &context);
virtual bool validate();
private:
std::string public_;
std::string private_;
std::string response_;
std::string challenge_;
std::string remote_address_;
};
}

#endif

Loading…
Cancel
Save