SOLVED! BUG! CRITICAL! In Virtuemart 2.0.6 is not verified the required fields

Started by serapol, May 04, 2012, 23:30:24 PM

Previous topic - Next topic

serapol

In Virtumart 2.0.6 required fields are not checked at registration. If Javascript is to circumvent the user can easily register with no address, name, etc.

I tried to sort out the problem but did not understand how it works and whether there is such a check at all.

serapol

You validation occurs only in the basket, and only if task "checkout" is not correct. Validation should occur in all forms of user fields.

I suggest my solution to this problem
You need to add a validation function in the components/com_virtuemart/controllers/user.php


         /**
* Validation userdata
*
* @author Serapol
* @param String if BT or ST
* @param Array $data from post
* @return msg, if there is a msg, the redirect should be executed after
*/
private function validateUserData($type='BT', $data) {

if (!class_exists('VirtueMartModelUserfields'))
require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'userfields.php');
$userFieldsModel = VmModel::getModel('userfields');

if ($type == 'BT')
$fieldtype = 'account'; else
$fieldtype = 'shipment';

$neededFields = $userFieldsModel->getUserFields(
$fieldtype
, array('required' => true, 'delimiters' => true, 'captcha' => true, 'system' => false)
, array('delimiter_userinfo', 'name','username', 'password', 'password2', 'address_type_name', 'address_type', 'user_is_vendor', 'agreed'));

$msg = false;

$i = 0 ;

if ($type == 'ST') {
$dataST = array();
$_pattern = '/^shipto_/';

foreach ($data as $_k => $_v) {
if (preg_match($_pattern, $_k)) {
$_new = preg_replace($_pattern, '', $_k);
$dataST[$_new] = $_v;
}
}
$data = $dataST;
}

foreach ($neededFields as $field) {
if($field->required && empty($data[$field->name])){
$msg_fields[] = JText::_($field->title);
}
}

if ($msg_fields) {
$msg = JText::sprintf('COM_VIRTUEMART_MISSING_VALUE_FOR_FIELD', implode(', ', $msg_fields) );
}

return $msg;
}



Need to make changes in the function "saveData"


         /**
* Save the user info. The saveData function dont use the userModel store function for anonymous shoppers, because it would register them.
* We make this function private, so we can do the tests in the tasks.
*
* @author Max Milbers
* @author Valérie Isaksen
*
* @param boolean Defaults to false, the param is for the userModel->store function, which needs it to determin how to handle the data.
* @return String it gives back the messages.
*/
private function saveData($cart=false,$register=false) {
$mainframe = JFactory::getApplication();
$currentUser = JFactory::getUser();
$msg = '';

$data = JRequest::get('post');
/* //why is this in the controller and the model and not only in the model?
* Why is this written as plugin, but works only correct for captcha?
*
JPluginHelper::importPlugin('vmuserfield');
$dispatcher = JDispatcher::getInstance();
//Todo to adjust to new pattern, using &
$valid = true ;
if ($currentUser->id == 0) {$new = true;}
else $new=false;
Why you do create the new not directly in teh plugin? Why it does not get directly the data?
$dispatcher->trigger('plgVmOnUserVerify',array(&$valid,$new));
if( $valid == false ) {
// vmError('COM_VIRTUEMART_CAPTCHA_CODE_WRONG','COM_VIRTUEMART_CAPTCHA_CODE_WRONG');
return false;
}*/

// vmdebug('$currentUser',$currentUser);
//$data['address_type'] = JRequest::getWord('addrtype','BT');    //<------------------------- do not need, "addrtype" use is not here. Violated save the contact information.-------------------------


                //-------------------------------add a redirect to a page form if required fields are empty--------------------------------

                if ($msg = $this->validateUserData($data['address_type'], $data)) {
$mainframe->redirect(base64_decode($data['return']), $msg, 'error');
}
                //----------------------------end add a redirect to a page form if required fields are empty--------------------------------


if(!$currentUser->guest || $register){
$this->addModelPath( JPATH_VM_ADMINISTRATOR.DS.'models' );
$userModel = VmModel::getModel('user');

if(!$cart){
// Store multiple selectlist entries as a ; separated string
if (key_exists('vendor_accepted_currencies', $data) && is_array($data['vendor_accepted_currencies'])) {
$data['vendor_accepted_currencies'] = implode(',', $data['vendor_accepted_currencies']);
}

$data['vendor_store_name'] = JRequest::getVar('vendor_store_name','','post','STRING',JREQUEST_ALLOWHTML);
$data['vendor_store_desc'] = JRequest::getVar('vendor_store_desc','','post','STRING',JREQUEST_ALLOWHTML);
$data['vendor_terms_of_service'] = JRequest::getVar('vendor_terms_of_service','','post','STRING',JREQUEST_ALLOWHTML);
}

//It should always be stored
// if($currentUser->id==0 ){
$ret = $userModel->store($data);
// }

if($currentUser->guest){

                //-----------------------------------add a redirect to a page form if required corefields are empty or other error Joomla registration--------------------------------
if (!is_array($ret) && !$ret['success']) {
$mainframe->redirect(base64_decode($data['return']), $ret['message'], 'error');
}
                //--------------------------------end add a redirect to a page form if required corefields are empty or other error Joomla registration--------------------------------

$msg = (is_array($ret)) ? $ret['message'] : $ret;
$usersConfig = &JComponentHelper::getParams( 'com_users' );
$useractivation = $usersConfig->get( 'useractivation' );
if (is_array($ret) && $ret['success'] && !$useractivation) {
// Username and password must be passed in an array
$credentials = array('username' => $ret['user']->username,
  'password' => $ret['user']->password_clear
);
$return = $mainframe->login($credentials);
}
}

}

                $this->saveToCart($data);

return $msg;
}


