Location: PHPKode > scripts > NuCaptcha (PHP) > nucaptcha-client-php-1.0.12882/nucaptcha-client-php-1.0.12882/php/leappublishertransaction.php
<?php
/**
 * @package   NuCaptcha PHP clientlib
 * @author    <hide@address.com> Leap Marketing Technologies Inc
 * @license   LGPL License 2.1 (see included license.txt)
 * @link      http://www.nucaptcha.com/api/php
 */

/**
 * Default transaction interface.
 */
class lmPublisherTransaction extends lmTransactionInterface
{
	/**
	 * The javascript linsk to embed
	 *
	 * @var string
	 */
	private $mLinks = "";

	/**
	 * Extra fields to send onto the javascript
	 *
	 * @var bool
	 */
	private $mExtraJavaScriptFields = false;

	/**
	 * The HTML to return in GetWidget() if there was an error
	 *
	 * @var string
	 */
	private $mHTMLOnFailure = "";

	/**
	 * Should the transaction use SSL?
	 *
	 * @var bool
	 */
	private $mUseSSL = false;

	/**
	 * the template to display to the user (2 for gif, 3 for JavaScript, 4 for Flash)
	 * @var int
	 */
	private $mTemplateSelector = null;
	
	/**
	 * the captcha pupose for this transaction.  see Leap::PURPOSE_ constants.
	 * @var int
	 */
	private $mPurpose = null;

	/**
	 * The HTML sent back from the token server
	 *
	 * @var string
	 */
	private $mHTML = "";

	/**
	 * Campaign ID to request in the TREQ
	 * @var string
	*/
	private $mCampaignProfile = null;

	/**
	 * Resource Server URL
	 * @var string
	 */
	private $mResourceServer = null;
	
	/**
	 * CSS Skin name (not path)
	 * @var string
	 */
	private $mSkin = "default";

	/**
	 * Widget language
	 * @var string
	 */
	private $mDefaultLang = null;

	/**
	 * Decodes the token from the token response from the token server, and stores some data from it
	 *
	 * @param lmTextChunkData $decoded
	 */
	protected function decodeTRESChunk(lmTextChunkData $TRES)
	{
		$this->mResourceServer			= $TRES->GetChunk("RSERV");
		if (0 == strlen($this->mHTML))
		{
			$this->mHTML				= $TRES->GetChunk("HTML");
		}
		$this->mLinks					= $TRES->GetChunk("LINKS");
		$this->mExtraJavaScriptFields	= $TRES->GetChunk("JSVALUES2");
	}

	/**
	 * GetLinks:
	 * Gets a chunk of HTML code that has a list of <script type="text/javascript" src="myscript.js"></script> blocks
	 *
	 * @return string
	 */
	public function GetLinks()
	{
		$this->CheckSocketRead();

		// should be the resource server returned by the token server
		return $this->mLinks;
	}

	public function GetTransactionID()
	{
		$this->CheckSocketRead();
		
		return lmHelper::GetIVFromToken($this->getToken());
	}

	/**
	 * GetJavascriptInternal:
	 * Gets the javascript code to run the leap stuff
	 * Should call it inline, or in the onLoad function for the document
	 * You should be able to insert the javascript code directly into a function.
	 * It will be a list of calls, like: callLeapFunction1(); callLeapFunction2();
	 * So if you're not going to embed it inside javascript of your own, you'll have to wrap it in a
	 * <script type="text/javascript"></script> block
	 *
	 * @param array $parameters - see the parent implementation of this function for more info
	 * @return string
	 */
	protected function GetJavascriptInternal($parameters)
	{
		if ($this->getStatusInfo() !== 0)
		{
			return "";
		}
		
		return $this->GenerateJavascriptFunctionCall($parameters, "lmLoadPlayer");
	}

