2016/10/31

Secure your shop against brute force attacks!

Magento published a post which says that some URLs in your Magento installation may vulnerable to brute force attacks and they talk about an increasing number of attacks on Magento stores.

Secure /admin path

This URL leads you to your adminpanel with a default Magento installation. You should change that path URI to something cryptic to increase your security level.
You can do that in your Magento system configuration: Advanced > Admin.
Additionally you can secure it by denying all access by .htaccess except your IP:

order deny,allow
deny from all
allow from x.x.x.x

 

Secure /rss/catalog and /rss/order

This can be done by adding new rewrite conditions to your .htacces.
Add these lines to your /magento_root/.htaccess:

## block access to admin rss feed
    RewriteCond %{REQUEST_URI} ^.*/rss/catalog[OR,NC]
    RewriteCond %{REQUEST_URI} ^.*/rss/order[NC]
    RewriteRule ^(.*)$ https://%{HTTP_HOST}/ [R=302,L]

This will redirect the /rss/ feed directly to your homepage. If you have no SSL change the last line to

RewriteRule ^(.*)$ http://%{HTTP_HOST}/ [R=302,L]

But you should add SSL to your shop.

Secure /downloader 

This path is used to install or uninstall modules in your shop. To secure this place from unauthorized access we have to deny access with the .htaccess in the /downloader folder. Add these lines to your /downloader/.htaccess file:

order deny,allow
deny from all

If you want to use the downloader, you can temporary comment these lines or whitelist your IP, if you add this line:

allow from x.x.x.x

Check other vulnerabilities.

To be sure you secured all known vulnerabilities, this page is good to check states of all available patches: https://www.magereport.com/

2016/10/30

How to crop an image in Magento 1.x

We can easily render an image in Magento through the delivered Varien_Image library.

Here is an example for a class method (e.g. for a helper):

public function getCroppedImage($imageSource,
        $top,
        $left,
        $right,
        $bottom)
    {
        $mediaPathSegment = "yourfolder/cache/";
        if(!$imageSource) {
            return false;
        }
        $destinationFilepath = Mage::getBaseDir('base') . "/media/" . $mediaPathSegment . basename($imageSource);

        // only render, if source file exists and destination file does not (to prevent rendering on every page request
        if(file_exists($imageSource) && !file_exists($destinationFilepath)) {
            // render image
            $imageObj = new Varien_Image($imageSource);
            // crop image
            $imageObj->crop($top, $left, $right, $bottom);
            // save to file
            $imageObj->save( $destinationFilepath );

            // return image url
            if(file_exists($destinationFilepath)) {
                // build url path to get image link for frontend
                return Mage::getBaseUrl('media') .$mediaPathSegment . basename($imageSource);
            } else {
                // if image could not be rendered fallback and return original image
                return $imageSource;
            }
        }
        return false;
    }

The parameter $imageSource has to be an absolute filepath to the image you want to render.

How crop() is working

Crop has four parameters: top, left, right and bottom. To understand how the crop method is working you take an imaginary line which is parallel to the side you set. If you increase the value, the imaginary line is moving to the opposite side of the image. Everything of the image that is between the specific image side and the imaginary line will be cut.

This means that

$imageObj->crop(10,10,10,10);

will cut 10 pixel from image on every side. The image will be 20 pixel smaller for width and height.
This also means, that the cropped image will keep the original ratio.

Cropping an image to a square

As another example I created a method that will cut an image to a square. This is needed sometimes to fit an image to a layout or a design. Images that are not the same format look ugly and uneasy.

/**
 * cropping images to square and resize
 *
 * @param string $imageFilename
 * @param int $resizeWidth in pixel
 * @return mixed returns new resized image url or false
 */
public function getSquareImageResized($imageFilename, $resizeWidth = null)
{
    if(!$imageFilename) {
        return false;
    }

    $mediaPathSegment = "yourfolder" . DS . "cache" . DS . "square_resized" . DS;
    $destinationFilepath = Mage::getBaseDir('base') . DS . "media" . DS . $mediaPathSegment . basename($imageFilename);

    if(file_exists($imageFilename)) {
        if(!file_exists($destinationFilepath)) {
            // render image
            $imageObj = new Varien_Image($imageFilename);
            // crop image
            $imageObj->constrainOnly( true );
            $imageObj->keepAspectRatio( true );
            $imageObj->keepFrame( false );

            // crop image
            $width = $imageObj->getOriginalWidth();
            $height = $imageObj->getOriginalHeight();

            // cut image to square
            if ($width > $height) {
                $diff = ($width-$height) / 2;
                $imageObj->crop(0, $diff, $diff, 0);
            } else {
                $diff = ($height-$width) / 2;
                $imageObj->crop($diff, 0, 0, $diff);
            }

            // resize image if needed
            if($resizeWidth != null) {
                $imageObj->resize($resizeWidth, $resizeWidth);
            }
            $imageObj->save( $destinationFilepath );
        }
        // return image url
        if(file_exists($destinationFilepath)) {
            return Mage::getBaseUrl('media') . $mediaPathSegment . basename($imageFilename);
        }else{
            return $imageFilename;
        }
    }
    return false;
}