For a user with blank fields on the same page back, you need to add the "return" to the components/com_virtuemart/views/user/views.php

After

        if (empty($this->fTask)) {
    $ftask = 'saveUser';
    $this->assignRef('fTask', $ftask);
}


add

//return URL for Validation Userdata by serapol
$uri = JFactory::getURI();
$url = $uri->toString(array('path', 'query', 'fragment'));
$return = base64_encode($url);
$this->assignRef('return', $return);


and add this option in the form of a template user/tmpl/edit.php

After
<input type="hidden" name="task" value="" />

add
<input type="hidden" name="return" value="<?php echo $this->return ?>"/>

and add to the form template user/tmpl/edit_address.php

after
<input type = "hidden" name = "address_type" value = "<?php echo $this->address_type;?>" />

add
<input type="hidden" name="return" value="<?php echo $this->return ?>"/>

serapol

Yet you do not have javascript validation is field "country" and "state"

Solving the problem

Step one
In the administartor/components/com_virtuemart/models/userfields.php as a function "getUserFieldsFilled" to make the following changes
In case 'virtuemart_country_id' in a function call "ShopFunctions::renderCountryList" add new parameter $_fld->required

ShopFunctions::renderCountryList($_return['fields'][$_fld->name]['value'], false, array(), $_prefix, $_fld->required); //--------------------pass to the function if this field is required------------------

In case 'virtuemart_state_id' in a function call "ShopFunctions::renderStateList" add new parameter $_fld->required


shopFunctions::renderStateList( $_return['fields'][$_fld->name]['value'],
// ShopFunctions::getCountryIDByName($_return['fields']['virtuemart_country_id']['value']),
$_prefix,
false,
$_fld->required //--------------------pass to the function if this field is required------------------
// $_prefix
);


Step two
In the file administartor/components/com_virtuemart/helpers/shopfunctions.php in function "renderCountryList" add parameter $required and same code

public function renderCountryList($countryId = 0, $multiple = false, $_attrib = array(), $_prefix = '', $required = 0) {

.......................................

$attrs['class'] = 'virtuemart_country_id';

if ($required) {
$attrs['class'] .= ' required'; //--------------Add if class "required" for joomla formvalidation if fields required ----------------------
}

....................................

}