	/**
	 * GetJavascriptParameters:
	 * Gets an array of javascript variables to reinitialize through ajax with.
	 * Called by the parent class to get the values.
	 *
	 * @return array
	 */
	protected function GetJavascriptParameters()
	{
		$this->CheckSocketRead();

		$dataRequest = $this->getDataServer();
		$token = $this->getToken();
		$resourceServer = $this->mResourceServer;
			
		$imagePath = $this->GetImagePath($resourceServer);

		$values = array();
		
		$values["dataRequest"] = $this->EscapeString($dataRequest);
		$values["token"] = $this->EscapeString($token);
		$values["resourceServer"] = $this->EscapeString($resourceServer);
		$values["w"] = 312;
		$values["h"] = 286;
		
		$values["validationFields"] = $this->CreateValidationFieldJSON();
		$values["cssSkin"] = $this->EscapeString($this->mSkin);
		
		// left over from non-css implementation
		// these can be removed when we force css
		{
			$values["skin"] = $this->EscapeString($this->GetImagePath($resourceServer));
			
			$values["webRequest"] = false;
			$values["imagePath"] = $this->EscapeString($imagePath);
			$values["showFlashVars"] = false;
			
			/*
			* LEAP-1221 - this is required until a new version of resources is up.
			* The old version still looks for skinJSON, so this is a bit of
			* backwards compatibility. Resources >= 51 should do it.
			*/
			$values["skinJSON"] = '[]';
		}

		// deal with the extra values now
		$values = $this->AppendExtraValuesFromTokenServer($values);

		// allow derived classes a shot next
		$values = $this->AppendJavascriptVariables($values);

		return $values;
	}

	/**
	 * AppendExtraValuesFromTokenServer:
	 * Appends values from the token server to the values being fed to the javascript
	 *
	 * @param array $values - the array to add values to
	 * @return array
	 */
	private function AppendExtraValuesFromTokenServer($values)
	{
		if (is_array($this->mExtraJavaScriptFields))
		{
			foreach ($this->mExtraJavaScriptFields as $k => $v)
			{
				if( is_numeric($v) )
				{
					$values[$k] = $v;
				}
				else if( is_bool($v) )
				{
					$values[$k] = $v ? "true" : "false";
				}
				else
				{
					$values[$k] = $this->EscapeString($v);
				}
			}
		}
		return $values;
	}

	/**
	 * CreateValidationFieldJSON:
	 * Takes the validation fields from the token response and creates a JSON array
	 * that the javascript can use to know what fields to send when/if the publisher writes
	 * some javascript code to get the validation field values (to do an ajax validation).
	 *
	 * @return string
	 */
	private function CreateValidationFieldJSON()
	{
		$list = $this->getResponseFieldData();
		
		$values = Array();

		foreach($list as $value)
		{
			$values[] = $this->EscapeString($value['varname']);
		}

		$fields = '[' . join(',', $values) . ']';

		return $fields;
	}

	/**
	 * Constructor:
	 * Saves the input variables for use later on in Initialize()
	 *
	 * @param $errorCallback			- a callback to call on error of some form. Should take an int and a message.
	 * @param $htmlOnFailure			- the HTML to display to the user on failure of some kind. This will be returned in GetWidget() on failure of some kind.
	 * @param bool $useSSL				- If the client uses SSL, set this to true to avoid browser warnings
	 * @param string $profile           - CampaignID/Profile to use.
	 * @param int $templateSelector     - the template to display to the user -- see TEMPLATE_* constants
	 * @param string $purpose         - a string providing information regarding the captcha usage for this transaction.  see Leap::PURPOSE_ constants.
	 * @param string $defaultLang       - widget language
	 */
	public function __construct($errorCallback, $htmlOnFailure, $useSSL = false, $campaignProfile = null, $templateSelector = null, $purpose = null, $defaultLang = Leap::LANGUAGE_ENGLISH)
	{
		// validate input
		switch ($templateSelector)
		{
			case null:
			case Leap::TEMPLATE_DEFAULT:
			case Leap::TEMPLATE_FLASHONLY:
			case Leap::TEMPLATE_JAVASCRIPTONLY:
				break;
			default:
				throw new LeapException("Invalid template selector " . $templateSelector, LMSC_INVALIDDATA);
		}
		
		switch ($purpose)
		{
			case Leap::PURPOSE_UNKNOWN;
			case Leap::PURPOSE_CREATE_ACCOUNT:
			case Leap::PURPOSE_PASSWORD_RESET:
			case Leap::PURPOSE_LOGIN:
			case Leap::PURPOSE_POST:
			case Leap::PURPOSE_COMMENT:
			case Leap::PURPOSE_EDIT:
			case Leap::PURPOSE_VOTE:
			case Leap::PURPOSE_SEND:
			case Leap::PURPOSE_ACTION:
			case Leap::PURPOSE_GENERIC:
				break;
			default:
				throw new LeapException("Invalid purpose $purpose: " . $purpose, LMSC_INVALIDDATA);
		}

		// save this for later on
		$this->mHTMLOnFailure           = $htmlOnFailure;
		$this->mUseSSL                  = $useSSL;
		$this->mCampaignProfile         = $campaignProfile;
		$this->mTemplateSelector        = $templateSelector;
		$this->mPurpose                 = $purpose;
		$this->mDefaultLang             = $defaultLang;

		$this->setErrorCallback($errorCallback);
	}

