João Cunha Posted April 6, 2012 Share Posted April 6, 2012 (edited) Hi there! This is my first contribution to the community. I hope it helps someone. I would like to share my approach on how to integrate Zen-Cart / OSCommerce passwords with Prestashop. I have a Zen-Cart shop with 50k registered customers which I am migrating to Prestashop. The "Back Office -> Tools -> CSV Import" tool works like a charm to import your customers but they will not be able to login on Prestashop because passwords are encrypted in different ways on both store managers. This solution requires no database modification (aside from creating a support table) and only one php code modification (/classes/Customer.php). It will let your legacy customers login and change passwords through admin panel or "forgot my password" if they'd like. Actually they would not notice anything different at all. If you want to understand some of the inner workings of both systems, I would recommend you to learn a little about password hashing and hash salting. You can skip this part if you want to get your hands dirty fast. How Zen-Cart / OSCommerce passwords work: Format: 32 alphanumeric characters + colon + 2 alphanumeric characters salt E.g: e56d64755f66a86996b54114bb4102bf:08 35 characters total It has a salting function which generates a random salt for every password. The password is hashed with MD5 and salted with 2 aditional characters. These two aditional characters are then appended to the password with a colon. How Prestashop passwords work: Format: 32 alphanumeric characters (a standard MD5 salted hash) E.g: e56d64755f66a86996b54114bb4102bf 32 characters total It uses a per-installation random constant called _COOKIE_KEY_ as salt. As you can see, they simply don't match. After some tries, I ended up with the following solution: ================================== IMPORTANT NOTES: - It works for Prestashop V1.4.7X (needs to be tested for other versions); - DO A BACKUP BEFORE ANY CHANGES IN YOUR DATABASE/CODE; - Try it in a development environment; - I'm obviously not responsible if you screw your shop; - Have I already mentioned to do backups? - English is my second language. Sorry you grammar nazis. DATABASE: 1) Export the prefix_customers table from Zen-Cart / OSCommerce / OpenCart into a CSV file; 2) Import your users through Prestashop's CSV Import tool; 3) Create this table in your Prestashop database: CREATE TABLE zc_legacy_passwords ( id INT NOT NULL, PRIMARY KEY(id), email VARCHAR(100), password VARCHAR(35), updated BOOLEAN NOT NULL ); 4) Populate this table using the previously created .CSV file or create a .SQL file from the following query and import into the zc_legacy_passwords table: SELECT customers_id, LOWER(customers_email_address), customers_password FROM PREFIX_customers ORDER BY customers_id Now we have all the data needed to allow our customers log into Prestashop, but we still need to change how the login process work. CODING STEPS: Modify the /classes/Customer.php file with the following: 1) Look for the public function getByEmail($email, $passwd = NULL) <- line 203 2) Replace lines 217 and 218, turning it from... if (!$result) return false; ...to... // == BEGIN ZEN-CART / OSCOMMERCE TO PRESTASHOP PASSWORD INTEGRATION == // == BY João Cunha - [email protected] // == @ 31/03/2012 // == USE AND MODIFY AT WILL // == TESTED ON PRESTASHOP V1.4.7X if (!$result) { //<- INVALID PRESTASHOP LOGIN, IT MAY BE A ZEN-CART / OSCOMMERCE PASSWORD //CHECK IF THE GIVEN EMAIL MATCHES A ROW IN OUR LEGACY TABLE AND RETRIEVES THE LEGACY PASSWORD $resultZC = Db::getInstance()->getRow(' SELECT `password` FROM `zc_legacy_passwords` WHERE `email` = \''.pSQL($email).'\' AND `updated` = 0'); if (!$resultZC) return false; //<- EMAIL NOT FOUND IN NONE OF THE TABLES, SO IT IS AN INVALID LOGIN //ENCRYPTS THE GIVEN PASSWORD IN ZEN-CART / OSCOMMERCE FORMAT $salt = substr($resultZC['password'], strrpos($resultZC['password'],':')+1, 2); $ZCpassword = md5($salt . $passwd) . ':' . $salt; if ($ZCpassword != $resultZC['password']) return false; //<- WRONG ZEN-CART/OSCOMMERCE PASSWORD GIVEN //WE'LL UPDATE THE CUSTOMER TABLE WITH ITS PRESTASHOP ENCRYPTED PASSWORD... Db::getInstance()->Execute(' UPDATE `'._DB_PREFIX_ .'customer` SET `passwd` = \''.md5(pSQL(_COOKIE_KEY_.$passwd)).'\' WHERE `email` = \''.pSQL($email).'\''); //...AND FLAG IT AS UPDATED, SO THE NEXT TIME HE LOGS IN, HE WON'T ENTER THIS ROUTINE. Db::getInstance()->Execute(' UPDATE `zc_legacy_passwords` SET `updated` = 1 WHERE `email` = \''.pSQL($email).'\''); //USER IS AUTHENTICATED, OVERWRITE THE EMPTY $result VARIABLE $result = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_ .'customer` WHERE `active` = 1 AND `email` = \''.pSQL($email).'\' AND `deleted` = 0 AND `is_guest` = 0'); } // == END ZEN-CART / OSCOMMERCE TO PRESTASHOP PASSWORD INTEGRATION ================================== And you're done! I don't know if there is another way of achieving the same results without modifying the Customer.php core file, but that would be great. Since I'm a Prestashop noob, I would like to hear any thoughts from you guys. Cheers, João Cunha Brazil Edited October 21, 2012 by João Cunha (see edit history) 4 1 Link to comment Share on other sites More sharing options...
Dh42 Posted April 6, 2012 Share Posted April 6, 2012 Not that I have used zen cart recently, but that is a pretty great idea of getting things to work. Good Job Link to comment Share on other sites More sharing options...
João Cunha Posted June 13, 2012 Author Share Posted June 13, 2012 Anyone out there willing to do a class override implementation of the solution? Bonus: http://throwingfire.com/storing-passwords-securely/ Link to comment Share on other sites More sharing options...
speed3r Posted October 9, 2012 Share Posted October 9, 2012 (edited) Thanks for posting solution to this issue, it's working fine with PS1.5 as well. I found a little typo in your manual - missing "d" in DB table creation causes problems in queries further: DATABASE: 3) Create this table in your Prestashop database: CREATE TABLE zc_legacy_passwords ( `id` INT NOT NULL, PRIMARY KEY(id), `email` VARCHAR(100), `password` VARCHAR(35), `updated` BOOLEAN NOT NULL ); I made a class override for PS1.5 based on your code - you can overwrite prestashop/override/classes/Customer.php with that code instead of editing core files. <?php class Customer extends CustomerCore { public function getByEmail($email, $passwd = null) { if (!Validate::isEmail($email) || ($passwd && !Validate::isPasswd($passwd))) die (Tools::displayError()); $sql = 'SELECT * FROM `'._DB_PREFIX_.'customer` WHERE `email` = \''.pSQL($email).'\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).' '.(isset($passwd) ? 'AND `passwd` = \''.Tools::encrypt($passwd).'\'' : '').' AND `deleted` = 0 AND `is_guest` = 0'; $result = Db::getInstance()->getRow($sql); // == BEGIN ZEN-CART / OSCOMMERCE TO PRESTASHOP PASSWORD INTEGRATION == // == BY João Cunha - [email protected] // == @ 31/03/2012 // == USE AND MODIFY AT WILL // == TESTED ON PRESTASHOP V1.4.7X if (!$result) { //<- INVALID PRESTASHOP LOGIN, IT MAY BE A ZEN-CART / OSCOMMERCE PASSWORD //CHECK IF THE GIVEN EMAIL MATCHES A ROW IN OUR LEGACY TABLE AND RETRIEVES THE LEGACY PASSWORD $resultZC = Db::getInstance()->getRow(' SELECT `password` FROM `osc_legacy_passwords` WHERE `email` = \''.pSQL($email).'\' AND `updated` = 0'); if (!$resultZC) return false; //<- EMAIL NOT FOUND IN NONE OF THE TABLES, SO IT IS AN INVALID LOGIN //ENCRYPTS THE GIVEN PASSWORD IN ZEN-CART / OSCOMMERCE FORMAT $salt = substr($resultZC['password'], strrpos($resultZC['password'],':')+1, 2); $ZCpassword = md5($salt . $passwd) . ':' . $salt; if ($ZCpassword != $resultZC['password']) return false; //<- WRONG ZEN-CART/OSCOMMERCE PASSWORD GIVEN //WE'LL UPDATE THE CUSTOMER TABLE WITH ITS PRESTASHOP ENCRYPTED PASSWORD... Db::getInstance()->Execute(' UPDATE `'._DB_PREFIX_ .'customer` SET `passwd` = \''.md5(pSQL(_COOKIE_KEY_.$passwd)).'\' WHERE `email` = \''.pSQL($email).'\''); //...AND FLAG IT AS UPDATED, SO THE NEXT TIME HE LOGS IN, HE WON'T ENTER THIS ROUTINE. Db::getInstance()->Execute(' UPDATE `osc_legacy_passwords` SET `updated` = 1 WHERE `email` = \''.pSQL($email).'\''); //USER IS AUTHENTICATED, OVERWRITE THE EMPTY $result VARIABLE $result = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_ .'customer` WHERE `active` = 1 AND `email` = \''.pSQL($email).'\' AND `deleted` = 0 AND `is_guest` = 0'); } // == END ZEN-CART / OSCOMMERCE TO PRESTASHOP PASSWORD INTEGRATION $this->id = $result['id_customer']; foreach ($result as $key => $value) if (key_exists($key, $this)) $this->{$key} = $value; return $this; } } EDIT: Forgot to mention - I've renamed legacy passwords table name to osc_legacy_passwords so you'll probably have to rename it (either table name in DB or hardcoded in script). Edited October 9, 2012 by speed3r (see edit history) 2 Link to comment Share on other sites More sharing options...
João Cunha Posted October 21, 2012 Author Share Posted October 21, 2012 Thanks for posting solution to this issue, it's working fine with PS1.5 as well. I found a little typo in your manual - missing "d" in DB table creation causes problems in queries further: Good catch. Post edited accordingly. I made a class override for PS1.5 based on your code - you can overwrite prestashop/override/classes/Customer.php with that code instead of editing core files. (...) EDIT: Forgot to mention - I've renamed legacy passwords table name to osc_legacy_passwords so you'll probably have to rename it (either table name in DB or hardcoded in script). Awesome, man! Didn't test it yet but it looks all good. Thanks a lot! Link to comment Share on other sites More sharing options...
SWS19 Posted October 21, 2012 Share Posted October 21, 2012 Hello, Excellent contribution! I'm moving over from CubeCart v4 to Prestashop 1.5 and need a little help adapting this method for use. CC stores the md5 password and a 6 digit salt in seperate table columns. I guessed I'd have to add the salt column to the legacy table and somehow modify the two parts of code below: $resultZC = Db::getInstance()->getRow(' SELECT `password` FROM `zc_legacy_passwords` WHERE `email` = \''.pSQL($email).'\' AND `updated` = 0'); //ENCRYPTS THE GIVEN PASSWORD IN ZEN-CART / OSCOMMERCE FORMAT $salt = substr($resultZC['password'], strrpos($resultZC['password'],':')+1, 2); $ZCpassword = md5($salt . $passwd) . ':' . $salt; So far I've not had much luck. Is anyone able to help please? Thanks, Steve Link to comment Share on other sites More sharing options...
João Cunha Posted October 21, 2012 Author Share Posted October 21, 2012 (edited) I'm moving over from CubeCart v4 to Prestashop 1.5 and need a little help adapting this method for use. CC stores the md5 password and a 6 digit salt in seperate table columns. I guessed I'd have to add the salt column to the legacy table and somehow modify the two parts of code below: (...) So far I've not had much luck. Is anyone able to help please? Hi, Steve! It looks pretty straightforward. All you should do is to concatenate both fields (password and salt) and then remove the substr() method from the equation. You could save the salt in a field called 'salt' on your legacy table and then retrieve both password and salt. Do you know if the salt goes on the begining or the end of the string? João Cunha Edited October 21, 2012 by João Cunha (see edit history) Link to comment Share on other sites More sharing options...
SWS19 Posted October 21, 2012 Share Posted October 21, 2012 (edited) Thanks for the quick reply. I've searched around and I think the salt is before the password. I've tried the below, am I going in the right direction? $resultZC = Db::getInstance()->getRow(' SELECT `password`, `salt` FROM `cc_legacy_passwords` WHERE `email` = \''.pSQL($email).'\' AND `updated` = 0'); and //ENCRYPTS THE GIVEN PASSWORD IN ZEN-CART / OSCOMMERCE FORMAT $salt = $resultZC['salt']; $ZCpassword = md5($salt . $passwd); Edit: meant to say I added a 'salt' column to the cc_legacy_passwords table. Edited October 21, 2012 by SWS19 (see edit history) Link to comment Share on other sites More sharing options...
SWS19 Posted October 22, 2012 Share Posted October 22, 2012 Still struggling concatenate both fields. There's a snippet of CubeCart code below on how it puts the salt and pass together: $pass_hash = md5(md5($salt).md5($pass)); Not sure if that helps anyone help me. Thanks, Steve Link to comment Share on other sites More sharing options...
bvelichkov Posted January 5, 2013 Share Posted January 5, 2013 Thanks for the idea, guys!!!! I had to rewrite almost everything, because I'm migrating from a custom system to Prestashop, but your clue was priceless. Thanks once again!!! Link to comment Share on other sites More sharing options...
Rapture Posted January 7, 2013 Share Posted January 7, 2013 Did you get to move the password database from cubecart to prestashop? I'm having the same trouble. Still struggling concatenate both fields. There's a snippet of CubeCart code below on how it puts the salt and pass together: $pass_hash = md5(md5($salt).md5($pass)); Not sure if that helps anyone help me. Thanks, Steve Link to comment Share on other sites More sharing options...
PhiLho Posted January 8, 2013 Share Posted January 8, 2013 An excellent idea, that will be extremely useful to us as well. Thanks, João Cunha, for the idea and initial implementation, and speed3r for the override implementation. Congratulations. Link to comment Share on other sites More sharing options...
Porpoise Posted March 26, 2013 Share Posted March 26, 2013 Thanks for posting solution to this issue, it's working fine with PS1.5 as well. I found a little typo in your manual - missing "d" in DB table creation causes problems in queries further: I made a class override for PS1.5 based on your code - you can overwrite prestashop/override/classes/Customer.php with that code instead of editing core files. <?php Snipped to save space } EDIT: Forgot to mention - I've renamed legacy passwords table name to osc_legacy_passwords so you'll probably have to rename it (either table name in DB or hardcoded in script). Thanks for that. I was beginning to think we would have to get our existing clients to generate new accounts. Although it would be nice to be able to import their addresses and previous order data as well. Link to comment Share on other sites More sharing options...
tinyDev Posted April 23, 2013 Share Posted April 23, 2013 (edited) For CubeCart follow Joao's original (and great!) instructions with the below modifications: We need to add an additional salt column into our legacy database table as below: CREATE TABLE cc_legacy_passwords ( id INT NOT NULL, PRIMARY KEY(id), email VARCHAR(100), password VARCHAR(32), salt VARCHAR(6), updated BOOLEAN NOT NULL ); Next I've modified the code so that encrypts in the CubeCart format (it will concatenate the password and salt before checking if it's valid). I've also added a snippet of code to generate a random secure key for the customer upon their return and login. <?php class Customer extends CustomerCore { public function getByEmail($email, $passwd = null) { if (!Validate::isEmail($email) || ($passwd && !Validate::isPasswd($passwd))) die (Tools::displayError()); $sql = 'SELECT * FROM `'._DB_PREFIX_.'customer` WHERE `email` = \''.pSQL($email).'\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).' '.(isset($passwd) ? 'AND `passwd` = \''.Tools::encrypt($passwd).'\'' : '').' AND `deleted` = 0 AND `is_guest` = 0'; $result = Db::getInstance()->getRow($sql); // == BEGIN CubeCart TO PRESTASHOP PASSWORD INTEGRATION == // == BY João Cunha - [email protected] // == @ 31/03/2012 // == Updated for CubeCart by tinyDev // == @ 12/01/2013 // == USE AND MODIFY AT WILL // == TESTED ON PRESTASHOP V1.5.3.X if (!$result) { //<- INVALID PRESTASHOP LOGIN, IT MAY BE A CubeCart PASSWORD //CHECK IF THE GIVEN EMAIL MATCHES A ROW IN OUR LEGACY TABLE AND RETRIEVES THE LEGACY PASSWORD $resultZC = Db::getInstance()->getRow(' SELECT `password`, `salt` FROM `cc_legacy_passwords` WHERE `email` = \''.pSQL($email).'\' AND `updated` = 0'); if (!$resultZC) return false; //<- EMAIL NOT FOUND IN NONE OF THE TABLES, SO IT IS AN INVALID LOGIN //ENCRYPTS THE GIVEN PASSWORD IN CubeCart FORMAT $salt = $resultZC['salt']; $ZCpassword = md5(md5($salt).md5($passwd)); if ($ZCpassword != $resultZC['password']) return false; //<- WRONG CubeCart PASSWORD GIVEN //WE'LL UPDATE THE CUSTOMER TABLE WITH ITS PRESTASHOP ENCRYPTED PASSWORD Db::getInstance()->Execute(' UPDATE `'._DB_PREFIX_ .'customer` SET `passwd` = \''.md5(pSQL(_COOKIE_KEY_.$passwd)).'\' WHERE `email` = \''.pSQL($email).'\''); //SET RANDOM SECURE_KEY [ADDED BY tinyDev] Db::getInstance()->Execute(' UPDATE `'._DB_PREFIX_ .'customer` SET `secure_key` = \''.md5(uniqid(rand(), true)).'\' WHERE `email` = \''.pSQL($email).'\' AND `secure_key` = \''.pSQL($secure_key['']).'\''); //...AND FLAG IT AS UPDATED, SO THE NEXT TIME HE LOGS IN, HE WON'T ENTER THIS ROUTINE. Db::getInstance()->Execute(' UPDATE `cc_legacy_passwords` SET `updated` = 1 WHERE `email` = \''.pSQL($email).'\''); //USER IS AUTHENTICATED, OVERWRITE THE EMPTY $result VARIABLE $result = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_ .'customer` WHERE `active` = 1 AND `email` = \''.pSQL($email).'\' AND `deleted` = 0 AND `is_guest` = 0'); } // == END CubeCart TO PRESTASHOP PASSWORD INTEGRATION $this->id = $result['id_customer']; foreach ($result as $key => $value) if (key_exists($key, $this)) $this->{$key} = $value; return $this; } } Hope that helps others. tinyDev Edited April 23, 2013 by tinyDev (see edit history) Link to comment Share on other sites More sharing options...
timonia Posted May 28, 2013 Share Posted May 28, 2013 (edited) This modification also works on older versions of Prestashop. There's just one small part of code to be removed, because this column (is_guest) doesn't exist in older versions. Just change the following code: AND `deleted` = 0 AND `is_guest` = 0'); Into: AND `deleted` = 0'); That's all. Edited May 28, 2013 by timonia (see edit history) Link to comment Share on other sites More sharing options...
Jota. Posted February 3, 2014 Share Posted February 3, 2014 Thanks for posting solution to this issue, it's working fine with PS1.5 as well. I found a little typo in your manual - missing "d" in DB table creation causes problems in queries further: I made a class override for PS1.5 based on your code - you can overwrite prestashop/override/classes/Customer.php with that code instead of editing core files. <?php class Customer extends CustomerCore { public function getByEmail($email, $passwd = null) { if (!Validate::isEmail($email) || ($passwd && !Validate::isPasswd($passwd))) die (Tools::displayError()); $sql = 'SELECT * FROM `'._DB_PREFIX_.'customer` WHERE `email` = \''.pSQL($email).'\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).' '.(isset($passwd) ? 'AND `passwd` = \''.Tools::encrypt($passwd).'\'' : '').' AND `deleted` = 0 AND `is_guest` = 0'; $result = Db::getInstance()->getRow($sql); // == BEGIN ZEN-CART / OSCOMMERCE TO PRESTASHOP PASSWORD INTEGRATION == // == BY João Cunha - [email protected] // == @ 31/03/2012 // == USE AND MODIFY AT WILL // == TESTED ON PRESTASHOP V1.4.7X if (!$result) { //<- INVALID PRESTASHOP LOGIN, IT MAY BE A ZEN-CART / OSCOMMERCE PASSWORD //CHECK IF THE GIVEN EMAIL MATCHES A ROW IN OUR LEGACY TABLE AND RETRIEVES THE LEGACY PASSWORD $resultZC = Db::getInstance()->getRow(' SELECT `password` FROM `osc_legacy_passwords` WHERE `email` = \''.pSQL($email).'\' AND `updated` = 0'); if (!$resultZC) return false; //<- EMAIL NOT FOUND IN NONE OF THE TABLES, SO IT IS AN INVALID LOGIN //ENCRYPTS THE GIVEN PASSWORD IN ZEN-CART / OSCOMMERCE FORMAT $salt = substr($resultZC['password'], strrpos($resultZC['password'],':')+1, 2); $ZCpassword = md5($salt . $passwd) . ':' . $salt; if ($ZCpassword != $resultZC['password']) return false; //<- WRONG ZEN-CART/OSCOMMERCE PASSWORD GIVEN //WE'LL UPDATE THE CUSTOMER TABLE WITH ITS PRESTASHOP ENCRYPTED PASSWORD... Db::getInstance()->Execute(' UPDATE `'._DB_PREFIX_ .'customer` SET `passwd` = \''.md5(pSQL(_COOKIE_KEY_.$passwd)).'\' WHERE `email` = \''.pSQL($email).'\''); //...AND FLAG IT AS UPDATED, SO THE NEXT TIME HE LOGS IN, HE WON'T ENTER THIS ROUTINE. Db::getInstance()->Execute(' UPDATE `osc_legacy_passwords` SET `updated` = 1 WHERE `email` = \''.pSQL($email).'\''); //USER IS AUTHENTICATED, OVERWRITE THE EMPTY $result VARIABLE $result = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_ .'customer` WHERE `active` = 1 AND `email` = \''.pSQL($email).'\' AND `deleted` = 0 AND `is_guest` = 0'); } // == END ZEN-CART / OSCOMMERCE TO PRESTASHOP PASSWORD INTEGRATION $this->id = $result['id_customer']; foreach ($result as $key => $value) if (key_exists($key, $this)) $this->{$key} = $value; return $this; } }EDIT: Forgot to mention - I've renamed legacy passwords table name to osc_legacy_passwords so you'll probably have to rename it (either table name in DB or hardcoded in script). First of all thanks for this code, I thought that I have found a solution to my passwords problem (I'm migrating from Oscommerce to Prestashop) BUT I'm afraid that something is wrong, I have followed your instructions but it doesn't work for me, I get this error: "There is 1 error - Authentication failed" Seems like it's not checking the new osc_legacy_passwords table ... I'm using PrestaShop 1.5.6.2 version I created the new table using: CREATE TABLE osc_legacy_passwords ( id INT NOT NULL, PRIMARY KEY(id), email VARCHAR(100), password VARCHAR(35), updated BOOLEAN NOT NULL ); And a new customer class (Customer.php) in override folder with speed3r code I have to say that I don't have a clue of Php, so any help is welcome. Thanks in advance. Link to comment Share on other sites More sharing options...
Afriluka Posted February 24, 2014 Share Posted February 24, 2014 (edited) Hello guys, I have the same problem as Jota. When I install the override Customer.php it seems like the store is ignoring the new table with the old oscommerce passwords. Btw. My Prestashopversion is 1.5.6.1 When I change the corefile /classes/Customer.php like Joao Cunha described it, it is working. But of course it would be better to use a overridefile. So what could be the reason? What do we have to change? Matt Edited February 24, 2014 by Afriluka (see edit history) Link to comment Share on other sites More sharing options...
Jota. Posted February 24, 2014 Share Posted February 24, 2014 Hello guys, I have the same problem as Jota. When I install the override Customer.php it seems like the store is ignoring the new table with the old oscommerce passwords. Btw. My Prestashopversion is 1.5.6.1 When I change the corefile /classes/Customer.php like Joao Cunha described it, it is working. But of course it would be better to use a overridefile. So what could be the reason? What do we have to change? Matt Hi Matt, after going crazy with this, and many hours of time lost, I finally discovered that the solution was extremely easy (http://www.prestashop.com/forums/topic/238197-solved-overrides-not-working-anymore-in-154/)... when you place something in override folder you have to delete the file "class_index.php" in cache folder. After doing that it works like a charm. (I did a security back up before deleting just in case) Hope this helps. Kind regards. Jon. Link to comment Share on other sites More sharing options...
san_merah Posted May 13, 2014 Share Posted May 13, 2014 Will; above solution work with Presta 1.6? Link to comment Share on other sites More sharing options...
libris86 Posted October 27, 2014 Share Posted October 27, 2014 Thanks fo all, This solution work fine for me with Oscommerce 2.x and prestashop 1.5.x (solution João) and work fine too with overide classe other solution. I test it with success For an other projetc, i must migrate Oscommerce 2.x to prestashop 1.6.0.9 Any idea too help me for coding solution ? Best regard, Eric Link to comment Share on other sites More sharing options...
jrstafford1 Posted January 27, 2015 Share Posted January 27, 2015 Thanks for the posts. I used this and modified to make it work with a transition from Wordpress to Prestashop 1.6.0.9. Anyone that needs assistance with WP to Prestashop let me know. Link to comment Share on other sites More sharing options...
edlman Posted February 27, 2015 Share Posted February 27, 2015 Hello, I took an inspiration from the code here. I tried it with osCommerce 2.3.4 and it didn't work. Passwords in osC 2.3.4 are stored in newer format $P$md5hash without :salt. So I took the code from here, code from osC for password manipulation and combined them to one. Copy the code and store it to prestashop/override/classes/Customer.php. Don't forget to remove prestashop/cache/class_index.php, otherwise this new Customer class won't be found and used. I don't use support table for legacy osC account. I have osC passwords in PrestaShop customers table. When PrestaShop password fails, I try to authenticate with osC password. If it succeed then I update the password to PrestaShop and reauthenticate with PrestaShop password to proceed. <?php class Customer extends CustomerCore { public function getByEmail($email, $passwd = null) { if(!Validate::isEmail($email) || ($passwd && !Validate::isPasswd($passwd))) die(Tools::displayError()); $db = Db::getInstance(); $sql = 'SELECT * FROM `' . _DB_PREFIX_ . 'customer` WHERE `email` = \'' . pSQL($email) . '\' ' . Shop::addSqlRestriction(Shop::SHARE_CUSTOMER) . ' ' . (isset($passwd) ? 'AND `passwd` = \'' . Tools::encrypt($passwd) . '\'' : '') . ' AND `deleted` = 0 '.($ignore_guest ? ' AND `is_guest` = 0' : ''); $result = $db->getRow($sql); // == BEGIN OSCOMMERCE TO PRESTASHOP PASSWORD INTEGRATION == // == BY Martin Edlman - [email protected] // == @ 27/2/2014 // == USE AND MODIFY AT WILL // == TESTED ON PRESTASHOP V1.6.X if(! $result) { // <- INVALID PRESTASHOP LOGIN, IT MAY BE AN OSCOMMERCE PASSWORD $resultOSC = $db->getRow(' SELECT `passwd` FROM `' . _DB_PREFIX_ . 'customer` WHERE `email` = \'' . pSQL($email) . '\' ' . Shop::addSqlRestriction(Shop::SHARE_CUSTOMER) . ' AND `deleted` = 0 '.($ignore_guest ? ' AND `is_guest` = 0' : '')); if(! $resultOSC) return false; // <- EMAIL NOT FOUND, SO IT IS AN INVALID LOGIN if(! OSCPassword::check($passwd, $resultOSC['passwd'])) return false; // <- WRONG OSCOMMERCE PASSWORD GIVEN // WE'LL UPDATE THE CUSTOMER TABLE WITH ITS PRESTASHOP ENCRYPTED PASSWORD... $db->Execute(' UPDATE `' . _DB_PREFIX_ . 'customer` SET `passwd` = \'' . md5(pSQL(_COOKIE_KEY_ . $passwd)) . '\' WHERE `email` = \'' . pSQL($email) . '\''); // REUSE ORIGINAL SQL TO AUTHENTICATE WITH UPDATED PRESTASHOP PASSWORD $result = $db->getRow($sql); } // == END OSCOMMERCE TO PRESTASHOP PASSWORD INTEGRATION $this->id = $result['id_customer']; foreach($result as $key => $value) if(key_exists($key, $this)) $this->{$key} = $value; return $this; } } class OSCPassword { private static $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; private static function encode64($input, $count) { $output = ''; $i = 0; do { $value = ord($input[$i++]); $output .= self::$itoa64[$value & 0x3f]; if($i < $count) $value |= ord($input[$i]) << 8; $output .= self::$itoa64[($value >> 6) & 0x3f]; if($i++ >= $count) break; if($i < $count) $value |= ord($input[$i]) << 16; $output .= self::$itoa64[($value >> 12) & 0x3f]; if($i++ >= $count) break; $output .= self::$itoa64[($value >> 18) & 0x3f]; } while($i < $count); return $output; } private static function crypt($password, $setting) { $output = '*0'; if(substr($setting, 0, 2) == $output) $output = '*1'; $id = substr($setting, 0, 3); // We use "$P$", phpBB3 uses "$H$" for the same thing if($id != '$P$' && $id != '$H$') return $output; $count_log2 = strpos(self::$itoa64, $setting[3]); if($count_log2 < 7 || $count_log2 > 30) return $output; $count = 1 << $count_log2; $salt = substr($setting, 4, 8); if(strlen($salt) != 8) return $output; // We're kind of forced to use MD5 here since it's the only // cryptographic primitive available in all versions of PHP // currently in use. To implement our own low-level crypto // in PHP would result in much worse performance and // consequently in lower iteration counts and hashes that are // quicker to crack (by non-PHP code). if(PHP_VERSION >= '5') { $hash = md5($salt . $password, TRUE); do { $hash = md5($hash . $password, TRUE); } while(--$count); } else { $hash = pack('H*', md5($salt . $password)); do { $hash = pack('H*', md5($hash . $password)); } while(--$count); } $output = substr($setting, 0, 12); $output .= self::encode64($hash, 16); return $output; } public static function check($password, $stored_hash) { $hash = self::crypt($password, $stored_hash); if($hash[0] == '*') $hash = crypt($password, $stored_hash); // PrestaShop has varchar(32) for password return substr($hash, 0, 32) == $stored_hash; } } ?> I hope this will help someone. Regards Martin 1 Link to comment Share on other sites More sharing options...
mrelo Posted March 30, 2015 Share Posted March 30, 2015 I know it's not realted to this topic, but does anybody have a solution for joomla 1.5.26 to the newest 1.6.0.14 (VM 1.1.9)? I try to use this script (with little modifications) but no luck. Link to comment Share on other sites More sharing options...
Arteinfo Posted May 28, 2015 Share Posted May 28, 2015 Hi there! This is my first contribution to the community. I hope it helps someone. I would like to share my approach on how to integrate Zen-Cart / OSCommerce passwords with Prestashop. I have a Zen-Cart shop with 50k registered customers which I am migrating to Prestashop. The "Back Office -> Tools -> CSV Import" tool works like a charm to import your customers but they will not be able to login on Prestashop because passwords are encrypted in different ways on both store managers. Thank you! It worked well in PS 1.6.14 Link to comment Share on other sites More sharing options...
serpeal79 Posted June 2, 2015 Share Posted June 2, 2015 Hi. I've tried this with a Prestashop 1.6.14 and the original solution by Joao Cunha works fine. I don't understand why, but the override solution doesn't work. It seems prestashop is not accessing the override file Customer.php. File permissions are -rw-r--rw-, shouldn't it work? Thanks Joao and speed3r Link to comment Share on other sites More sharing options...
serpeal79 Posted June 5, 2015 Share Posted June 5, 2015 (edited) Hi again. I found out why the override solution didn't work for me in my Prestashop 1.6.14. In order to make the override solution to work you must delete: ./prestashop/cache/class_index.php And since getByEmail headers have changed from 1.5 till 1.6.14, the override file for 1.6.14 should contain this: <?php class Customer extends CustomerCore { public function getByEmail($email, $passwd = null, $ignore_guest = true) { if (!Validate::isEmail($email) || ($passwd && !Validate::isPasswd($passwd))) die (Tools::displayError()); $result = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.'customer` WHERE `email` = \''.pSQL($email).'\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).' '.(isset($passwd) ? 'AND `passwd` = \''.pSQL(Tools::encrypt($passwd)).'\'' : '').' AND `deleted` = 0 '.($ignore_guest ? ' AND `is_guest` = 0' : '')); // == BEGIN ZEN-CART / OSCOMMERCE TO PRESTASHOP PASSWORD INTEGRATION == // == BY João Cunha - [email protected] // == @ 31/03/2012 // == USE AND MODIFY AT WILL // == TESTED ON PRESTASHOP V1.4.7X if (!$result) { //<- INVALID PRESTASHOP LOGIN, IT MAY BE A ZEN-CART / OSCOMMERCE PASSWORD //CHECK IF THE GIVEN EMAIL MATCHES A ROW IN OUR LEGACY TABLE AND RETRIEVES THE LEGACY PASSWORD $resultZC = Db::getInstance()->getRow(' SELECT `password` FROM `zc_legacy_passwords` WHERE `email` = \''.pSQL($email).'\' AND `updated` = 0'); if (!$resultZC) return false; //<- EMAIL NOT FOUND IN NONE OF THE TABLES, SO IT IS AN INVALID LOGIN //ENCRYPTS THE GIVEN PASSWORD IN ZEN-CART / OSCOMMERCE FORMAT $salt = substr($resultZC['password'], strrpos($resultZC['password'],':')+1, 2); $ZCpassword = md5($salt . $passwd) . ':' . $salt; if ($ZCpassword != $resultZC['password']) return false; //<- WRONG ZEN-CART/OSCOMMERCE PASSWORD GIVEN //WE'LL UPDATE THE CUSTOMER TABLE WITH ITS PRESTASHOP ENCRYPTED PASSWORD... Db::getInstance()->Execute(' UPDATE `'._DB_PREFIX_ .'customer` SET `passwd` = \''.md5(pSQL(_COOKIE_KEY_.$passwd)).'\' WHERE `email` = \''.pSQL($email).'\''); //...AND FLAG IT AS UPDATED, SO THE NEXT TIME HE LOGS IN, HE WON'T ENTER THIS ROUTINE. Db::getInstance()->Execute(' UPDATE `zc_legacy_passwords` SET `updated` = 1 WHERE `email` = \''.pSQL($email).'\''); //USER IS AUTHENTICATED, OVERWRITE THE EMPTY $result VARIABLE $result = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_ .'customer` WHERE `active` = 1 AND `email` = \''.pSQL($email).'\' AND `deleted` = 0 AND `is_guest` = 0'); } // == END ZEN-CART / OSCOMMERCE TO PRESTASHOP PASSWORD INTEGRATION $this->id = $result['id_customer']; foreach ($result as $key => $value) if (array_key_exists($key, $this)) $this->{$key} = $value; return $this; } } I hope this helps. Kind regards. Edited June 5, 2015 by serpeal79 (see edit history) 2 Link to comment Share on other sites More sharing options...
Styg82 Posted October 1, 2015 Share Posted October 1, 2015 Helped me a lot! I just migrated users from xt:commerce Veyton to prestashop. Link to comment Share on other sites More sharing options...
zod Posted November 5, 2015 Share Posted November 5, 2015 I confirm this is working in Prestashop 1.6.1.1, i just migrated from Zen Cart 1.3.9. I used the override class of serpeal79. 1 Link to comment Share on other sites More sharing options...
robert.zak Posted March 31, 2016 Share Posted March 31, 2016 Thanks for the fix and I'm glad it worked for many of you. Unfortunately it doest work with oscommerce 2.3.1 and the latest prestashop. I've tried Martins code also but no luck Rob Link to comment Share on other sites More sharing options...
tarmogr Posted December 16, 2016 Share Posted December 16, 2016 Thanks for the fix and I'm glad it worked for many of you. Unfortunately it doest work with oscommerce 2.3.1 and the latest prestashop. I've tried Martins code also but no luck Rob It works, I have operated oscommerce from version 2.3 through 2.3.3.4 and all my test accounts from various versions of osc worked. I used eldman code but I had to upgrade it since his code is not for presta 1.6.1.10. Also if you use eldman solution you cant import passwords via prestashop CSV function (other data can), need to use phpmyadmin/sql query. code for prsta v. 1.6.1.10 override/Customer.php: <?php class Customer extends CustomerCore { public function getByEmail($email, $passwd = null, $ignore_guest = true) { if (!Validate::isEmail($email) || ($passwd && !Validate::isPasswd($passwd))) { die(Tools::displayError()); } $result = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.'customer` WHERE `email` = \''.pSQL($email).'\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).' '.(isset($passwd) ? 'AND `passwd` = \''.pSQL(Tools::encrypt($passwd)).'\'' : '').' AND `deleted` = 0 '.($ignore_guest ? ' AND `is_guest` = 0' : '')); // == BEGIN OSCOMMERCE TO PRESTASHOP PASSWORD INTEGRATION == // == BY Martin Edlman - [email protected] // == @ 27/2/2014 // == USE AND MODIFY AT WILL // == TESTED ON PRESTASHOP V1.6.X if(! $result) { // <- INVALID PRESTASHOP LOGIN, IT MAY BE AN OSCOMMERCE PASSWORD $resultOSC = Db::getInstance()->getRow(' SELECT `passwd` FROM `' . _DB_PREFIX_ . 'customer` WHERE `email` = \'' . pSQL($email) . '\' ' . Shop::addSqlRestriction(Shop::SHARE_CUSTOMER) . ' AND `deleted` = 0 '.($ignore_guest ? ' AND `is_guest` = 0' : '')); if(! $resultOSC) return false; // <- EMAIL NOT FOUND, SO IT IS AN INVALID LOGIN if(! OSCPassword::check($passwd, $resultOSC['passwd'])) return false; // <- WRONG OSCOMMERCE PASSWORD GIVEN // WE'LL UPDATE THE CUSTOMER TABLE WITH ITS PRESTASHOP ENCRYPTED PASSWORD... Db::getInstance()->Execute(' UPDATE `' . _DB_PREFIX_ . 'customer` SET `passwd` = \'' . md5(pSQL(_COOKIE_KEY_ . $passwd)) . '\' WHERE `email` = \'' . pSQL($email) . '\''); // REUSE ORIGINAL SQL TO AUTHENTICATE WITH UPDATED PRESTASHOP PASSWORD $result = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.'customer` WHERE `email` = \''.pSQL($email).'\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).' '.(isset($passwd) ? 'AND `passwd` = \''.pSQL(Tools::encrypt($passwd)).'\'' : '').' AND `deleted` = 0 '.($ignore_guest ? ' AND `is_guest` = 0' : '')); if(! $result) { return false; //incase our password rewrite does not match prestashop authentication } } // == END OSCOMMERCE TO PRESTASHOP PASSWORD INTEGRATION $this->id = $result['id_customer']; foreach ($result as $key => $value) { if (property_exists($this, $key)) { $this->{$key} = $value; } } return $this; } } class OSCPassword { private static $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; private static function encode64($input, $count) { $output = ''; $i = 0; do { $value = ord($input[$i++]); $output .= self::$itoa64[$value & 0x3f]; if($i < $count) $value |= ord($input[$i]) << 8; $output .= self::$itoa64[($value >> 6) & 0x3f]; if($i++ >= $count) break; if($i < $count) $value |= ord($input[$i]) << 16; $output .= self::$itoa64[($value >> 12) & 0x3f]; if($i++ >= $count) break; $output .= self::$itoa64[($value >> 18) & 0x3f]; } while($i < $count); return $output; } private static function crypt($password, $setting) { $output = '*0'; if(substr($setting, 0, 2) == $output) $output = '*1'; $id = substr($setting, 0, 3); // We use "$P$", phpBB3 uses "$H$" for the same thing if($id != '$P$' && $id != '$H$') return $output; $count_log2 = strpos(self::$itoa64, $setting[3]); if($count_log2 < 7 || $count_log2 > 30) return $output; $count = 1 << $count_log2; $salt = substr($setting, 4, 8); if(strlen($salt) != 8) return $output; // We're kind of forced to use MD5 here since it's the only // cryptographic primitive available in all versions of PHP // currently in use. To implement our own low-level crypto // in PHP would result in much worse performance and // consequently in lower iteration counts and hashes that are // quicker to crack (by non-PHP code). if(PHP_VERSION >= '5') { $hash = md5($salt . $password, TRUE); do { $hash = md5($hash . $password, TRUE); } while(--$count); } else { $hash = pack('H*', md5($salt . $password)); do { $hash = pack('H*', md5($hash . $password)); } while(--$count); } $output = substr($setting, 0, 12); $output .= self::encode64($hash, 16); return $output; } public static function check($password, $stored_hash) { $hash = self::crypt($password, $stored_hash); if($hash[0] == '*') $hash = crypt($password, $stored_hash); // PrestaShop has varchar(32) for password return substr($hash, 0, 32) == $stored_hash; } } ?> Link to comment Share on other sites More sharing options...
Matte01990 Posted December 20, 2016 Share Posted December 20, 2016 (edited) Hello tarmogr, thank you for sharing your code. I'm trying to migrate customers from magento to prestashop 1.6.1.7. Where should I add ''class OSCPassword''? In Customer.php as well? I'm having some issues with your code :/ ''old'' magento passwords still have the salt suffix.Should I create a support/legacy table? thank you Edited December 20, 2016 by Matte01990 (see edit history) Link to comment Share on other sites More sharing options...
tarmogr Posted December 20, 2016 Share Posted December 20, 2016 Hello Matte If you use the same code as I did, there is no need for separate table. You should copy the whole code above to the override/Customers.php file You then need to modify the class OSCPassword class according to magento algorithm. I used print_r($some_variable); to debug the code and see contents of variables. Link to comment Share on other sites More sharing options...
electriz Posted May 18, 2018 Share Posted May 18, 2018 Works flawlessly on 1.6 (tested on oscommerce).. Thanks to João Cunha and everyone who contributed in this topic. Link to comment Share on other sites More sharing options...
sanji_japan Posted March 5, 2021 Share Posted March 5, 2021 This is really a useful code! I am migrating a heavily modified old Zen Cart store to Prestashop 1.7... would this code work also on 1.7 ? Thanks Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now