diff --git a/README.md b/README.md index 1e40abd..ef30609 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ captcha_module -Contrib module contaning captcha logic. +Contrib module containing captcha logic. diff --git a/controllers/oecaptchacontact.php b/controllers/oecaptchacontact.php new file mode 100644 index 0000000..b9af7d9 --- /dev/null +++ b/controllers/oecaptchacontact.php @@ -0,0 +1,44 @@ +getCaptcha()->passCaptcha()) { + return false; + } + + return parent::send(); + } + + /** + * Template variable getter. Returns object of handling CAPTCHA image + * + * @return object + */ + public function getCaptcha() + { + if ($this->captcha === null) { + $this->captcha = oxNew('oeCaptcha'); + } + + return $this->captcha; + } + +} diff --git a/controllers/oecaptchadetails.php b/controllers/oecaptchadetails.php new file mode 100644 index 0000000..a2056e3 --- /dev/null +++ b/controllers/oecaptchadetails.php @@ -0,0 +1,52 @@ +getCaptcha()->passCaptcha(false)) { + $this->_iPriceAlarmStatus = 2; + return; + } + + return parent::addme(); + } + + /** + * Template variable getter. Returns object of handling CAPTCHA image + * + * @return object + */ + public function getCaptcha() + { + if ($this->captcha === null) { + $this->captcha = oxNew('oeCaptcha'); + } + return $this->captcha; + } +} diff --git a/controllers/oecaptchainvite.php b/controllers/oecaptchainvite.php new file mode 100644 index 0000000..f849ec9 --- /dev/null +++ b/controllers/oecaptchainvite.php @@ -0,0 +1,49 @@ +getCaptcha()->passCaptcha()) { + return false; + } + + return parent::send(); + } + + /** + * Template variable getter. Returns object of handling CAPTCHA image + * + * @return object + */ + public function getCaptcha() + { + if ($this->captcha === null) { + $this->captcha = oxNew('oeCaptcha'); + } + + return $this->captcha; + } + +} diff --git a/controllers/oecaptchapricealarm.php b/controllers/oecaptchapricealarm.php new file mode 100644 index 0000000..ddea7eb --- /dev/null +++ b/controllers/oecaptchapricealarm.php @@ -0,0 +1,37 @@ + pricealarm. + */ +class oeCaptchaPricealarm extends oeCaptchaPricealarm_parent +{ + /** + * Validates email + * address. If email is wrong - returns false and exits. If email + * address is OK - creates prcealarm object and saves it + * (oxpricealarm::save()). Sends pricealarm notification mail + * to shop owner. + * + * @return bool false on error + */ + public function addme() + { + //control captcha + $captcha = oxNew('oeCaptcha'); + if (!$captcha->passCaptcha(false)) { + $this->_iPriceAlarmStatus = 2; + + return; + } + + return parent::addme(); + } +} diff --git a/controllers/oecaptchasuggest.php b/controllers/oecaptchasuggest.php new file mode 100644 index 0000000..73d1db8 --- /dev/null +++ b/controllers/oecaptchasuggest.php @@ -0,0 +1,52 @@ +editval, error + * + * @return null + */ + public function send() + { + // spam spider prevension + if (!$this->getCaptcha()->passCaptcha()) { + return false; + } + + return parent::send(); + } + + /** + * Template variable getter. Returns object of handling CAPTCHA image + * + * @return object + */ + public function getCaptcha() + { + if ($this->captcha === null) { + $this->captcha = oxNew('oeCaptcha'); + } + + return $this->captcha; + } +} diff --git a/core/oecaptcha.php b/core/oecaptcha.php new file mode 100644 index 0000000..88ef8b8 --- /dev/null +++ b/core/oecaptcha.php @@ -0,0 +1,234 @@ +text) { + $this->text = ''; + for ($i = 0; $i < $this->macLength; $i++) { + $this->text .= strtolower($this->macChars{rand(0, strlen($this->macChars) - 1)}); + } + } + + return $this->text; + } + + /** + * Returns text hash + * + * @param string $text User supplie text + * + * @return string + */ + public function getHash($text = null) + { + // inserting captcha record + $time = time() + $this->timeout; + $textHash = $this->getTextHash($text); + + // if session is started - storing captcha info here + $session = $this->getSession(); + if ($session->isSessionStarted()) { + $hash = oxUtilsObject::getInstance()->generateUID(); + $hashArray = $session->getVariable('captchaHashes'); + $hashArray[$hash] = array($textHash => $time); + $session->setVariable('captchaHashes', $hashArray); + } else { + $database = oxDb::getDb(); + $query = "insert into oecaptcha (oxhash, oxtime) values (" . + $database->quote($textHash) . ", " . $database->quote($time) . ")"; + $database->execute($query); + $hash = $database->getOne('select LAST_INSERT_ID()', false, false); + } + + return $hash; + } + + /** + * Returns given string captcha hash + * + * @param string $text string to hash + * + * @return string + */ + public function getTextHash($text) + { + if (!$text) { + $text = $this->getText(); + } + $text = strtolower($text); + + return md5('ox' . $text); + } + + /** + * Returns url to CAPTCHA image generator. + * + * @return string + */ + public function getImageUrl() + { + $url = $this->getConfig()->getCurrentShopUrl() . 'modules/oe/captcha/core/utils/verificationimg.php?e_mac='; + $key = $this->getConfig()->getConfigParam('oecaptchakey'); + $key = empty($key) ? null : $key; + $url .= oxRegistry::getUtils()->strMan($this->getText(), $key); + + return $url; + } + + /** + * Checks if image could be generated + * + * @return bool + */ + public function isImageVisible() + { + return ((function_exists('imagecreatetruecolor') || function_exists('imagecreate')) && $this->getConfig()->getConfigParam('iUseGDVersion') > 1); + } + + /** + * Check if captcha is passed. + * + * @return bool + */ + public function passCaptcha($displayError = true) + { + $return = true; + + // spam spider prevention + $mac = $this->getConfig()->getRequestParameter('c_mac'); + $macHash = $this->getConfig()->getRequestParameter('c_mach'); + + if (!$this->pass($mac, $macHash)) { + $return = false; + } + + if (!$return && $displayError) { + // even if there is no exception, use this as a default display method + oxRegistry::get('oxUtilsView')->addErrorToDisplay('MESSAGE_WRONG_VERIFICATION_CODE'); + } + + return $return; + } + + /** + * Verifies captcha input vs supplied hash. Returns true on success. + * + * @param string $mac User supplied text + * @param string $macHash Generated hash + * + * @return bool + */ + protected function pass($mac, $macHash) + { + $time = time(); + $hash = $this->getTextHash($mac); + $pass = $this->passFromSession($macHash, $hash, $time); + + // if captcha info was NOT stored in session + if ($pass === null) { + $pass = $this->passFromDb((int) $macHash, $hash, $time); + } + + return (bool) $pass; + } + + /** + * Checks for session captcha hash validity + * + * @param string $macHash hash key + * @param string $hash captcha hash + * @param int $time check time + * + * @return bool + */ + protected function passFromSession($macHash, $hash, $time) + { + $pass = null; + $session = $this->getSession(); + + if (($hashArray = $session->getVariable('captchaHashes'))) { + $pass = (isset($hashArray[$macHash][$hash]) && $hashArray[$macHash][$hash] >= $time) ? true : false; + unset($hashArray[$macHash]); + if (!empty($hashArray)) { + $session->setVariable('captchaHashes', $hashArray); + } else { + $session->deleteVariable('captchaHashes'); + } + } + + return $pass; + } + + /** + * Checks for DB captcha hash validity + * + * @param int $macHash hash key + * @param string $hash captcha hash + * @param int $time check time + * + * @return bool + */ + protected function passFromDb($macHash, $hash, $time) + { + $database = oxDb::getDb(); + $where = "where oxid = " . $database->quote($macHash) . " and oxhash = " . $database->quote($hash); + $query = "select 1 from oecaptcha " . $where; + $pass = (bool) $database->getOne($query, false, false); + + if ($pass) { + // cleanup + $query = "delete from oecaptcha " . $where; + $database->execute($query); + } + + // garbage cleanup + $query = "delete from oecaptcha where oxtime < $time"; + $database->execute($query); + + return $pass; + } + +} diff --git a/core/oecaptchaevents.php b/core/oecaptchaevents.php new file mode 100644 index 0000000..948dce1 --- /dev/null +++ b/core/oecaptchaevents.php @@ -0,0 +1,62 @@ +execute($query); + + } + + /** + * Remove table oecaptcha. + * NOTE: table oecaptcha contains temporary data if any and can be + * removed without side effects on module deactivation + */ + public static function removeCaptchaTable() + { + $query = "DROP TABLE IF EXISTS `oecaptcha`"; + + oxDb::getDb()->execute($query); + } + + /** + * Execute action on activate event + * + * @return null + */ + public static function onActivate() + { + self::addCaptchaTable(); + } + + /** + * Execute action on deactivate event + * + * @return null + */ + public static function onDeactivate() + { + self::removeCaptchaTable(); + } +} diff --git a/core/utils/verificationimg.php b/core/utils/verificationimg.php new file mode 100644 index 0000000..b47a476 --- /dev/null +++ b/core/utils/verificationimg.php @@ -0,0 +1,106 @@ +getConfigParam('oecaptchakey'); + + if (empty($key)) { + $key = getOxConfKey(); + } + + return $decryptor->decrypt($value, $key); + } +} + +if (!function_exists('getOxConfKey')) { + + /** + * Get default config key. + * + * @return string + */ + function getOxConfKey() + { + $fileName = getShopBasePath() . '/core/oxconfk.php'; + $configFile = new oxConfigFile($fileName); + + return $configFile->getVar("sConfigKey"); + } + +} + +$mac = strRem($emac); +generateVerificationImg($mac); diff --git a/docs/README.txt b/docs/README.txt new file mode 100755 index 0000000..5400211 --- /dev/null +++ b/docs/README.txt @@ -0,0 +1,36 @@ +==Title== +OE Captcha + +==Author== +OXID eSales AG + +==Prefix== +oe + +==Shop Version== +6.x + +==Version== +1.0.0 + +==Link== +http://www.oxid-esales.com/ + +==Mail== + + +==Description== +OE Captcha Module + +==Installation== +Activate the module in administration area. + +==Extend== + + +==Modules== + +==Modified original templates== + +==Uninstall== +Disable the module in administration area and delete module folder. diff --git a/metadata.php b/metadata.php new file mode 100755 index 0000000..9d7b722 --- /dev/null +++ b/metadata.php @@ -0,0 +1,63 @@ + 'oecaptcha', + 'title' => array( + 'de' => 'Simple Captcha', + 'en' => 'Simple Captcha', + ), + 'description' => array( + 'de' => 'OXID eSales Simple Captcha Module', + 'en' => 'OXID eSales Simple Captcha Module', + ), + 'thumbnail' => 'out/pictures/picture.png', + 'version' => '1.0.0', + 'author' => 'OXID eSales AG', + 'url' => 'http://www.oxid-esales.com/', + 'email' => '', + 'extend' => array('details' => 'oe/captcha/controllers/oecaptchadetails', + 'contact' => 'oe/captcha/controllers/oecaptchacontact', + 'invite' => 'oe/captcha/controllers/oecaptchainvite', + 'pricealarm' => 'oe/captcha/controllers/oecaptchapricealarm', + 'suggest' => 'oe/captcha/controllers/oecaptchasuggest'), + 'files' => array( + 'oecaptcha' => 'oe/captcha/core/oecaptcha.php', + 'oecaptchaEvents' => 'oe/captcha/core/oecaptchaevents.php', + ), + 'templates' => array(), + 'blocks' => array( + array('template' => 'form/contact.tpl', 'block'=>'captcha_form', 'file'=>'/views/blocks/captcha_form.tpl'), + array('template' => 'form/invite.tpl', 'block'=>'captcha_form', 'file'=>'/views/blocks/captcha_form.tpl'), + array('template' => 'form/pricealarm.tpl', 'block'=>'captcha_form', 'file'=>'/views/blocks/captcha_form.tpl'), + array('template' => 'form/suggest.tpl', 'block'=>'captcha_form', 'file'=>'/views/blocks/captcha_form.tpl'), + ), + 'settings' => array( + array('group' => 'main', 'name' => 'oecaptchakey', 'type' => 'str', 'value' => ''), + ), + 'events' => array( + 'onActivate' => 'oecaptchaevents::onActivate', + 'onDeactivate' => 'oecaptchaevents::onDeactivate' + ), +); diff --git a/out/pictures/picture.png b/out/pictures/picture.png new file mode 100755 index 0000000..3818857 Binary files /dev/null and b/out/pictures/picture.png differ diff --git a/tests/unit/CaptchaTestCase.php b/tests/unit/CaptchaTestCase.php new file mode 100644 index 0000000..b378e19 --- /dev/null +++ b/tests/unit/CaptchaTestCase.php @@ -0,0 +1,40 @@ +execute($query); + } + + /** + * Fixture set up. + */ + protected function tearDown() + { + $query = "DROP TABLE `oecaptcha`"; + oxDb::getDb()->execute($query); + + parent::tearDown(); + } + +} diff --git a/tests/unit/core/oecaptchaEventsTest.php b/tests/unit/core/oecaptchaEventsTest.php new file mode 100644 index 0000000..d527557 --- /dev/null +++ b/tests/unit/core/oecaptchaEventsTest.php @@ -0,0 +1,59 @@ +execute("DROP TABLE IF EXISTS `oecaptcha`"); + } + + /** + * Tear down the fixture. + */ + public function tearDown() + { + oeCaptchaEvents::addCaptchaTable(); + + parent::tearDown(); + } + + /** + * Test onActivate event. + */ + public function testOnActivate() + { + oeCaptchaEvents::onActivate(); + + $oDbMetaDataHandler = oxNew('oxDbMetaDataHandler'); + + //If session is not available, table oecaptcha is where captcha information is stored + $this->assertTrue($oDbMetaDataHandler->tableExists('oecaptcha')); + + } + + /** + * Test onActivate event. + */ + public function testOnDeactivate() + { + oeCaptchaEvents::onDeactivate(); + + $oDbMetaDataHandler = oxNew('oxDbMetaDataHandler'); + + //If session is not available, table oecaptcha is where captcha information is stored + $this->assertFalse($oDbMetaDataHandler->tableExists('oecaptcha')); + + } + +} diff --git a/tests/unit/core/oecaptchaTest.php b/tests/unit/core/oecaptchaTest.php new file mode 100644 index 0000000..fb7bd44 --- /dev/null +++ b/tests/unit/core/oecaptchaTest.php @@ -0,0 +1,230 @@ +captcha = $this->getProxyClass('oecaptcha'); + } + + /** + * oeCaptcha::getText() test case + */ + public function testGetText() + { + $this->assertNull($this->captcha->getNonPublicVar('text')); + $sText = $this->captcha->getText(); + $this->assertEquals($sText, $this->captcha->getNonPublicVar('text')); + $this->assertEquals(5, strlen($sText)); + } + + /** + * oeCaptcha::getTextHash() test case + */ + public function testGetTextHash() + { + $this->assertEquals('c4b961848aeff4d9b083fe15a56c9bd0', $this->captcha->getTextHash('test1')); + } + + /** + * oeCaptcha::getHash() test case + */ + public function testGetHashNoSession() + { + $session = $this->getMock('oxSession', array('isSessionStarted')); + $session->expects($this->once())->method('isSessionStarted')->will($this->returnValue(false)); + + $captcha = $this->getMock('oeCaptcha', array('getSession')); + $captcha->expects($this->once())->method('getSession')->will($this->returnValue($session)); + + $hash = $captcha->getHash('test'); + $this->assertEquals(oxDb::getDb()->getOne('select LAST_INSERT_ID()', false, false), $hash); + } + + /** + * oeCaptcha::getHash() test case + * #0004286 adding case for multiple hashes + */ + public function testGetHashSession() + { + $session = $this->getMock('oxSession', array('isSessionStarted')); + $session->expects($this->exactly(2))->method('isSessionStarted')->will($this->returnValue(true)); + + $captcha = $this->getMock('oeCaptcha', array('getSession')); + $captcha->expects($this->exactly(2))->method('getSession')->will($this->returnValue($session)); + $hash1 = $captcha->getHash('test1'); + $hash2 = $captcha->getHash('test2'); + + $captchaHash = oxRegistry::getSession()->getVariable('captchaHashes'); + $this->assertNotNull($captchaHash); + $this->assertTrue(isset($captchaHash[$hash1])); + $this->assertTrue(isset($captchaHash[$hash2])); + } + + /** + * oeCaptcha::getImageUrl() test case + */ + public function testGetImageUrl() + { + $this->setConfigParam('oecaptchakey', 'someTestCaptchaKey'); + $this->captcha->setNonPublicVar('text', 'test1'); + $expected = $this->getConfig()->getShopUrl() . 'modules/oe/captcha/core/utils/verificationimg.php?e_mac=ox_MAsbCBYgVBoQ'; + + $this->assertEquals($expected, $this->captcha->getImageUrl()); + } + + /** + * oeCaptcha::getImageUrl() test case if sCaptcha key is not set + */ + public function testGetImageUrlFallbackKey() + { + $this->setConfigParam('oecaptchakey', ''); + $this->captcha->setNonPublicVar('text', 'test1'); + + $expected = $this->getConfig()->getShopUrl() . 'modules/oe/captcha/core/utils/verificationimg.php?e_mac=ox_MB4FUUYlYlld'; + $this->assertEquals($expected, $this->captcha->getImageUrl()); + } + + /** + * oeCaptcha::isImageVisible() test case + */ + public function testIsImageVisible() + { + $this->assertTrue($this->captcha->isImageVisible()); + } + + /** + * oeCaptcha::isImageVisible() test case + */ + public function testIsImageVisibleLowGD() + { + $this->getConfig()->setConfigParam('iUseGDVersion', 0); + $this->assertFalse($this->captcha->isImageVisible()); + } + + /** + * oeCaptcha::pass() test case + */ + public function testDbPassCorrect() + { + $captcha = $this->getMock('oeCaptcha', array('passFromSession')); + $captcha->expects($this->once())->method('passFromSession')->will($this->returnValue(null)); + + // reseting session + $session = oxNew('oxSession'); + $captcha->setSession($session); + + $captcha->getHash('3at8u'); + $hash = oxDb::getDb()->getOne('select LAST_INSERT_ID()', false, false); + $this->assertTrue($captcha->pass('3at8u', $hash)); + } + + /** + * oeCaptcha::pass() test case + */ + public function testDbPassFail() + { + $captcha = $this->getMock('oeCaptcha', array('passFromSession')); + $captcha->expects($this->once())->method('passFromSession')->will($this->returnValue(null)); + + $this->assertFalse($captcha->pass('3at8v', 'd9a470912b222133fb913da36c0f50d0')); + } + + /** + * oeCaptcha::pass() test case + * #0004286 adding case for multiple hashes + */ + public function testSessionPassCorrect() + { + $mac1 = '3at8u'; + $mac2 = '3at8u'; + $hash1 = 1234; + $hash2 = 1235; + + $captcha = oxNew('oeCaptcha'); + $hash = array( + $hash1 => array($captcha->getTextHash($mac1) => time() + 3600), + $hash2 => array($captcha->getTextHash($mac2) => time() + 3600) + ); + $session = $this->getSession(); + $session->setVariable('captchaHashes', $hash); + + $captcha = $this->getMock('oeCaptcha', array('passFromDb')); + $captcha->expects($this->never())->method('passFromDb'); + + $this->assertTrue($captcha->pass($mac1, $hash1)); + $this->assertEquals(1, count($session->getVariable('captchaHashes'))); + + $this->assertTrue($captcha->pass($mac2, $hash2)); + $this->assertNull($session->getVariable('captchaHashes')); + } + + /** + * oeCaptcha::pass() test case + */ + public function testSessionPassFail() + { + $this->getSession()->setVariable('captchaHashes', array('testHash' => array('testTextHash' => 132))); + + $captcha = $this->getMock('oeCaptcha', array('passFromDb')); + $captcha->expects($this->never())->method('passFromDb'); + + $this->assertFalse($captcha->pass('3at8v', 'd9a470912b222133fb913da36c0f50d0')); + } + + /** + * Test passing captcha. + */ + public function testPassCaptchaYes() + { + $captcha = $this->getMock('oeCaptcha', array('pass')); + $captcha->expects($this->once())->method('pass')->will($this->returnValue(true)); + + $result = $captcha->passCaptcha(); + $this->assertTrue($result); + } + + /** + * Test not passing captcha. + */ + public function testPassCaptchaNo() + { + $utilsView = $this->getMock('oxUtilsView', array('addErrorToDisplay')); + $utilsView->expects($this->once())->method('addErrorToDisplay')->with($this->equalTo('MESSAGE_WRONG_VERIFICATION_CODE')); + oxRegistry::set('oxUtilsView', $utilsView); + + $captcha = $this->getMock('oeCaptcha', array('pass')); + $captcha->expects($this->once())->method('pass')->will($this->returnValue(false)); + + $result = $captcha->passCaptcha(); + $this->assertFalse($result); + } + + /** + * Test not passing captcha without displaying error message. + */ + public function testPassCaptchaNoWithoutDisplayMessage() + { + $utilsView = $this->getMock('oxUtilsView', array('addErrorToDisplay')); + $utilsView->expects($this->never())->method('addErrorToDisplay'); + oxRegistry::set('oxUtilsView', $utilsView); + + $captcha = $this->getMock('oeCaptcha', array('pass')); + $captcha->expects($this->once())->method('pass')->will($this->returnValue(false)); + + $result = $captcha->passCaptcha(false); + $this->assertFalse($result); + } +} diff --git a/tests/unit/views/contactTest.php b/tests/unit/views/contactTest.php new file mode 100644 index 0000000..e33988f --- /dev/null +++ b/tests/unit/views/contactTest.php @@ -0,0 +1,150 @@ +deleteVariable('Errors'); + + $params['oxuser__oxusername'] = 'aaaa@aaa.com'; + $this->setRequestParameter('editval', $params); + $contact = oxNew('Contact'); + + $this->assertFalse($contact->send()); + + //checking if warning was added to errors list + $message = oxRegistry::getLang()->translateString('MESSAGE_WRONG_VERIFICATION_CODE'); + $errors = oxRegistry::getSession()->getVariable('Errors'); + $error = unserialize($errors['default'][0]); + + $this->assertEquals($message, $error->getOxMessage()); + } + + /** + * Test if send mail is not executed if user data is not entered + * and warning message is displayed + */ + public function testSaveWithoutUserData() + { + oxRegistry::getSession()->deleteVariable('Errors'); + oxTestModules::addFunction('oeCaptcha', 'pass', '{return true;}'); + + $params['oxuser__oxusername'] = 'aaaa@aaa.com'; + $this->setRequestParameter('editval', $params); + $contact = oxNew('Contact'); + + $this->assertFalse($contact->send()); + + //checking if warning was added to errors list + $message = oxRegistry::getLang()->translateString('ERROR_MESSAGE_INPUT_NOTALLFIELDS'); + $errors = oxRegistry::getSession()->getVariable('Errors'); + $error = unserialize($errors['default'][0]); + + $this->assertEquals($message, $error->getOxMessage()); + } + + /** + * Test send mail + */ + public function testSave() + { + oxTestModules::addFunction('oeCaptcha', 'pass', '{return true;}'); + oxTestModules::addFunction('oxemail', 'sendContactMail', '{return true;}'); + + $params['oxuser__oxusername'] = 'aaaa@aaa.com'; + $params['oxuser__oxfname'] = 'first name'; + $params['oxuser__oxlname'] = 'last name'; + $this->setRequestParameter('editval', $params); + $this->setRequestParameter('c_subject', 'testSubject'); + $contact = $this->getProxyClass('Contact'); + $contact->send(); + + $this->assertEquals(1, $contact->getNonPublicVar('_blContactSendStatus')); + } + + /** + * Test getting object for handling CAPTCHA image + */ + public function testGetCaptcha() + { + $contact = oxNew('Contact'); + $this->assertEquals(oxNew('oeCaptcha'), $contact->getCaptcha()); + } + + /** + * Test case for bug #0002065: Contact-Mail shows MR or MRS instead of localized salutation + */ + public function testSendForBugtrackEntry0002065() + { + $params = array( + 'oxuser__oxusername' => 'info@oxid-esales.com', + 'oxuser__oxfname' => 'admin', + 'oxuser__oxlname' => 'admin', + 'oxuser__oxsal' => 'MR' + ); + + $this->setRequestParameter('editval', $params); + $this->setRequestParameter('c_message', 'message'); + $this->setRequestParameter('c_subject', 'subject'); + + $language = oxRegistry::getLang(); + $message = $language->translateString('MESSAGE_FROM') . ' ' . $language->translateString('MR') . + ' admin admin(info@oxid-esales.com)

message'; + + $email = $this->getMock('oxemail', array('sendContactMail')); + $email->expects($this->once())->method('sendContactMail')->with($this->equalTo('info@oxid-esales.com'), + $this->equalTo('subject'), $this->equalTo($message))->will($this->returnValue(true)); + oxTestModules::addModuleObject('oxemail', $email); + + $captcha = $this->getMock('oeCaptcha', array('passCaptcha')); + $captcha->expects($this->once())->method('passCaptcha')->will($this->returnValue(true)); + + $contact = $this->getMock('oecaptchacontact', array('getCaptcha')); + $contact->expects($this->once())->method('getCaptcha')->will($this->returnValue($captcha)); + $contact->send(); + } + + /** + * Testing method send() + */ + public function testSendEmailNotSend() + { + $utils = $this->getMock('oxUtilsView', array('addErrorToDisplay')); + $utils->expects($this->once())->method('addErrorToDisplay')->with($this->equalTo('ERROR_MESSAGE_CHECK_EMAIL')); + oxTestModules::addModuleObject('oxUtilsView', $utils); + + $params = array( + 'oxuser__oxusername' => 'info@oxid-esales.com', + 'oxuser__oxfname' => 'admin', + 'oxuser__oxlname' => 'admin', + 'oxuser__oxsal' => 'MR' + ); + + $this->setRequestParameter('editval', $params); + $this->setRequestParameter('c_message', 'message'); + $this->setRequestParameter('c_subject', 'subject'); + + $email = $this->getMock('oxemail', array('sendContactMail')); + $email->expects($this->once())->method('sendContactMail')->will($this->returnValue(false)); + oxTestModules::addModuleObject('oxemail', $email); + + $captcha = $this->getMock('oeCaptcha', array('passCaptcha')); + $captcha->expects($this->once())->method('passCaptcha')->will($this->returnValue(true)); + + $contact = $this->getMock('oecaptchacontact', array('getCaptcha')); + $contact->expects($this->once())->method('getCaptcha')->will($this->returnValue($captcha)); + $contact->send(); + } +} diff --git a/tests/unit/views/detailsTest.php b/tests/unit/views/detailsTest.php new file mode 100644 index 0000000..86a415a --- /dev/null +++ b/tests/unit/views/detailsTest.php @@ -0,0 +1,45 @@ +getProxyClass('oecaptchadetails'); + $this->assertEquals(oxNew('oeCaptcha'), $details->getCaptcha()); + } + + /** + * Invalid captcha test case. + */ + public function testAddmeInvalidCaptcha() + { + $captcha = $this->getMock('oeCaptcha', array('passCaptcha')); + $captcha->expects($this->once())->method('passCaptcha')->will($this->returnValue(false)); + + $email = $this->getMock('oxEmail', array('sendPricealarmNotification')); + $email->expects($this->never())->method('sendPricealarmNotification'); + oxTestModules::addModuleObject('oxEmail', $email); + + $details = $this->getMock($this->getProxyClassName('oecaptchadetails'), array('getCaptcha')); + $details->expects($this->once())->method('getCaptcha')->will($this->returnValue($captcha)); + + $details->addme(); + $this->assertSame(2, $details->getNonPublicVar('_iPriceAlarmStatus')); + } + +} + + diff --git a/tests/unit/views/inviteTest.php b/tests/unit/views/inviteTest.php new file mode 100644 index 0000000..6a7be7e --- /dev/null +++ b/tests/unit/views/inviteTest.php @@ -0,0 +1,106 @@ +cleanUpTable('oxinvitations', 'oxuserid'); + + parent::tearDown(); + } + + /** + * Testing method getCaptcha() + * + * @return null + */ + public function testGetCaptcha() + { + $invite = $this->getProxyClass('oecaptchainvite'); + $this->assertEquals(oxNew('oeCaptcha'), $invite->getCaptcha()); + } + + /** + * Testing method send() - no captcha text + */ + public function testSendWithoutCaptcha() + { + $this->setRequestParameter('editval', array('rec_email' => 'testRecEmail@oxid-esales.com', + 'send_name' => 'testSendName', + 'send_email' => 'testSendEmail@oxid-esales.com', + 'send_message' => 'testSendMessage', + 'send_subject' => 'testSendSubject')); + $this->getConfig()->setConfigParam('blInvitationsEnabled', true); + + $captcha = $this->getMock('oeCaptcha', array('passCaptcha')); + $captcha->expects($this->once())->method('passCaptcha')->will($this->returnValue(false)); + + $invite = $this->getMock('oecaptchainvite', array('getCaptcha', 'getUser')); + $invite->expects($this->never())->method('getUser'); + $invite->expects($this->once())->method('getCaptcha')->will($this->returnValue($captcha)); + $invite->send(); + $this->assertFalse($invite->getInviteSendStatus()); + } + + /** + * Testing method send() + */ + public function testSend() + { + $this->setRequestParameter('editval', array('rec_email' => array('testRecEmail@oxid-esales.com'), 'send_name' => 'testSendName', 'send_email' => 'testSendEmail@oxid-esales.com', 'send_message' => 'testSendMessage', 'send_subject' => 'testSendSubject')); + $this->getConfig()->setConfigParam('blInvitationsEnabled', true); + + $email = $this->getMock('oxEmail', array('sendInviteMail')); + $email->expects($this->once())->method('sendInviteMail')->will($this->returnValue(true)); + oxTestModules::addModuleObject('oxEmail', $email); + + $captcha = $this->getMock('oeCaptcha', array('passCaptcha')); + $captcha->expects($this->once())->method('passCaptcha')->will($this->returnValue(true)); + + $invite = $this->getMock('oecaptchainvite', array('getCaptcha', 'getUser')); + $invite->expects($this->once())->method('getCaptcha')->will($this->returnValue($captcha)); + $invite->expects($this->any())->method('getUser')->will($this->returnValue(oxNew('oxUser'))); + $invite->send(); + $this->assertTrue($invite->getInviteSendStatus()); + } + + /** + * Testing method render() + * + * @return null + */ + public function testRender() + { + $this->getConfig()->setConfigParam('blInvitationsEnabled', true); + + $invite = $this->getMock('invite', array('getUser')); + $invite->expects($this->any())->method('getUser')->will($this->returnValue(oxNew('oxUser'))); + + $this->assertEquals('page/privatesales/invite.tpl', $invite->render()); + } + + /** + * Testing method render() - mail was sent status + */ + public function testRenderMailWasSent() + { + $this->getConfig()->setConfigParam('blInvitationsEnabled', true); + + $invite = $this->getProxyClass('invite'); + $invite->setNonPublicVar('_iMailStatus', 1); + $invite->render(); + + $this->assertTrue($invite->getInviteSendStatus()); + } + +} diff --git a/tests/unit/views/pricealarmTest.php b/tests/unit/views/pricealarmTest.php new file mode 100644 index 0000000..a192f33 --- /dev/null +++ b/tests/unit/views/pricealarmTest.php @@ -0,0 +1,111 @@ +cleanUpTable('oxpricealarm', 'oxartid'); + + parent::tearDown(); + } + + /** + * Test incorrect captcha. + */ + public function testAddmeIncorectCaptcha() + { + $priceAlarm = $this->getProxyClass('oecaptchapricealarm'); + $this->setRequestParameter('c_mac', 'aa'); + $this->setRequestParameter('c_mach', 'bb'); + + $priceAlarm->addme(); + + $this->assertEquals(2, $priceAlarm->getNonPublicVar('_iPriceAlarmStatus')); + + $query = 'select count(oxid) from oxpricealarm'; + $this->assertEquals(0, oxDb::getDb()->getOne($query)); + } + + /** + * Test incorrect email. + */ + public function testAddmeIncorectEmail() + { + $priceAlarm = $this->getProxyClass('oecaptchapricealarm'); + oxTestModules::addFunction('oeCaptcha', 'passCaptcha', '{return true;}'); + + $this->setRequestParameter('pa', array('email' => 'ladyGaga')); + $priceAlarm->addme(); + + $this->assertEquals(0, $priceAlarm->getNonPublicVar('_iPriceAlarmStatus')); + + $query = 'select count(oxid) from oxpricealarm'; + $this->assertEquals(0, oxDb::getDb()->getOne($query)); + } + + /** + * Test all is well. + */ + public function testAddmeSavesAndSendsPriceAlarm() + { + $priceAlarm = $this->getProxyClass('pricealarm'); + oxTestModules::addFunction('oeCaptcha', 'passCaptcha', '{return true;}'); + oxTestModules::addFunction('oxEmail', 'sendPricealarmNotification', '{return 999;}'); + + $this->getSession()->setVariable('usr', 'testUserId'); + $parameters['email'] = 'goodemail@ladyGagaFans.lt'; + $parameters['aid'] = '_testArtId'; + $parameters['price'] = '10'; + + $parameters['mano'] = '101'; + + $this->setRequestParameter('pa', $parameters); + $priceAlarm->addme(); + + $this->assertEquals(999, $priceAlarm->getNonPublicVar('_iPriceAlarmStatus')); + + $query = 'select * from oxpricealarm'; + $alarm = oxDb::getDb(oxDB::FETCH_MODE_ASSOC)->getRow($query); + + $this->assertEquals($parameters['email'], $alarm['OXEMAIL']); + $this->assertEquals($parameters['aid'], $alarm['OXARTID']); + $this->assertEquals($parameters['price'], $alarm['OXPRICE']); + $this->assertEquals('testUserId', $alarm['OXUSERID']); + $this->assertEquals('EUR', $alarm['OXCURRENCY']); + $this->assertEquals(0, $alarm['OXLANG']); + } + + /** + * Test saving active language. + */ + public function testAddmeSavesCurrentActiveLanguage() + { + $priceAlarm = $this->getProxyClass('pricealarm'); + oxTestModules::addFunction('oeCaptcha', 'passCaptcha', '{return true;}'); + oxTestModules::addFunction('oxEmail', 'sendPricealarmNotification', '{return 999;}'); + + $this->getSession()->setVariable('usr', 'testUserId'); + $parameters['email'] = 'goodemail@ladyGagaFans.lt'; + + oxRegistry::getLang()->setBaseLanguage(1); + $this->setRequestParameter('pa', $parameters); + + $priceAlarm->addme(); + + $query = 'select oxlang from oxpricealarm'; + $language = oxDb::getDb(oxDB::FETCH_MODE_ASSOC)->getOne($query); + + $this->assertEquals(1, $language); + } + +} diff --git a/tests/unit/views/suggestTest.php b/tests/unit/views/suggestTest.php new file mode 100644 index 0000000..c28a415 --- /dev/null +++ b/tests/unit/views/suggestTest.php @@ -0,0 +1,111 @@ +execute($sDelete); + + $sDelete = "delete from oxobject2list where oxlistid like 'testlist%'"; + oxDb::getDB()->execute($sDelete); + + parent::tearDown(); + } + + /** + * Test getter for suggest data. + */ + public function testGetSuggestData() + { + oxTestModules::addFunction('oeCaptcha', 'passCaptcha', '{return true;}'); + $this->setRequestParameter('editval', array('name' => 'test', 'value' => 'testvalue')); + + $suggest = $this->getProxyClass('oecaptchasuggest'); + $suggest->send(); + + $parameter = $suggest->getSuggestData(); + + $this->assertEquals('test', $parameter->name); + $this->assertEquals('testvalue', $parameter->value); + } + + /** + * Test captcha getter. + */ + public function testGetCaptcha() + { + $suggest = $this->getProxyClass('oecaptchasuggest'); + $this->assertEquals(oxNew('oeCaptcha'), $suggest->getCaptcha()); + } + + /** + * Test all is well. + */ + public function testSendPass() + { + $this->setRequestParameter( + 'editval', + array( + 'name' => 'test', + 'value' => 'testvalue', + 'rec_name' => 'test1', + 'rec_email' => 'recmail@oxid.lt', + 'send_name' => 'test3', + 'send_email' => 'sendmail@oxid.lt', + 'send_message' => 'test5', + 'send_subject' => 'test6', + ) + ); + + $email = $this->getMock('stdclass', array('sendSuggestMail')); + $email->expects($this->once())->method('sendSuggestMail') + ->will($this->returnValue(1)); + + oxTestModules::addModuleObject('oxemail', $email); + + $product = $this->getMock('oxarticle', array('getId')); + $product->expects($this->once())->method('getId')->will($this->returnValue('XProduct')); + + $captcha = $this->getMock('oeCaptcha', array('passCaptcha')); + $captcha->expects($this->once())->method('passCaptcha')->will($this->returnValue(true)); + + $suggest = $this->getMock('oecaptchasuggest', array('getProduct', 'getCaptcha')); + $suggest->expects($this->once())->method('getProduct')->will($this->returnValue($product)); + $suggest->expects($this->once())->method('getCaptcha')->will($this->returnValue($captcha)); + + $this->setRequestParameter('searchparam', 'searchparam&&A'); + $this->setRequestParameter('searchcnid', 'searchcnid&&A'); + $this->setRequestParameter('searchvendor', 'searchvendor&&A'); + $this->setRequestParameter('searchmanufacturer', 'searchmanufacturer&&A'); + $this->setRequestParameter('listtype', 'listtype&&A'); + + $expected = 'details?anid=XProduct&searchparam=searchparam%26%26A&searchcnid=searchcnid&&A&searchvendor=searchvendor&&A&searchmanufacturer=searchmanufacturer&&A&listtype=listtype&&A'; + $this->assertEquals($expected, $suggest->send()); + } + + /** + * Test invalid captcha case. + */ + public function testSendInvalidCaptcha() + { + $captcha = $this->getMock('oeCaptcha', array('passCaptcha')); + $captcha->expects($this->once())->method('passCaptcha')->will($this->returnValue(false)); + + $suggest = $this->getMock('oecaptchasuggest', array('getProduct', 'getCaptcha')); + $suggest->expects($this->never())->method('getProduct'); + $suggest->expects($this->once())->method('getCaptcha')->will($this->returnValue($captcha)); + + $this->assertFalse($suggest->send()); + } +} diff --git a/translations/de/oecaptcha_de_lang.php b/translations/de/oecaptcha_de_lang.php new file mode 100755 index 0000000..0effcb4 --- /dev/null +++ b/translations/de/oecaptcha_de_lang.php @@ -0,0 +1,17 @@ + 'UTF-8', + 'MESSAGE_WRONG_VERIFICATION_CODE' => 'Der Prüfcode, den Sie eingegeben haben, ist nicht korrekt. Bitte versuchen Sie es erneut!' +); diff --git a/translations/en/oecaptcha_en_lang.php b/translations/en/oecaptcha_en_lang.php new file mode 100755 index 0000000..45abef1 --- /dev/null +++ b/translations/en/oecaptcha_en_lang.php @@ -0,0 +1,17 @@ + 'UTF-8', + 'MESSAGE_WRONG_VERIFICATION_CODE' => "The verification code you entered is not correct. Please try again." +); diff --git a/views/admin/de/module_options.php b/views/admin/de/module_options.php new file mode 100644 index 0000000..8440e95 --- /dev/null +++ b/views/admin/de/module_options.php @@ -0,0 +1,13 @@ + 'UTF-8', + 'SHOP_MODULE_GROUP_main' => 'Allgemein', + 'SHOP_MODULE_oecaptchakey' => 'Captcha Key', +); diff --git a/views/admin/en/module_options.php b/views/admin/en/module_options.php new file mode 100644 index 0000000..b9b8e88 --- /dev/null +++ b/views/admin/en/module_options.php @@ -0,0 +1,13 @@ + 'UTF-8', + 'SHOP_MODULE_GROUP_main' => 'General', + 'SHOP_MODULE_oecaptchakey' => 'Captcha Key', +); diff --git a/views/blocks/captcha_form.tpl b/views/blocks/captcha_form.tpl new file mode 100644 index 0000000..8f10081 --- /dev/null +++ b/views/blocks/captcha_form.tpl @@ -0,0 +1,18 @@ +[{$smarty.block.parent}] + +[{assign var="oCaptcha" value=$oView->getCaptcha()}] + + +
  • + + [{assign var="oCaptcha" value=$oView->getCaptcha()}] + [{if $oCaptcha->isImageVisible()}] + + [{else}] + [{$oCaptcha->getText()}] + [{/if}] + +

    + [{oxmultilang ident="ERROR_MESSAGE_INPUT_NOTALLFIELDS"}] +

    +