Nov 11, 2014

Developer notes for migrating extensions to OpenCart 2

My condolences to anyone reading this.

Please note that this is not a full list of changes, as I've only been working with payment gateway extensions at the moment.

Opencart released version 2 in October 2014 with major layout and structure changes. When looking at the new version at first glance the codebase seems the same and you'd think extensions should work by default. They won't.

The first thing to notice is that they completely changed templates files - HTML structure, forms. TPL files should be completely rewritten. But at least the new admin layout looks nice.
  • Admin template files use forms, columns.
  • Catalog template files use a new default page layout
  • Any custom error template files need to adhere to the new layout.

Methods visibilty in classes is changed to public. Using private or protected will not work.
class ControllerPaymentPPStandard extends Controller {
public function index() { ...

Catalog model has a new property (terms & conditions URL) that is returned in the method data array.:
'terms'      => '',

There is no render function in controllers in version 2. Using the call
$this->render(); has been changed to
return $this->load->view($template_file, $data);
Important thing to note here is that $data must be a local variable, not a class attribute.

Redirection is changed from
$this->redirect(...)
to
$this->response->redirect(...)


Methods
$this->model_checkout_order->confirm() and
$this->model_checkout_order->update() have been changed to
$this->model_checkout_order->addOrderHistory();


May 24, 2014

VMware Workstation install error: Service VMware Authorization Service (VMAuthdService) failed to start.

I was trying to install VMware Workstation 10 on my PC when suddenly wild message appears:

Service VMware Authorization Service (VMAuthdService) failed to start.
Verify that you have sufficient privileges to start system services.


I followed all of the official VMware guides to resolve this problem but non of them worked. After pulling my hairs for a while, the solution was to disable hardware-assisted virtualization in Avast! Antivirus. Even when you disable Avast! shield control, you are unable to install Workstation without disabling hardware-assisted virtualization or uninstalling Avast!.

Open Avast!

1. Go to Settings
2. Go to Troubleshooting
3. Uncheck Enable hardware-assisted virtualization
4. Reboot
5. Profit


May 17, 2014

HttpsURLConnection POST example with NameValuePair and UrlEncodedFormEntity

try {
 String u = "https://...";
 
 // Add your data
 List nameValuePairs = new ArrayList(2);
 nameValuePairs.add(new BasicNameValuePair("id", "1"));
 // ...
 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nameValuePairs);
 
 URL url = new URL(u);
 HttpsURLConnection request = (HttpsURLConnection) url.openConnection();

 request.setUseCaches(false);
 request.setDoOutput(true);
 request.setDoInput(true);

 request.setRequestMethod("POST");
 OutputStream post = request.getOutputStream();
 entity.writeTo(post);
 post.flush();

 BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream()));
 String inputLine, response = "";
 while ((inputLine = in.readLine()) != null) {
  response += inputLine;
 }
 post.close();
 in.close();
} catch (Exception e) {
 Log.e("Your app", "error", e);
}

May 16, 2014

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

Dealing with the above mentioned Exception has sent me into a wild-goose chase for a quick fix.
Unfortunately the depth of this problem is much larger than I anticipated.

A quick web search suggests that there is a problem with the SSL chain, therefore this would mean that there is a SSL configuration problem on the server, that it's not serving the certificates correctly, eg. in the correct order, or using a self-signed certificate in which case the server also acts as the Certificate Authority.

Some mentioned solutions were to implement your own SSL Client, with a Trust Manager that does absolutely nothing. This is VERY VERY BAD. Don't do it.

Other suggestions were to use your own Trust Keystore (when using self signed certificates, or using "untrusted CAs", like, for example, a university CA).

But if you're using a trusted CA this shouldn't be a problem, right?

For a SSL Server Test you can use Qualys' tool here:
https://www.ssllabs.com/ssltest/analyze.html?d=example.com

