0

i am using Yii user managment Module,when i a user is registering on my webiste,the captcha image is not shown on the form,however on contact form that is generated by Yii,the captcha is shown.Here is my View

EDIT: when i use firebug or chrome developer tools,i see that link is working fine even if i refresh it,the code changes but the image isnt printed but the img and its attirbute are in the html file

<?php $this->breadcrumbs = array(Yum::t('Registration')); ?>
<div class="form">
<?php $activeform = $this->beginWidget('CActiveForm', array(
        'id'=>'registration-form',
        'enableAjaxValidation'=>true,
        'enableClientValidation'=>true,
        'focus'=>array($form,'username'),
        ));
?>

<?php echo Yum::requiredFieldNote(); ?>
<?php echo CHtml::errorSummary(array($form, $profile)); ?>

<div class="row"> <?php
echo $activeform->labelEx($form,'username');
echo $activeform->textField($form,'username');
?> </div>

<div class="row">
<?php
echo $activeform->labelEx($profile,'email');
echo $activeform->textField($profile,'email');
?> </div>  

<div class="row"> <?php
echo $activeform->labelEx($profile,'firstname');
echo $activeform->textField($profile,'firstname'); 
?> </div>  

    <div class="row"> <?php
   echo $activeform->labelEx($profile,'lastname');
   echo $activeform->textField($profile,'lastname');
   ?> </div>  

<div class="row">
<?php echo $activeform->labelEx($form,'password'); ?>
<?php echo $activeform->passwordField($form,'password'); ?>
</div>

<div class="row">
<?php echo $activeform->labelEx($form,'verifyPassword'); ?>
<?php echo $activeform->passwordField($form,'verifyPassword'); ?>
</div>

 <?php if(extension_loaded('gd') 
        && Yum::module('registration')->enableCaptcha): ?>
  <div class="row">
    <?php echo CHtml::activeLabelEx($form,'verifyCode'); ?>
    <div>
    <?php $this->widget('CCaptcha', array('captchaAction'=>'//registration/registration/captcha')); ?>
    </br>
    <?php echo CHtml::activeTextField($form,'verifyCode'); ?>
    </div>
    <p class="hint">
    <?php echo Yum::t('Please enter the letters as they are shown in the image above.'); ?>
    <br/><?php echo Yum::t('Letters are not case-sensitive.'); ?></p>
</div>
<?php endif; ?>

<div class="row submit">
    <?php echo CHtml::submitButton(Yum::t('Registration')); ?>
</div>

<?php $this->endWidget(); ?>
</div><!-- form -->

here is my controller

<?php
/* This file handles a example registration process logic and some of the
* most used functions for Registration and Activation. It is recommended to
* extend from this class and implement your own, project-specific 
* Registration process. If this example does exactly what you want in your
* Project, then you can feel lucky already! */

Yii::import('application.modules.user.controllers.YumController');
Yii::import('application.modules.user.models.*');
Yii::import('application.modules.profile.models.*');
Yii::import('application.modules.registration.models.*');

