Module: SolveMedia

Defined in:
lib/solvemedia.rb,
lib/solvemedia/railtie.rb,
lib/solvemedia/version.rb,
lib/solvemedia/constants.rb,
lib/solvemedia/view_helpers.rb,
lib/solvemedia/ad_copy_error.rb,
lib/solvemedia/controller_methods.rb

Overview

Methods for using the Solve Media service. These methods are called internally by the Rails Railtie; those not using Rails may call these methods directly.

Defined Under Namespace

Modules: ControllerMethods, ViewHelpers Classes: AdCopyError, Railtie

Constant Summary collapse

VERSION =
"1.0.1"
VERIFY_SERVER =
'http://verify.solvemedia.com'
API_SERVER =
'http://api.solvemedia.com'
API_SECURE_SERVER =
'https://api-secure.solvemedia.com'
SIGNUP_URL =
'http://portal.solvemedia.com/portal/public/signup'

Class Method Summary collapse

Class Method Details

.puzzle(ckey, options = {}) ⇒ String

Returns the HTML for the Solve Media puzzle. Can be set to use either the standard version or the AJAX version. For more complex uses of the AJAX version, such as multi-puzzle, you should not use this method and instead use purpose-written Javascript in your view.

For theme, lang, and size options, see (portal.solvemedia.com/portal/help/pub/themewiz)

For more about the AJAX puzzle, see (portal.solvemedia.com/portal/help/pub/ajax)

Parameters:

  • ckey (String)

    Your challenge (public) key

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :tabindex (Integer) — default: nil

    HTML tabindex

  • :theme (String) — default: 'purple'
  • :lang (String) — default: 'en'
  • :size (String) — default: '300x150'

    Widget size. Please note that 300x150 is the only size which can display ads.

  • :use_SSL (Boolean) — default: false

    Set to true if using the puzzle on an HTTPS site

  • :ajax (Boolean) — default: false

    Uses the AJAX api (see above)

  • :ajax_div (String)

    ID of the div element into which the puzzle is inserted, if using AJAX. Required if ajax is set to true.

Returns:

  • (String)

    HTML string containing code to display the puzzle

Raises:

  • (AdCopyError)

    if key is not set

  • (AdCopyError)

    if AJAX puzzle is selected but no container div is specified



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/solvemedia.rb', line 42

def self.puzzle(ckey, options = {})
  raise AdCopyError, "Solve Media API keys not found. Keys can be obtained at #{SIGNUP_URL}" unless ckey

  options = { :tabindex => nil,
              :theme    => 'purple',
              :lang     => 'en',
              :size     => '300x150',
              :use_SSL  => false,
              :ajax     => false
            }.merge(options)

  server = options[:use_SSL] ? SolveMedia::API_SECURE_SERVER : SolveMedia::API_SERVER
    
  if options[:ajax]
    puts options.inspect
    raise AdCopyError, "No div specified for AJAX puzzle" unless options[:ajax_div]
    aopts = {:theme => options[:theme], :lang => options[:lang], :size => options[:size]}
    aopts[:tabindex] = options[:tabindex] if options[:tabindex]

    output = <<-EOF
      <script src="#{server}/papi/challenge.ajax"></script>
      <script type="text/javascript">
        function loadSolveMediaCaptcha(){
          if(window.ACPuzzle) { 
              ACPuzzle.create('#{ckey}', '#{options[:ajax_div]}', {#{aopts.map{|k,v| "#{k}:'#{v}'" }.join(', ') }});
          } else {
              setTimeout(loadSolveMediaCaptcha, 50);
          }
        }
        loadSolveMediaCaptcha();
      </script>
    EOF
  else
    output = []
    
    output << %{<script type="text/javascript">}
    output << "	var ACPuzzleOptions = {"
    output << %{			tabindex:   #{options[:tabindex]},} unless options[:tabindex].nil?
    output << %{			theme:      '#{options[:theme]}',}
    output << %{			lang:       '#{options[:lang]}',}
    output << %{			size:       '#{options[:size]}'}
    output << "	};"
    output << %{</script>}
    
    output << %{<script type="text/javascript"}
    output << %{   src="#{server}/papi/challenge.script?k=#{ckey}">}
    output << %{</script>}

    output << %{<noscript>}
    output << %{   <iframe src="#{server}/papi/challenge.noscript?k=#{ckey}"}
    output << %{	 height="300" width="500" frameborder="0"></iframe><br/>}
    output << %{   <textarea name="adcopy_challenge" rows="3" cols="40">}
    output << %{   </textarea>}
    output << %{   <input type="hidden" name="adcopy_response"}
    output << %{	 value="manual_challenge"/>}
    output << %{</noscript>}
    output = output.join("\n")
  end
  return output
end

.verify(challenge, response, vkey, hkey, remote_ip, options = {}) ⇒ Boolean

Sends a POST request to the Solve Media server in order to verify the user’s input.

Parameters:

  • challenge (String)

    The challenge id. Normally found in the form field adcopy_challenge

  • response (String)

    The user’s response to the puzzle. Normally found in the form field acdopy_response

  • vkey (String)

    Your verification (private) key

  • hkey (String)

    Your hash key

  • remote_ip (String)

    The IP from which the form was submitted

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :validate_response (Boolean) — default: true

    Validate the response from the Solve Media server

  • :timeout (Integer) — default: 5

    Amount of time in seconds before the request should time out

Returns:

  • (Boolean)

    Was the user’s answer correct?

Raises:

  • (AdCopyError)

    if validate_response is true and the response cannot be verified

  • (Timeout::Error)

    if the request to the verification server takes longer than expected



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/solvemedia.rb', line 126

def self.verify(challenge, response, vkey, hkey, remote_ip, options = {})
  options = { :validate_response  => true,
              :timeout            => 5,
            }.merge(options)

  #disregard spam submissions
  return false if (challenge.nil? || challenge.empty? || response.nil? || challenge.nil?)
  
  #Send POST to SolveMedia
  result = nil
  Timeout::timeout(options[:timeout]) do
    result = Net::HTTP.post_form URI.parse("#{SolveMedia::VERIFY_SERVER}/papi/verify"), {
      "privatekey"  =>  vkey,  
      "challenge"   =>  challenge,
      "response"    =>  response,
      "remoteip"    =>  remote_ip
    }
  end

  answer, error, authenticator = result.body.split("\n")

  #validate the response
  if options[:validate_response] && authenticator != Digest::SHA1.hexdigest("#{answer}#{challenge}#{hkey}")
    raise AdCopyError, "SolveMedia Error: Unable to Validate Response" 
  end
  
  return answer.downcase == "true" ? true : false
end