	/**
	 * @param lmTextChunk $chunk - The text chunk, with data to initialize; see derived classes for more info
	 * @param string $tokenkey - The key to send with the token request to the server, that it can encrypt messages with
	 */
	public function Initialize(lmTextChunk $treq, $tokenkey)
	{
		// save this for later
		$this->setSessionKey($tokenkey);

		$this->mAnswers = array();

		if(true === $this->mUseSSL)
		{
			$treq->AddChunk('USESSL', 1);
		}

		if (null != $this->mCampaignProfile)
		{
			$treq->AddChunk('CAID', $this->mCampaignProfile);
		}

		if (false != $this->mTemplateSelector)
		{
			$treq->AddChunk('TEMPLATE', $this->mTemplateSelector);
		}
		
		if (null != $this->mPurpose)
		{
			$treq->AddChunk('PURPOSE', $this->mPurpose);
		}

		if(null != $this->mDefaultLang)
		{
			$treq->AddChunk('DEFAULTLANG', $this->mDefaultLang);
		}
		
		if(defined('LM_PLATFORM'))
		{
			$treq->AddChunk('PLATFORM', LM_PLATFORM);
		}

		$this->sendTREQ($treq);
	}

	/**
	 * GetHTML:
	 * Gets the HTML code that needs to be embedded in a website.
	 *
	 * @param $position - How you want the player positioned.  ('left', 'center', 'right')
	 * @return string
	 */
	public function GetHTML($position = Leap::POSITION_LEFT)
	{
		$this->CheckSocketRead();

		if ($this->getStatusInfo() !== 0)
		{
			return $this->mHTMLOnFailure;
		}

		// left over from non css implementation
		// this can be removed once we force css
		{
			switch (strtolower($position))
			{
				default:
				case strtolower(Leap::POSITION_LEFT):
					return $this->mHTML;
				case strtolower(Leap::POSITION_CENTER):
					return str_replace('class="nucaptcha"', 'class="nucaptcha nucaptcha_center"', $this->mHTML);
				case strtolower(Leap::POSITION_RIGHT):
					return str_replace('class="nucaptcha"', 'class="nucaptcha nucaptcha_right"', $this->mHTML);
			}
		}
		return $this->mHTML;
	}

	/**
	 * Gets the ip address of the web user.
	 *
	 * @return string
	 */
	private function GetIpAddress()
	{
		// get the ip, for error tracking
		return $_SERVER['REMOTE_ADDR'];
	}

	/**
	 * EscapeString:
	 * Adds the quotes to a string
	 *
	 * @param string $str
	 * @return string
	 */
	protected function EscapeString($str)
	{
		return '"' . $str . '"';
	}

	/**
	 * EscapeString:
	 * Removes "'s from a string
	 *
	 * @param string $str
	 * @return string
	 */
	protected function UnescapeString($str)
	{
		if(0 === strpos($str, '"'))
		{
			$str = substr($str, 1);
		}

		if('"' == substr($str, strlen($str) - 1))
		{
			$str = substr($str, 0, strlen($str) - 1);
		}

		return $str;
	}