class YumRegistrationController extends YumController {
  public $defaultAction = 'registration';

// Only allow the registration if the user is not already logged in and
// the function is activated in the Module Configuration
public function beforeAction($action) {
    if (!Yii::app()->user->isGuest) 
        $this->redirect(Yii::app()->user->returnUrl);

    $this->layout = Yum::module('registration')->layout;
    return parent::beforeAction($action);
}

public function accessRules() {
    return array(
            array('allow',
                'actions' => array('index', 'registration', 'recovery', 'activation','captcha', 'resendactivation'),
                'users' => array('*'),
                ),
            array('deny', // deny all other users
                'users' => array('*'),
                ),
            );
}

public function actions() {
    return array(
            'captcha' => array(
                'class' => 'CCaptchaAction',
                'backColor' => 0xFFFFFF,
                ),
            );
}

/*
 * an Example implementation of an registration of an new User in the system.
 *
 * please see the documentation of yii-user-management for examples on how to
 * extend from this class and implement your own registration logic in
 * user/docs/registration.txt
 */
public function actionRegistration() {
    // When we overrie the registrationUrl, this one is not valid anymore!
    if(Yum::module('registration')->registrationUrl != array(
                '//registration/registration/registration'))
        throw new CHttpException(403);

    Yii::import('application.modules.profile.models.*');
    $form = new YumRegistrationForm;
    $profile = new YumProfile;

    $this->performAjaxValidation('YumRegistrationForm', $form);

    if (isset($_POST['YumRegistrationForm'])) { 
        $form->attributes = $_POST['YumRegistrationForm'];
        $profile->attributes = $_POST['YumProfile'];

        $form->validate();
        $profile->validate();

        if(!$form->hasErrors() && !$profile->hasErrors()) {
            $user = new YumUser;
            $user->register($form->username, $form->password, $profile->email);
            $profile->user_id = $user->id;
            $profile->save();

            $this->sendRegistrationEmail($user);
            Yum::setFlash('Thank you for your registration. Please check your email.');
            $this->redirect(Yum::module()->loginUrl);
        }
    } 

    $this->render(Yum::module()->registrationView, array(
                'form' => $form,
                'profile' => $profile,
                )
            );  
}

// Send the Email to the given user object. $user->email needs to be set.
public static function sendRegistrationEmail($user) {
    if (!isset($user->profile->email)) {
        throw new CException(Yum::t('Email is not set when trying to send Registration Email'));
    }
    $activation_url = $user->getActivationUrl();

    // get the text to sent from the yumtextsettings table
    $content = YumTextSettings::model()->find('language = :lang', array(
                'lang' => Yii::app()->language));
    $sent = null;

    if (is_object($content)) {
        $body = strtr($content->text_email_registration, array(
                    '{username}' => $user->username,
                    '{activation_url}' => $activation_url));

        $mail = array(  'from_name'=>Yii::app()->name,
                'from' => Yum::module('registration')->registrationEmail,
                'to' => $user->profile->email,
                'to_name'=>$user->profile->firstname,
                'subject' => strtr($content->subject_email_registration, array(
                        '{username}' => $user->username)),
                'body' => $body,
                );
        $sent = YumMailer::send($mail);
    }
    else {
        throw new CException(Yum::t('The messages for your application language are not defined.'));
    }

    return $sent;
}

/**
 * Activation of an user account. The Email and the Activation key send
 * by email needs to correct in order to continue. The Status will
 * be initially set to 1 (active - first Visit) so the administrator
 * can see, which accounts have been activated, but not yet logged in 
 * (more than once)
 */
public function actionActivation($email, $key) {
    // If already logged in, we dont activate anymore
    if (!Yii::app()->user->isGuest) {
        Yum::setFlash('You are already logged in, please log out to activate your account');
        $this->redirect(Yii::app()->user->returnUrl);
    }

    // If everything is set properly, let the model handle the Validation
    // and do the Activation
    $status = YumUser::activate($email, $key);


    if($status instanceof YumUser) {
        if(Yum::module('registration')->loginAfterSuccessfulActivation) {
            $login = new YumUserIdentity($status->username, false); 
            $login->authenticate(true);
            Yii::app()->user->login($login);    
        } 

        $this->render(Yum::module('registration')->activationSuccessView);
    }
    else
        $this->render(Yum::module('registration')->activationFailureView, array(
                    'error' => $status));
}

/**
 * Password recovery routine. The User will receive an email with an
 * activation link. If clicked, he will be prompted to enter his new
 * password.
 */
public function actionRecovery($email = null, $key = null) {
    $form = new YumPasswordRecoveryForm;

    if ($email != null && $key != null) {
        if($profile = YumProfile::model()->find('email = :email', array(
                        'email' =>  $email))) {
            $user = $profile->user;
            if($user->activationKey == $key) {
                $passwordform = new YumUserChangePassword;
                if (isset($_POST['YumUserChangePassword'])) {
                    $passwordform->attributes = $_POST['YumUserChangePassword'];
                    if ($passwordform->validate()) {
                        $user->password = YumUser::encrypt($passwordform->password);
                        $user->activationKey = YumUser::encrypt(microtime() . $passwordform->password);
                        $user->save();
                        Yum::setFlash('Your new password has been saved.');
                        $this->redirect(Yum::module()->loginUrl);
                    }
                }
                $this->render(
                        Yum::module('registration')->changePasswordView, array(
                            'form' => $passwordform));
                Yii::app()->end();
            } else {
                $form->addError('login_or_email', Yum::t('Invalid recovery key'));
                Yum::log(Yum::t(
                            'Someone tried to recover a password, but entered a wrong recovery key. Email is {email}, associated user is {username} (id: {uid})', array(
                                '{email}' => $email,
                                '{uid}' => $user->id,
                                '{username}' => $user->username)));
            }
        }
    } else {
        if (isset($_POST['YumPasswordRecoveryForm'])) {
            $form->attributes = $_POST['YumPasswordRecoveryForm'];

            if ($form->validate()) {
                Yum::setFlash(
                        'Instructions have been sent to you. Please check your email.');

                if($form->user instanceof YumUser) {
                    $form->user->generateActivationKey();
                    $recovery_url = $this->createAbsoluteUrl(
                            Yum::module('registration')->recoveryUrl[0], array(
                                'key' => $form->user->activationKey,
                                'email' => $form->user->profile->email));

                    Yum::log(Yum::t(
                                '{username} successfully requested a new password in the password recovery form. A email with the password recovery url {recovery_url} has been sent to {email}', array(
                                    '{email}' => $form->user->profile->email,
                                    '{recovery_url}' => $recovery_url,
                                    '{username}' => $form->user->username)));

                    $content = YumTextSettings::model()->find(
                            'language = :lang', array('lang' => Yii::app()->language));
                    $sent = null;

                    if (is_object($content)) {
                        $mail = array(
                                'from' => Yii::app()->params['adminEmail'],
                                'to' => $form->user->profile->email,
                                'subject' => $content->subject_email_registration,
                                'body' => strtr($content->text_email_recovery, array(
                                        '{recovery_url}' => $recovery_url)),
                                );
                        $sent = YumMailer::send($mail);
                    } else {
                        throw new CException(Yum::t('The messages for your application language are not defined.'));
                    }
                } else
                    Yum::log(Yum::t(
                                'A password has been requested, but no associated user was found in the database. Requested user/email is: {username}', array(
                                    '{username}' => $form->login_or_email)));
                $this->redirect(Yum::module()->loginUrl);
            }
        }
    }
 $this->render(Yum::module('registration')->recoverPasswordView, array(
                'form' => $form));
    }
  }