In function "renderStateList" add parameter $required and same code


public function renderStateList($stateId = '0', $_prefix = '', $multiple = false, $required = 0) {

......................................

if ($required) {
$class = 'required ';//--------------Add if class "required" for joomla formvalidation if fields required ----------------------
}

//-------------------Adding a variable $class into select form ------------------------------------
                $listHTML = '<select class="'.$class.'inputbox multiple" id="virtuemart_state_id" ' . $attrs . '>
<OPTION value="">' . JText::_('COM_VIRTUEMART_LIST_EMPTY_OPTION') . '</OPTION>
</select>';

.....................................
}



That's it, now is validation of these fields javascript

serapol

I propose to change the validation function in the cart, as the post to check the data before the order is not logical. It is necessary to validate the data being in the session by.

My version of the function "validateUserData" in the file components/com_virtuemart/helpers/cart.php


/**
* Test cart session userdata if valid
*
* @author Serapol
* @param String if BT or ST
* @return redirectMsg, if there is a redirectMsg, the redirect should be executed after
*/
private function validateUserData($type='BT') {

if (!class_exists('VirtueMartModelUserfields'))
require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'userfields.php');
$userFieldsModel = VmModel::getModel('userfields');

$cart = $this->getCart(false);  //-----------get details cart-----------

if ($type == 'BT')
$fieldtype = 'account'; else
$fieldtype = 'shipment';

$neededFields = $userFieldsModel->getUserFields(
$fieldtype
, array('required' => true, 'delimiters' => true, 'captcha' => true, 'system' => false)
, array('delimiter_userinfo', 'name','username', 'password', 'password2', 'address_type_name', 'address_type', 'user_is_vendor', 'agreed'));

$redirectMsg = false;

$i = 0 ;


                //-----------------------check userfields required fields in the cart------------------------
                foreach ($neededFields as $field) {

if($field->required && !isset($cart->{$type}[$field->name])){
$redirectMsg = JText::sprintf('COM_VIRTUEMART_MISSING_VALUE_FOR_FIELD',JText::_($field->title) );
$i++;
}
}

return $redirectMsg;
}


If such a verification, until the client enters all the required data will not be able to order

serapol

Another found a nuance in components/com_virtuemart/helpers/cart.php. In the function "saveAddressInCart" is a code


                //dont store passwords in the session
unset($address['password']);
unset($address['password2']);


I propose to add a place


unset($address['username']);


Do not quite understand why login stored in the session. IMHO

serapol

Where can I write the different solutions that they are not lost on the prairie Forum?

Milbo

Hello serapol,

thank you for you input. Thanks for the code with the country and stateslist. I understood your other purposes, but decided, just to move the validate addreses data function to the usermodel and it is now called always there, when an address data is stored. Check the next svn.
Should I fix your bug, please support the VirtueMart project and become a member
______________________________________
Extensions approved by the core team: http://extensions.virtuemart.net/

gcomo01

Hi all,
I got a scenario that during testing I fill as a guest the registration fields for user registration. The new user registers no problem. The data of registration form is cached and after I login using my other user registered long before in account maintenance the data on Shopper Information is the one i used for registering the new user ... not the old user data that I logged in .. in the backend vm I see the data is ok though. If i don't save shopper details andlogout and login again it is ok (seesion cleared  I Guess) .Any solutions out there ?
thx G
joomla 1.7.3 vm 2.0.6

Milbo

No, and I dont know how a solution should look like. Atm we just think that a just entered data should not be deleted. But we could create a popup question. When someone logs in and there is already data in the BT/ST what todo with it.
Should I fix your bug, please support the VirtueMart project and become a member
______________________________________
Extensions approved by the core team: http://extensions.virtuemart.net/

kavit

Hey can you give final steps to do it correctly because its so confusing and data will be cleared after submiting the form and also popup is not showing for required field please help us i need it :)

My site address is http://3deducationalsolutions.com/

Thanks in advanced