	/**
	 * GetJavascriptParametersInternal:
	 * Gets an array of javascript variables to initialize with.
	 *
	 * @param boolean $isFlashTransparent - true if you want to set the wmode of the Flash swf to transparent
	 * @param boolean $setFocusToAnswerBox - true if you want the text entry box on the NuCaptcha player to be focused once it's loaded
	 * @param string $position
	 * @param int $tabIndex
	 * @return array
	 */
	private function GetJavascriptParametersInternal($isFlashTransparent, $setFocusToAnswerBox, $position, $tabIndex=null)
	{
		$parameters = $this->GetJavascriptParameters();
		
		$parameters["isTransparent"] = $isFlashTransparent;
		$parameters["highlightAnswerBox"] = $setFocusToAnswerBox;
		$parameters["tabIndex"] = $tabIndex === null ? -1 : intval($tabIndex);
		$parameters["position"] = $this->EscapeString($position);
		$parameters["language"] = $this->EscapeString(strtoupper($this->mDefaultLang));

		// get the ip, for error tracking
		$parameters['ipAddress'] = $this->EscapeString($this->GetIpAddress());

		
		return $parameters;
	}

	/**
	 * Gets the javascript code to run the leap stuff.
	 *
	 * Should call it inline, or in the onLoad function for the document You should be able to insert the javascript code directly into a function.
	 * It will be a list of calls, like: callLeapFunction1(); callLeapFunction2();
	 *
	 * So if you're not going to embed it inside javascript of your own, you'll have to wrap it in a <script type="text/javascript"></script> block
	 *
	 * @param boolean $isFlashTransparent - true if you want to set the wmode of the Flash swf to transparent
	 * @param boolean $setFocusToAnswerBox - true if you want the text entry box on the NuCaptcha player to be focused once it's loaded
	 * @param string $position - One of Leap::POSITION_LEFT, Leap::POSITION_RIGHT or Leap::POSITION_CENTER. Default is LEFT.
	 * @return string
	 */
	public function GetJavascript($isFlashTransparent = false,
								  $setFocusToAnswerBox = false,
								  $position = Leap::POSITION_LEFT)
	{
		$parameters = $this->GetJavascriptParametersInternal($isFlashTransparent, $setFocusToAnswerBox, $position);

		return $this->GetJavascriptInternal($parameters);
	}



	/**
	 * Gets the javascript code to reinitialize the players with a new token.
	 *
	 * Used to do ajax submits, without having to do submit on a form.
	 * Returns a javascript block of code that can be eval'd.
	 *
	 * @param boolean $isFlashTransparent - true if you want to set the wmode of the Flash swf to transparent
	 * @param boolean $setFocusToAnswerBox - true if you want the text entry box on the NuCaptcha player to be focused once it's loaded
	 * @param string $position - One of Leap::POSITION_LEFT, Leap::POSITION_RIGHT or Leap::POSITION_CENTER. Default is LEFT.
	 * @return string
	 */
	public function GetJavascriptToReinitialize($isFlashTransparent = false,
												$setFocusToAnswerBox = false,
												$position = Leap::POSITION_LEFT)
	{
		$parameters = $this->GetJavascriptParametersInternal($isFlashTransparent, $setFocusToAnswerBox, $position);

		return $this->GetJavascriptToReinitializeInternal($parameters);
	}

	/**
	 * Derived classes should override this function instead of GetJavascriptToReinitialize.
	 *
	 * Gets the javascript code to reinitialize the players with a new token.
	 * Used to do ajax submits, without having to do submit on a form.
	 * Returns a javascript block of code that can be eval'd.
	 *
	 * @param array $parameters - see GetJavascriptToReinitializeInternal for a description of all of the name/value pairs that go into this array
	 * @return string
	 */
	public function GetJavascriptToReinitializeInternal($parameters)
	{
		return $this->GenerateJavascriptReinitializeCall($parameters);
	}

	/**
	 * Returns of the javascript function to call to reinitialize the leap player, using the json object returned from GetJSONToReinitialize().
	 *
	 * @return string
	 */
	public function GetJavascriptReinitializeFunctionName()
	{
		return "lmReinitializePlayer";
	}