Here is my model

<?php
/**
* RegistrationForm class.
* RegistrationForm is the data structure for keeping
* user registration form data. It is used by the 'registration' action of       'YumUserController'.
* @package Yum.models
*/
   class YumRegistrationForm extends YumUser {
public $verifyPassword;

/**
 * @var string
 */
public $verifyCode;

public function rules() 
{
    $rules = parent::rules();
    if(Yii::app()->getModule('user')->loginType != 'LOGIN_BY_EMAIL' || Yum::module()->registrationType ==REG_NO_USERNAME_OR_PASSWORD || Yum::module()->registrationType == REG_NO_USERNAME_OR_PASSWORD_ADMIN)
        $rules[] = array('username', 'required');
    $rules[] = array('password, verifyPassword', 'required');
    $rules[] = array('password', 'compare', 'compareAttribute'=>'verifyPassword', 'message' => Yii::t("UserModule.user", "Retype password is incorrect."));
    $rules[] = array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements(),'on'=>'insert');

    return $rules;


}

public function genRandomString( $length = 10)
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyz';
$string ='';    
for ($p = 0; $p < $length; $p++)
 {
    $string .= $characters[mt_rand(0, strlen($characters)-1)];
}
return $string;
}

  }
Eliethesaiyan
  • 2,327
  • 1
  • 22
  • 35

3 Answers3

4

Change it to this in your view. Default the captcha image is loaded from SiteController, where captcha is the action (you can see it under 'actions' there). You're referring to //registration/registration/captcha, which doesn't exists:

<?php $this->widget('CCaptcha', array('captchaAction'=>'site/captcha')); ?>
davey
  • 1,801
  • 2
  • 17
  • 22
  • Thanks Davey...actually the //registration/registration/captcha refer to controller called registrationController of a module called registration...it is valid and i can see in the html that the code changes when i click on the link that generates another code....i ve tried what you have suggested also...the image is displayed when it comes to validation...the form is validated against the The Model of registration..not the one with Site.....Any idea how i could validate the captcha against Site`s ContactForm`s captcha and the rest of the fields to the Registration model...? – Eliethesaiyan Sep 13 '13 at 13:22
  • Oh i'm sorry, you're right indeed about the module! Can you give me an example of the capthca url image? And the name of the input field of the captcha (where the user fills in the captcha code)? – davey Sep 16 '13 at 08:18
  • the url looks like this in firebug...http://localhost/deployment/index.php/registration/registration/captcha/v/5238088d835ba(this code keep changing when i click get a new code)...the textbox for inputing the details..you can refer to view file i ve posted in the question..thanks alot for your help – Eliethesaiyan Sep 17 '13 at 07:47
  • yes..exactly there i dont see any image..but when i point the captcha widget to site/Captcha action..it display the image – Eliethesaiyan Sep 17 '13 at 08:36
1

Short answer

Set captchaAction on the CaptchaValidator to the same value as in the widget

Long answer

I had the same problem: captcha working on the contacts page but on another controller/action page I had no image. Changing captchaAction on the widget to 'site/captcha' made the image appear but the validation didn't work!

After a few research I found that:

  • not setting captchaAction on the widget made invocation of CCaptchaAction::renderImageImagick() or CCaptchaAction::renderImageGD() produce an invalid PNG file (don't know why)
  • according to Yii CAPTCHA url is broken and https://github.com/yiisoft/yii2/issues/693 I also needed to add captchaAction on the CCaptchaValidator to the same value on CCaptcha widget

Now my CFormModel::rules() returns an array with this element:

array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements(), 'message'=>'Código incorreto.', 'captchaAction'=>'site/captcha'),

Hopes this helps someone.

Community
  • 1
  • 1
1

Need to write also because when you are overwritten accessRules(), you need to make the captcha action available for everyone, like this:

class MyController extends Controller
{
    public function accessRules() {
        return array('allow', 'actions' => array('captcha'), 'users' => array('*'));
    }
}

And

array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements()),

Please find the best help from these tutorials -

Add Captcha Yii Framework – Yii tutorial
Why does yii captcha not display “Get new code” ?

Rohit Suthar
  • 3,528
  • 1
  • 42
  • 48