2016/10/29

How to pay with Paypal in Magento from the Admin Panel?

If you or your sales team creates orders for your customers over the Magento adminpanel sometimes, you might came to this issue: You cannot select Paypal in the Backend order.

This seems logical if you think about the Paypal payment process: after the checkout you are redirected to the Paypal website for the purchase. This is not possible in a situation, where you are creating an order for a customer, because you do not have his password (e.g. if you talk with the customer on the phone or in person in your local store). This is a general issue for all payment options like Paypal like Sofort.com, Klarna, Billsafe and so on.

But with a little workaround, you can easily let your customers pay with Paypal while you are ordering for him in the Magento Backend.

The solution

We are adding a Backend Payment method which is called "Paypal" with no further program logic. This ensures, the order and invoice information shows the correct payment method.

BackendPayment provides payment methods like cash, debit and Paypal
After we created the order, we go to our the official Paypal website and use the "Request money" function. This allows you to enter the Paypal Email address of your customer and the amount of the order to request the money over Paypal.

For the developers 

It is easy to provide a new payment method which is only available in the admin panel and not on the customers checkout. Just create a new module with the default folders and configuration for at least models, blocks and helpers.

The first thing you need is a model which looks like the following (you have to change class names to your correct namespace):

/**
 * Grafzahl_BackendPayments
 *
 * @category    Grafzahl
 * @package     Grafzahl_BackendPayments
 * @copyright   Copyright (c) 2016 Grafzahl (https://grafzahl.io)
 * @license     https://grafzahl.io/license
 */

class Grafzahl_BackendPayments_Model_PaypalPayment
    extends Mage_Payment_Model_Method_Abstract
{
    protected $_code = 'backendpayments_paypal';
    protected $_infoBlockType = 'backendpayments/info';
    protected $_canUseInternal = true;
    protected $_canUseCheckout = false;
    protected $_canUseForMultishipping  = false;

    public function __construct()
    {
        parent::__construct();
    }
}

The second thing is to create the related block from the model in the attribute $_infoBlockType. The block just needs to extend the block Mage_Payment_Block_Info. Now check the extending block and update the methods to your needs.

Complete ready to use solution

Such a payment method, mentioned above is already available. You can download BackendPayments from our grafzahl.io store and install it in your Magento store from version 1.7.x - 1.9.x with no pain.

This will provide you three new payment methods in your admin panel order form: Paypal, Debit and Cash. You can even use any other payment provider instead of Paypal. The title can be edited in the system configuration.

With this module you can also create order with the method Cash payment and Debit Payment. If you have a little local store which you manage with a Magento Shop-System, you will be able to create orders with cash payment from your admin panel.

You can also configure if these methods should automatically create the invoice for you. For further information, check our documentation source.


2016/10/27

Why should you make your Magento Product Filter URL look sexy

Fist off - it is every URL´s right to look sexy and Magento supports readable URLs well.

But some areas are still a little bit abstract and not optimized for humans or the search engines.

Search engines like Google have very complex algorithms to rate a website. They already guess very good which content a user is searching for. Because they are rating the websites on how good they are optimized for human!

This is the reason why Magento´s default layered filter URLs are bad for humans and for SEO:
http://magento.local/men/shirts.html?color=27
Nobody knows that color=27 is blue - neither does Google (although we think Google knows everything)!
So if someone is searching for a Shirt in blue, your products won´t be in the index, because your Shirt is 27, and therefor not indexed as blue shirts ;). This may be the case for the product detail pages, where the product has it´s attributes, but here we talk about the category pages where the product collections are filtered.

To solve this problem we have created the SEO Filter URL module. It is easy to install and it works with almost no configuration.
At the end you will get URLs for your Magento  1.7, 1.8, 1.8.1, 1.9, 1.9.1, 1.9.2, 1.9.3 like:
 http://magento.local/men/shirts/filter/color/blue.html
 Also the price filter is translated. If you click filter "$140.00 and above", you will get:
http://magento1-9-3.local/men/shirts/filter/color/blue/price/from-140-and-above.html
in your browser´s address line.

For the developers among us:
It seamlessly integrates in the routing with an observer on the event controller_front_init_before. The links of the layered are change by overwriting the navigation model Mage_Catalog_Model_Layer_Filter_Item.
Also the page links of the catalog toolbar are change to get a readable "page" instead of "p=" for links in the pager.