	/**
	 * Gets the json object (as a string) to send (in javascript) to call the reinitialize function.
	 *
	 * To get the reinitialize function name, call GetJavascriptReinitializeFunctionName.
	 * Used to do ajax submits, without having to do submit on a form.
	 * Returns a javascript (json) encoded object.
	 *
	 * You can send in extra items to embed in the JSON object returned. The key's of the $extraParameters
	 * variable will be used as the names of the items in the JSON object, and the values will be the values.
	 * Note that you have to properly escape strings. So you'd have to do the following:
	 *
	 * $t->GetJSONToReinitialize(array("aString"=>"\"some string data\""));
	 *
	 * If you don't properly escape the string, then when the JSON object is used (or eval'd) in Javascript, it won't parse properly.
	 *
	 * @param array $extraParameters - hash table of extra parameters to put in the JSON
	 * @param boolean $isFlashTransparent - true if you want to set the wmode of the Flash swf to transparent
	 * @param boolean $setFocusToAnswerBox - true if you want the text entry box on the NuCaptcha player to be focused once it's loaded
	 * @param string $position - One of Leap::POSITION_LEFT, Leap::POSITION_RIGHT or Leap::POSITION_CENTER. Default is LEFT.
	 * @return string
	 */
	public function GetJSONToReinitialize($extraParameters = null,
										  $isFlashTransparent = false,
										  $setFocusToAnswerBox = false,
										  $position = Leap::POSITION_LEFT)
	{
		$parameters = $this->GetJavascriptParametersInternal($isFlashTransparent, $setFocusToAnswerBox, $position);

		if (($extraParameters != null) && (is_array($extraParameters)))
		{
			foreach ($extraParameters as $key => $value)
			{
				$parameters[$key] = $value;
			}
		}

		return $this->GenerateJSON($parameters);
	}

	/**
	 * Gets everything and can be embedded into the html page.
	 *
	 * Derived classes should override GetWidgetInternal, not this function. That way when new parameters are added, the derived classes won't have to be changed
	 *
	 * @param boolean $isFlashTransparent - true if you want to set the wmode of the Flash swf to transparent
	 * @param boolean $setFocusToAnswerBox - true if you want the text entry box on the NuCaptcha player to be focused once it's loaded
	 * @param string $position - One of Leap::POSITION_LEFT, Leap::POSITION_RIGHT or Leap::POSITION_CENTER. Default is LEFT.
	 * @param string $lang - deprecated, set language in InitializeTransaction instead.
	 * @param string $skin - CSS skin to use. Enterprise customers only.
	 * @return string
	 */
	public function GetWidget($isFlashTransparent = false,
							  $setFocusToAnswerBox = false,
							  $position = Leap::POSITION_LEFT,
							  $lang = Leap::LANGUAGE_ENGLISH,
							  $skin='default',
							  $tabIndex=null)
	{
		$this->mSkin = $skin;
		
		$parameters = $this->GetJavascriptParametersInternal(
				$isFlashTransparent,
				$setFocusToAnswerBox,
				$position,
				$tabIndex
		);

		$this->CheckSocketRead();

		$begin = '<!-- NuCaptcha Start - PHP ' . Leap::GetVersion() . ' -->';
		$end = '<!-- NuCaptcha End -->';
		if ($this->getStatusCode() !== false)
		{
			if( is_string($this->mHTMLOnFailure) )
			{
				return $begin . $this->mHTMLOnFailure . $end;
			}
			return $begin . $this->GetErrorHTML($this->getStatusCode()) . $end;
		}

		return $begin . $this->GetWidgetInternal($parameters, $skin) . $end;
	}

	/**
	 * GetWidgetInternal:
	 * Derived classes should override this if need be, as opposed to GetWidget.
	 *
	 * @param array $parameters - see GetWidget for a description of all of the name/value pairs that go into this array
	 * @return string
	 */
	protected function GetWidgetInternal($parameters)
	{	
		$widget = "";
		$widget .= $this->GetLinks() . "\n";
		$widget .= $this->GetHTML($this->UnescapeString($parameters["position"])) . "\n";
		$widget .= '<script type="text/javascript">' . "\n";
		$widget .= $this->GetJavascriptInternal($parameters) . "\n";
		$widget .= '</script>'  . "\n";

		return $widget;
	}

