Buenas. Soy el administrador de www.voluntariadoalcores.org. Hace unos días solicité cambiar el aspecto del formulario de recuperación de la contraseña que me aparecía en tablas descuadradas. Lo cierto es que, después de que me proporcionárais el código -se puede encontrar en el hilo: "Problemas con Formulario de Acceso"- he intentado recuperar la contraseña y me aparece este mensaje:
No sé a qué puede ser debido. Supongo que se deberá a una mala escritura del archivo "confirm.php" que fue el que modifiqué siguiendo vuestras instrucciones. ¿Qué podría hacer? Muchas gracias y saludos.
Hola Juan
Ese error usualmente aparece cuando has cambiado los permisos, puede ser que hayas movido los permisos accidentalmente del archivo,
verifica desde tu cpanel => administrador de archivos, de tu cuenta de hosting que el archivo confirm.php tenga permisos 644, verifica también las carpetas que tengan permisos 755
Saludos.
El archivo confirm.php tiene el permiso 644 y todas las carpetas superiores el 755. ¿Qué puedo hacer ahora? Gracias y saludos.
Hola Juan
Estoy viendo que la página de confirmación carga correctamente
http://www.voluntariadoalcores.org/?option=com_user&view=reset&layout=confirm
Verifica si a ti te carga también, prueba con otro navegador o limpia la cache del navegador que usasa
Saludos.
Pues he limpiado la caché pero sigo teniendo los mismos problemas. Cuando escribo el nombre de usuario y la clave, me sale el aviso.
Hola Juan
Verifica los permisos de los archivos
components/com_user/controller.php y components/com_user/models/ , tal como te indique anteriormente ese error es por permiso de archivos.
También sería bueno ver el error_log que se esta generando en la raiz de tu sitio web.
Saludos.
El controller.php arroja estos datos:
class UserController extends JController
{
/**
* Method to display a view
*
* @access public
* @since 1.5
*/
function display()
{
parent::display();
}
function edit()
{
global $mainframe, $option;
$db =& JFactory::getDBO();
$user =& JFactory::getUser();
if ( $user->get('guest')) {
JError::raiseError( 403, JText::_('Access Forbidden') );
return;
}
JRequest::setVar('layout', 'form');
parent::display();
}
function save()
{
// Check for request forgeries
JRequest::checkToken() or jexit( 'Invalid Token' );
$user =& JFactory::getUser();
$userid = JRequest::getVar( 'id', 0, 'post', 'int' );
// preform security checks
if ($user->get('id') == 0 || $userid == 0 || $userid $user->get('id')) {
JError::raiseError( 403, JText::_('Access Forbidden') );
return;
}
//clean request
$post = JRequest::get( 'post' );
$post['username'] = JRequest::getVar('username', '', 'post', 'username');
$post['password'] = JRequest::getVar('password', '', 'post', 'string', JREQUEST_ALLOWRAW);
$post['password2'] = JRequest::getVar('password2', '', 'post', 'string', JREQUEST_ALLOWRAW);
// get the redirect
$return = JURI::base();
// do a password safety check
if(strlen($post['password']) || strlen($post['password2'])) { // so that "0" can be used as password e.g.
if($post['password'] != $post['password2']) {
$msg = JText::_('PASSWORDS_DO_NOT_MATCH');
// something is wrong. we are redirecting back to edit form.
// TODO: HTTP_REFERER should be replaced with a base64 encoded form field in a later release
$return = str_replace(array('"', '', "'"), '', @$_SERVER['HTTP_REFERER']);
if (empty($return) || !JURI::isInternal($return)) {
$return = JURI::base();
}
$this->setRedirect($return, $msg, 'error');
return false;
}
}
// we don't want users to edit certain fields so we will unset them
unset($post['gid']);
unset($post['block']);
unset($post['usertype']);
unset($post['registerDate']);
unset($post['activation']);
// store data
$model = $this->getModel('user');
if ($model->store($post)) {
$msg = JText::_( 'Your settings have been saved.' );
} else {
//$msg = JText::_( 'Error saving your settings.' );
$msg = $model->getError();
}
$this->setRedirect( $return, $msg );
}
function cancel()
{
$this->setRedirect( 'index.php' );
}
function login()
{
// Check for request forgeries
JRequest::checkToken('request') or jexit( 'Invalid Token' );
global $mainframe;
if ($return = JRequest::getVar('return', '', 'method', 'base64')) {
$return = base64_decode($return);
if (!JURI::isInternal($return)) {
$return = '';
}
}
$options = array();
$options['remember'] = JRequest::getBool('remember', false);
$options['return'] = $return;
$credentials = array();
$credentials['username'] = JRequest::getVar('username', '', 'method', 'username');
$credentials['password'] = JRequest::getString('passwd', '', 'post', JREQUEST_ALLOWRAW);
//preform the login action
$error = $mainframe->login($credentials, $options);
if(!JError::isError($error))
{
// Redirect if the return url is not registration or login
if ( ! $return ) {
$return = 'index.php?option=com_user';
}
$mainframe->redirect( $return );
}
else
{
// Facilitate third party login forms
if ( ! $return ) {
$return = 'index.php?option=com_user&view=login';
}
// Redirect to a login form
$mainframe->redirect( $return );
}
}
function logout()
{
global $mainframe;
//preform the logout action
$error = $mainframe->logout();
if(!JError::isError($error))
{
if ($return = JRequest::getVar('return', '', 'method', 'base64')) {
$return = base64_decode($return);
if (!JURI::isInternal($return)) {
$return = '';
}
}
// Redirect if the return url is not registration or login
if ( $return && !( strpos( $return, 'com_user' )) ) {
$mainframe->redirect( $return );
}
} else {
parent::display();
}
}
/**
* Prepares the registration form
* @return void
*/
function register()
{
$usersConfig = &JComponentHelper::getParams( 'com_users' );
if (!$usersConfig->get( 'allowUserRegistration' )) {
JError::raiseError( 403, JText::_( 'Access Forbidden' ));
return;
}
$user =& JFactory::getUser();
if ( $user->get('guest')) {
JRequest::setVar('view', 'register');
} else {
$this->setredirect('index.php?option=com_user&task=edit',JText::_('You are already registered.'));
}
parent::display();
}
/**
* Save user registration and notify users and admins if required
* @return void
*/
function register_save()
{
global $mainframe;
// Check for request forgeries
JRequest::checkToken() or jexit( 'Invalid Token' );
// Get required system objects
$user = clone(JFactory::getUser());
$pathway =& $mainframe->getPathway();
$config =& JFactory::getConfig();
$authorize =& JFactory::getACL();
$document =& JFactory::getDocument();
// If user registration is not allowed, show 403 not authorized.
$usersConfig = &JComponentHelper::getParams( 'com_users' );
if ($usersConfig->get('allowUserRegistration') == '0') {
JError::raiseError( 403, JText::_( 'Access Forbidden' ));
return;
}
// Initialize new usertype setting
$newUsertype = $usersConfig->get( 'new_usertype' );
if (!$newUsertype) {
$newUsertype = 'Registered';
}
// Bind the post array to the user object
if (!$user->bind( JRequest::get('post'), 'usertype' )) {
JError::raiseError( 500, $user->getError());
}
// Set some initial user values
$user->set('id', 0);
$user->set('usertype', $newUsertype);
$user->set('gid', $authorize->get_group_id( '', $newUsertype, 'ARO' ));
$date =& JFactory::getDate();
$user->set('registerDate', $date->toMySQL());
// If user activation is turned on, we need to set the activation information
$useractivation = $usersConfig->get( 'useractivation' );
if ($useractivation == '1')
{
jimport('joomla.user.helper');
$user->set('activation', JUtility::getHash( JUserHelper::genRandomPassword()) );
$user->set('block', '1');
}
// If there was an error with registration, set the message and display form
if ( !$user->save() )
{
JError::raiseWarning('', JText::_( $user->getError()));
$this->register();
return false;
}
// Send registration confirmation mail
$password = JRequest::getString('password', '', 'post', JREQUEST_ALLOWRAW);
$password = preg_replace('/[x00-x1Fx7F]/', '', $password); //Disallow control chars in the email
UserController::_sendMail($user, $password);
// Everything went fine, set relevant message depending upon user activation state and display message
if ( $useractivation == 1 ) {
$message = JText::_( 'REG_COMPLETE_ACTIVATE' );
} else {
$message = JText::_( 'REG_COMPLETE' );
}
$this->setRedirect('index.php', $message);
}
function activate()
{
global $mainframe;
// Initialize some variables
$db =& JFactory::getDBO();
$user =& JFactory::getUser();
$document =& JFactory::getDocument();
$pathway =& $mainframe->getPathWay();
$usersConfig = &JComponentHelper::getParams( 'com_users' );
$userActivation = $usersConfig->get('useractivation');
$allowUserRegistration = $usersConfig->get('allowUserRegistration');
// Check to see if they're logged in, because they don't need activating!
if ($user->get('id')) {
// They're already logged in, so redirect them to the home page
$mainframe->redirect( 'index.php' );
}
if ($allowUserRegistration == '0' || $userActivation == '0') {
JError::raiseError( 403, JText::_( 'Access Forbidden' ));
return;
}
// create the view
require_once (JPATH_COMPONENT.DS.'views'.DS.'register'.DS.'view.html.php');
$view = new UserViewRegister();
$message = new stdClass();
// Do we even have an activation string?
$activation = JRequest::getVar('activation', '', '', 'alnum' );
$activation = $db->getEscaped( $activation );
if (empty( $activation ))
{
// Page Title
$document->setTitle( JText::_( 'REG_ACTIVATE_NOT_FOUND_TITLE' ) );
// Breadcrumb
$pathway->addItem( JText::_( 'REG_ACTIVATE_NOT_FOUND_TITLE' ));
$message->title = JText::_( 'REG_ACTIVATE_NOT_FOUND_TITLE' );
$message->text = JText::_( 'REG_ACTIVATE_NOT_FOUND' );
$view->assign('message', $message);
$view->display('message');
return;
}
// Lets activate this user
jimport('joomla.user.helper');
if (JUserHelper::activateUser($activation))
{
// Page Title
$document->setTitle( JText::_( 'REG_ACTIVATE_COMPLETE_TITLE' ) );
// Breadcrumb
$pathway->addItem( JText::_( 'REG_ACTIVATE_COMPLETE_TITLE' ));
$message->title = JText::_( 'REG_ACTIVATE_COMPLETE_TITLE' );
$message->text = JText::_( 'REG_ACTIVATE_COMPLETE' );
}
else
{
// Page Title
$document->setTitle( JText::_( 'REG_ACTIVATE_NOT_FOUND_TITLE' ) );
// Breadcrumb
$pathway->addItem( JText::_( 'REG_ACTIVATE_NOT_FOUND_TITLE' ));
$message->title = JText::_( 'REG_ACTIVATE_NOT_FOUND_TITLE' );
$message->text = JText::_( 'REG_ACTIVATE_NOT_FOUND' );
}
$view->assign('message', $message);
$view->display('message');
}
/**
* Password Reset Request Method
*
* @access public
*/
function requestreset()
{
// Check for request forgeries
JRequest::checkToken() or jexit( 'Invalid Token' );
// Get the input
$email = JRequest::getVar('email', null, 'post', 'string');
// Get the model
$model = &$this->getModel('Reset');
// Request a reset
if ($model->requestReset($email) === false)
{
$message = JText::sprintf('PASSWORD_RESET_REQUEST_FAILED', $model->getError());
$this->setRedirect('index.php?option=com_user&view=reset', $message);
return false;
}
$this->setRedirect('index.php?option=com_user&view=reset&layout=confirm');
}
/**
* Password Reset Confirmation Method
*
* @access public
*/
function confirmreset()
{
// Check for request forgeries
JRequest::checkToken() or jexit( 'Invalid Token' );
// Get the input
$token = JRequest::getVar('token', null, 'post', 'alnum');
$username = JRequest::getVar('username', null, 'post');
// Get the model
$model = &$this->getModel('Reset');
// Verify the token
if ($model->confirmReset($token, $username) !== true)
{
$message = JText::sprintf('PASSWORD_RESET_CONFIRMATION_FAILED', $model->getError());
$this->setRedirect('index.php?option=com_user&view=reset&layout=confirm', $message);
return false;
}
$this->setRedirect('index.php?option=com_user&view=reset&layout=complete');
}
/**
* Password Reset Completion Method
*
* @access public
*/
function completereset()
{
// Check for request forgeries
JRequest::checkToken() or jexit( 'Invalid Token' );
// Get the input
$password1 = JRequest::getVar('password1', null, 'post', 'string', JREQUEST_ALLOWRAW);
$password2 = JRequest::getVar('password2', null, 'post', 'string', JREQUEST_ALLOWRAW);
// Get the model
$model = &$this->getModel('Reset');
// Reset the password
if ($model->completeReset($password1, $password2) === false)
{
$message = JText::sprintf('PASSWORD_RESET_FAILED', $model->getError());
$this->setRedirect('index.php?option=com_user&view=reset&layout=complete', $message);
return false;
}
$message = JText::_('PASSWORD_RESET_SUCCESS');
$this->setRedirect('index.php?option=com_user&view=login', $message);
}
/**
* Username Reminder Method
*
* @access public
*/
function remindusername()
{
// Check for request forgeries
JRequest::checkToken() or jexit( 'Invalid Token' );
// Get the input
$email = JRequest::getVar('email', null, 'post', 'string');
// Get the model
$model = &$this->getModel('Remind');
// Send the reminder
if ($model->remindUsername($email) === false)
{
$message = JText::sprintf('USERNAME_REMINDER_FAILED', $model->getError());
$this->setRedirect('index.php?option=com_user&view=remind', $message);
return false;
}
$message = JText::sprintf('USERNAME_REMINDER_SUCCESS', $email);
$this->setRedirect('index.php?option=com_user&view=login', $message);
}
function _sendMail(&$user, $password)
{
global $mainframe;
$db =& JFactory::getDBO();
$name = $user->get('name');
$email = $user->get('email');
$username = $user->get('username');
$usersConfig = &JComponentHelper::getParams( 'com_users' );
$sitename = $mainframe->getCfg( 'sitename' );
$useractivation = $usersConfig->get( 'useractivation' );
$mailfrom = $mainframe->getCfg( 'mailfrom' );
$fromname = $mainframe->getCfg( 'fromname' );
$siteURL = JURI::base();
$subject = sprintf ( JText::_( 'Account details for' ), $name, $sitename);
$subject = html_entity_decode($subject, ENT_QUOTES);
if ( $useractivation == 1 ){
$message = sprintf ( JText::_( 'SEND_MSG_ACTIVATE' ), $name, $sitename, $siteURL."index.php?option=com_user&task=activate&activation=".$user->get('activation'), $siteURL, $username, $password);
} else {
$message = sprintf ( JText::_( 'SEND_MSG' ), $name, $sitename, $siteURL);
}
$message = html_entity_decode($message, ENT_QUOTES);
//get all super administrator
$query = 'SELECT name, email, sendEmail' .
' FROM #__users' .
' WHERE LOWER( usertype ) = "super administrator"';
$db->setQuery( $query );
$rows = $db->loadObjectList();
// Send email to user
if ( ! $mailfrom || ! $fromname ) {
$fromname = $rows[0]->name;
$mailfrom = $rows[0]->email;
}
JUtility::sendMail($mailfrom, $fromname, $email, $subject, $message);
// Send notification to all administrators
$subject2 = sprintf ( JText::_( 'Account details for' ), $name, $sitename);
$subject2 = html_entity_decode($subject2, ENT_QUOTES);
// get superadministrators id
foreach ( $rows as $row )
{
if ($row->sendEmail)
{
$message2 = sprintf ( JText::_( 'SEND_MSG_ADMIN' ), $row->name, $sitename, $name, $email, $username);
$message2 = html_entity_decode($message2, ENT_QUOTES);
JUtility::sendMail($mailfrom, $fromname, $row->email, $subject2, $message2);
}
}
}
}
?>
El archivo reset.php (com_user/models) muestra lo siguiente::
class UserModelReset extends JModel
{
/**
* Registry namespace prefix
*
* @var string
*/
var $_namespace = 'com_user.reset.';
/**
* Verifies the validity of a username/e-mail address
* combination and creates a token to verify the request
* was initiated by the account owner. The token is
* sent to the account owner by e-mail
*
* @since 1.5
* @param string Username string
* @param string E-mail address
* @return bool True on success/false on failure
*/
function requestReset($email)
{
jimport('joomla.mail.helper');
jimport('joomla.user.helper');
$db = &JFactory::getDBO();
// Make sure the e-mail address is valid
if (!JMailHelper::isEmailAddress($email))
{
$this->setError(JText::_('INVALID_EMAIL_ADDRESS'));
return false;
}
// Build a query to find the user
$query = 'SELECT id FROM #__users'
. ' WHERE email = '.$db->Quote($email)
. ' AND block = 0';
$db->setQuery($query);
// Check the results
if (!($id = $db->loadResult()))
{
$this->setError(JText::_('COULD_NOT_FIND_USER'));
return false;
}
// Generate a new token
$token = JUtility::getHash(JUserHelper::genRandomPassword());
$salt = JUserHelper::getSalt('crypt-md5');
$hashedToken = md5($token.$salt).':'.$salt;
$query = 'UPDATE #__users'
. ' SET activation = '.$db->Quote($hashedToken)
. ' WHERE id = '.(int) $id
. ' AND block = 0';
$db->setQuery($query);
// Save the token
if (!$db->query())
{
$this->setError(JText::_('DATABASE_ERROR'));
return false;
}
// Send the token to the user via e-mail
if (!$this->_sendConfirmationMail($email, $token))
{
return false;
}
return true;
}
/**
* Checks a user supplied token for validity
* If the token is valid, it pushes the token
* and user id into the session for security checks.
*
* @since 1.5
* @param token An md5 hashed randomly generated string
* @return bool True on success/false on failure
*/
function confirmReset($token, $username)
{
global $mainframe;
jimport('joomla.user.helper');
if(strlen($token) != 32) {
$this->setError(JText::_('INVALID_TOKEN'));
return false;
}
$db = &JFactory::getDBO();
$db->setQuery('SELECT id, activation FROM #__users WHERE block = 0 AND username = '.$db->Quote($username));
$row = $db->loadObject();
// Verify the token
if (!$row)
{
$this->setError(JText::_('INVALID_TOKEN'));
return false;
}
$parts = explode( ':', $row->activation );
$crypt = $parts[0];
if (!isset($parts[1])) {
$this->setError(JText::_('INVALID_TOKEN'));
return false;
}
$salt = $parts[1];
$testcrypt = JUserHelper::getCryptedPassword($token, $salt);
// Verify the token
if (!($crypt == $testcrypt))
{
$this->setError(JText::_('INVALID_TOKEN'));
return false;
}
// Push the token and user id into the session
$mainframe->setUserState($this->_namespace.'token', $crypt.':'.$salt);
$mainframe->setUserState($this->_namespace.'id', $row->id);
return true;
}
/**
* Takes the new password and saves it to the database.
* It will only save the password if the user has the
* correct user id and token stored in her session.
*
* @since 1.5
* @param string New Password
* @param string New Password
* @return bool True on success/false on failure
*/
function completeReset($password1, $password2)
{
jimport('joomla.user.helper');
global $mainframe;
// Make sure that we have a pasword
if ( ! $password1 )
{
$this->setError(JText::_('MUST_SUPPLY_PASSWORD'));
return false;
}
// Verify that the passwords match
if ($password1 != $password2)
{
$this->setError(JText::_('PASSWORDS_DO_NOT_MATCH_LOW'));
return false;
}
// Get the necessary variables
$db = &JFactory::getDBO();
$id = $mainframe->getUserState($this->_namespace.'id');
$token = $mainframe->getUserState($this->_namespace.'token');
$salt = JUserHelper::genRandomPassword(32);
$crypt = JUserHelper::getCryptedPassword($password1, $salt);
$password = $crypt.':'.$salt;
// Get the user object
$user = new JUser($id);
// Fire the onBeforeStoreUser trigger
JPluginHelper::importPlugin('user');
$dispatcher =& JDispatcher::getInstance();
$dispatcher->trigger('onBeforeStoreUser', array($user->getProperties(), false));
// Build the query
$query = 'UPDATE #__users'
. ' SET password = '.$db->Quote($password)
. ' , activation = ""'
. ' WHERE id = '.(int) $id
. ' AND activation = '.$db->Quote($token)
. ' AND block = 0';
$db->setQuery($query);
// Save the password
if (!$result = $db->query())
{
$this->setError(JText::_('DATABASE_ERROR'));
return false;
}
// Update the user object with the new values.
$user->password = $password;
$user->activation = '';
$user->password_clear = $password1;
// Fire the onAfterStoreUser trigger
$dispatcher->trigger('onAfterStoreUser', array($user->getProperties(), false, $result, $this->getError()));
// Flush the variables from the session
$mainframe->setUserState($this->_namespace.'id', null);
$mainframe->setUserState($this->_namespace.'token', null);
return true;
}
/**
* Sends a password reset request confirmation to the
* specified e-mail address with the specified token.
*
* @since 1.5
* @param string An e-mail address
* @param string An md5 hashed randomly generated string
* @return bool True on success/false on failure
*/
function _sendConfirmationMail($email, $token)
{
$config = &JFactory::getConfig();
$uri = &JFactory::getURI();
$url = JURI::base().'index.php?option=com_user&view=reset&layout=confirm';
$sitename = $config->getValue('sitename');
// Set the e-mail parameters
$from = $config->getValue('mailfrom');
$fromname = $config->getValue('fromname');
$subject = JText::sprintf('PASSWORD_RESET_CONFIRMATION_EMAIL_TITLE', $sitename);
$body = JText::sprintf('PASSWORD_RESET_CONFIRMATION_EMAIL_TEXT', $sitename, $token, $url);
// Send the e-mail
if (!JUtility::sendMail($from, $fromname, $email, $subject, $body))
{
$this->setError('ERROR_SENDING_CONFIRMATION_EMAIL');
return false;
}
return true;
}
}
Con esto, ¿qué podría hacer? Respecto al error.log, ¿donde lo podría encontrar? Cuando lo encuentre lo reporto. Muchas gracias. Saludos.
Hola Juan,
El archivo error_log lo encuentras accediendo al Administrador de Archivos de tu cPanel en las carpetas /public_html y /administrator respectivamente pudiendo editarlo desde ahí con el Editor de Código de la parte superior de esa misma pantalla.
Agradeceremos que cuando tengas que facilitarnos el contenido de un archivo grande (como es el caso de "controller.php") lo insertes en un archivo de texto planto (txt) y lo adjuntes, para evitar un post tan largo que no aporta tampoco la información que necesitamos para ayudarte a resolver puntualmente tu problema.
Una consulta. ¿hiciste copia de seguridad con Akeeba Backup de tu sitio antes de realizar los cambios que ahora te dan error?.
Saludos
Lo siento, sí, lo facilitaré en un .txt. Adjunto el archivo de error localizado en el cPanel. No he visto nada de los permisos.
Respecto a la copia de seguridad, no la hice, ha sido un error. Sin embargo, tengo una copia antigua del archivo confirm.php, cuya modificación parece haber causado esta situación. Gracias y Saludos,
Hola Juan,
Una buena política es siempre realizar una copia de seguridad antes de realizar cualquier modificación, máxime si esta afecta a código del core de Joomla!, el cual no se recomienda cambiar porque se pierde tras una actualización.
Previa copia te recomendaría restaurar el archivo que dices tener anterior nuevamente.
Saludos
Es cierto, menos mal que guardé ese archivo anteriormente. Lo he restaurado y ahora la renovación de contraseña funciona perfectamente. Lo único, es que tengo el mismo problema que avisé anteriormente en el hilo "Formulario de acceso", es decir, me aparece el cuadro de CLAVE encima de el de NOMBRE DE USUARIO y justo al lado, el botón de enviar. Me gustaría poner en primer lugar el nombre de usuario, después el recuadro de clave y finalmente, debajo, el botón de enviar. Sé que es cuestión de escribir bien el código php del archivo, pero es que no sé cómo ponerlo. Adjunto el código del archivo confirm por si me podéis indicar qué cambiar para hacer lo que os he comentado. Muchas gracias y un saludo.
Perdón, no he adjuntado el archivo. Adjunto el código del archivo confirm.php. Saludos y Gracias.
Hola,
Viendo el archivo que has adjuntado veo que no está montada correctamente la estructura de la tabla. También intuyo que este archivo está en el template overwrite de la plantilla, es decir en los archivos de la plantilla que modifican las plantillas de componentes y módulos de Joomla que estén en la web.
Se puede ver una explicación sobre el template overwrite en la siguiente entrada de nuestro blog:
He realizado una corrección del archivo confirm.php que habría que colocar en la ruta templates/ja_lime/html/com_user/reset
Te lo adjunto en formato txt para que lo coloques dentro del archivo. Aunque no lo he probado debería funcionar. Recuerda hacer una copia de seguridad de archivo antes del cambio.
Por otra parte, puede que sea conveniente que agregues algún sistema de seguridad para el registro de usuarios en Joomla, como el captcha (letras y números que se muestran en una imagen y que hay que escribir para verificar que el que está rellenando el formulario es un humano). Te pongo un enlace al blog donde damos indicaciones sobre colocar un plugin para poner Recaptcha en los formularios de Joomla:
He implementado el código y funciona perfectamente!! Ya no de problemas con los permisos y la apariencias es la correcta: el nombre de usuario arriba y la clave abajo. Muchas gracias. Respecto al reCaptcha, lo tengo activado para todos los formularios que permite el joo Recaptcha, entre ellos, el de registro y el de recuperación de contraseña. Muchas gracias por todo. Saludos.
Hola Juan,
Genial que hayas solventado el problema y como dice Pablo, mejor este tipo de modificaciones en un "override" que en el archivo original, así cuando actualices no perderás ese cambio.
Saludos