Using this test I found no errors on the domain, but there was a notice that the site only works in browsers with SNI support.

SNI (Server Name Indication) is kind of like a Virtual Host for SSL. Usually SSL certificates were issued for an IP address, but having multiple virtual hosts on the same server can cause problems like different browsers getting different SSL certificates from the same server.

You can test this if you have Android <= 2.3.7. Open the browser and navigate to the site. If you get a certificate warning, check the certificate.

So, obviously, if old browsers have this problems, there are going to be problems in the code too.
The answer here summarizes it. The best workaround seems to be to use another library, which supports SNI.
http://stackoverflow.com/questions/21956663/why-does-android-get-the-wrong-ssl-certificate-two-domains-one-server

The most likely cause for this problem is that the server uses Server Name Indication to choose which certificate to send. If the client doesn't support SNI, the server cannot choose which certificate to send during the SSL/TLS handshake (before any HTTP traffic is sent). SNI is required when you want to use multiple certificates on the same IP address and port, but not all clients support it (notoriously, IE on any version of Windows XP, and a number of mobile browsers).

You're also visibly using the Apache HTTP Client library (not HttpsURLConnection, for which there can be SNI support with some Android versions. Support for SNI in the Apache HTTP Client library is quite recent, and certainly hasn't made it into the Android stack.You may find the workaround described in this article useful (although it seems only to work for Android 4.2+).

Another two options would be:
  • to use a distinct IP address for each host (so as not to need SNI), if you're in control of server, or
  • to use another HTTP Client library (e.g. HttpsURLConnection).





Other notes:

Installing the INTERMEDIATE certificate into Apache on Ubuntu/Debian systems
Credits: https://gist.github.com/mgedmin/7124635
    SSLCertificateFile /etc/ssl/certs/subdomain.example.com.crt
    SSLCertificateKeyFile /etc/ssl/private/subdomain.example.com.pem
    SSLCertificateChainFile /etc/ssl/certs/startssl-class1-intermediate.crt

Apr 8, 2014

CSS: floated elements with parent collapse and side menu

Having a floating side menu in CSS will cause problems with clearing floating elements in the content. For example, using .clearfix or clear:both will cause the clear to jump under the side menu.

The solution to this is somewhat counter-intuitive, but try using the property overflow:hidden; on the parent of the floating elements.


Now is the time for all good men to come to the aid of their country.
This is non-float content.





Now is the time for all good men to come to the aid of their country.
This parent has {overflow: hidden;}.

Mar 16, 2014

Raw TCP proxy using socat (Ubuntu)

On ubuntu you can just

# apt-get install socat

and then

# socat TCP-LISTEN:80,fork TCP:192.168.0.200:80

Feb 25, 2014

OpenStreetMaps layer in Google Maps API V3

Adding an OSM layer in Google Maps is very easy, since the V3 API provides a functionality for adding custom layers (even WMS!).

First, you need to define custom map settings, to include your layer. It's good to change the layer chooser to 'dropdown' too.
map = new google.maps.Map(document.getElementById("gmap_canvas"), {
 scaleControl: true,
 mapTypeId: google.maps.MapTypeId.ROADMAP,
 mapTypeControlOptions: {
  mapTypeIds: [
   "OSM",
   google.maps.MapTypeId.ROADMAP, 
   google.maps.MapTypeId.SATELLITE, 
   google.maps.MapTypeId.HYBRID, 
   google.maps.MapTypeId.TERRAIN
  ],
  style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
 }
});
Next, you define your OSM layer like so:
map.mapTypes.set("OSM", new google.maps.ImageMapType({
 getTileUrl: function(coord, zoom) {
  return "http://tile.openstreetmap.org/" + zoom + "/" + coord.x + "/" + coord.y + ".png";
 },
 tileSize: new google.maps.Size(256, 256),
 name: "OSM",
 maxZoom: 18
}));
And there you go. You can check the demo out at: http://poi.kafol.net/