	/**
	 * GetErrorHTML:
	 * Given a status code, returns a string of HTML to display to the user
	 *
	 * @param int $statusCode - the error code to put in the email that the user will send to support
	 * @return string
	 */
	protected function GetErrorHTML($errorCode)
	{
		$linkText = 'An error occurred. Click here to report the problem. Please tell us what happened so we can improve our system.';
		$emailAddr = 'hide@address.com';
		$emailSubject = 'NuCaptcha Error: '. $errorCode;
		$emailBody = "Please provide brief description of the error that occured here.\n\n====== DETAILS ======\n";
		$emailDetails = Array();
		$emailDetails['IP Address'] = $this->GetIpAddress();
		$emailDetails['PublisherID'] = "Unknown";
		$key = Leap::GetClientKey();
		if(null != $key)
		{
			try
			{
				$emailDetails['PublisherID'] = $key->GetChunk('CID');
			}
			catch(Exception $e)
			{
			}
		}
		$emailDetails['ClientLib'] = 'PHP ' . Leap::GetVersion();
		$emailDetails['Timestamp'] = date('D, d M y H:i:s O'); // DATE_RFC822

		// Append details to body
		foreach( $emailDetails as $k => $v )
		{
			$emailBody .= $k . ':' . $v . "\n";
		}

		$html = '<div class="error" style="width:300px">';

		$html .= '<a href="mailto:'.$emailAddr.'?subject='.rawurlencode($emailSubject).'&body='.rawurlencode($emailBody).'">';
		$html .= $linkText;
		$html .= '</a>';
		$html .= '</div>';
		return $html;
	}

	/**
	 * GetImagePath:
	 * Gets the path to the image resources, on a resource server
	 *
	 * @param binary $resourcesServer - The url to retrieve from
	 * @return string - the full path to the image resources for our skin
	 */
	protected function GetImagePath($resourceServer)
	{
		return $resourceServer . "images/player/leap/";
	}

	/**
	 * GenerateJavascriptCall:
	 * Returns the javascript call, based on the parameters
	 *
	 * @param array $parameters		- the list of variables to pass as the data object in the javascript
	 * @return string				- the code to call the javascript
	 */
	protected function GenerateJavascriptCall($parameters)
	{
		return $this->GenerateJavascriptFunctionCall($parameters, "lmLoadPlayer");
	}

	/**
	 * GenerateJavascriptReinitializeCall:
	 * Returns the javascript call to reinitialize, based on the parameters
	 *
	 * @param array $parameters		- the list of variables to pass as the data object in the javascript
	 * @return string				- the code to call the javascript
	 */
	protected function GenerateJavascriptReinitializeCall($parameters)
	{
		return $this->GenerateJavascriptFunctionCall($parameters, $this->GetJavascriptReinitializeFunctionName());
	}

	/**
	 * GenerateJSON:
	 * Generates a JSON object, with each member mapping to the parameter array passed in
	 *
	 * @param array $parameters		- the list of variables to pass as the data object in the javascript
	 * @return string				- the JSON object
	 */
	protected function GenerateJSON($parameters)
	{
		$ret = "";
		$ret .= "{";

		$index = 0;
		foreach ($parameters as $name => $value)
		{
			if ($index > 0)
			{
				$ret .= ", ";
			}

			$ret .= "\"$name\":";
			if (is_int($value) || is_float($value))
			{
				$ret .= "$value";
			}
			else if (is_bool($value))
			{
				$ret .= ($value === true) ? "true" : "false";
			}
			else
			{
				$ret .= $value;
			}
			$index++;
		}

		$ret .= "}\n";

		return $ret;
	}

	/**
	 * GenerateJavascriptFunctionCall:
	 * Helper function to take a list of name/value pairs and create a javascript object (JSON) to
	 * send to the function call javascript method
	 *
	 * @param array $parameters - name/value pairs to insert in the JSON object
	 * @param string $functionCall - the name of the function to call
	 * @return string - the javascript to call from the inputs
	 */
	private function GenerateJavascriptFunctionCall($parameters, $functionCall)
	{
		$ret = "";
		$ret .= "\tvar data = ";
		$ret .= $this->GenerateJSON($parameters);
		$ret .= ";\n";
		$ret .= "\t$functionCall(data);\n";

		return $ret;
	}


	public function GetPersistentData()
	{
		$this->CheckSocketRead();

		if ( $this->transactionFailed() )
		{
			return lmTransactionError::getTransactionErrorPersistentData($this->getStatusCode());
		}

		return parent::GetPersistentData();
	}

	/**
	 * AppendJavascriptVariables:
	 * Default null implementation of this method, which derived classes call
	 *
	 * @param array $values - name/value pairs to append to
	 * @return array - the values array
	 */
	protected function AppendJavascriptVariables($values)
	{
		return $values;
	}
}
Return current item: NuCaptcha (PHP)