megacolorboy

Abdush Shakoor's Weblog

Writings, experiments & ideas.

How to resolve the "file_get_contents(): SSL operation failed" error

If you're facing this error while trying to download a file from your server, it's most probably the SSL certificate that has been hosted on your server isn't correctly verified or maybe, you're using OpenSSL on a server running PHP 5.6.

As per the documentation, there are some changes that can be made to resolve it, like the following method:

<?php
public function foo(Request $request) {
    $arrContextOptions = array(
        "ssl" => array(
            "verify_peer" => false,
            "verify_peer_name" => false,
        ),
    );
    return Response::make(file_get_contents(asset('pdf/file.pdf'), false, stream_context_create($arrContextOptions)), 200, [
        'Content-Type' => 'application/pdf',
        'Content-Disposition' => 'inline; filename="file.pdf"',
    ]);
}
?>

Although, I won't recommend this unless you are testing it on a localhost environment as it's not secure and could have significant security implications because disabling verification can permit a Man in the Middle attack to take place.

Use it at your own risk!

Check if trait is being used in your class

Want to know if a trait is being used in your current class? Try this:

<?php
in_array(Foo::class, class_uses($this))
?>

By any chance, if the current class is inherited, please note that the class_uses() method will only return the list of traits used by the current class and won't include any traits of it's parent class.

Create migrations and seeds from an existing database

Up until now, I've written migrations and generated seeders for some Laravel projects that I have worked on but recently, I thought of seeing if there's a way to generate migrations and seeds from an existing database especially if it's a project that never had any migrations or seeds created before.

Luckily, I found these two packages, which turned out to be quite productive:

  1. kitloong/laravel-migrations-generator
  2. orangehill/iseed

Execute the following commands to install the packages mentioned above:

composer require --dev "kitloong/laravel-migrations-generator"
composer require orangehill/iseed

Generate migrations using existing database

You can generate your migrations for all tables like this:

php artisan migrate:generate

Or, you can specify the tables you wish to generate:

php artisan migrate:generate table1,table2,table3

Generate new seeds using existing database

You can generate seeds for a single table like this:

php artisan iseed table_name

And for multiple tables, you can do this:

php artisan iseed table1,table2,table3

Hope you find this tip useful!.

How to resolve the issue of not receiving emails on the same domain?

Recently, we hosted our company's redesigned website on GoDaddy, which offers cPanel to manage your website. I was dealing with an annoying email bug in which I was able to send/receive emails to any account except the ones that share the company domain.

The company's current email setup makes use of Google Workspace and since we're using a Shared Hosting account, GoDaddy allows you to use their SMTP relay and prohibits the use of third-party SMTP services such as Google Workspace, Outlook, etc.

After configuring it with Google's MX records in the DNS settings, I wasn't receiving any email on my own company email yet I was able to receive on other email accounts that didn't share the company's domain.

I did a little R&D and ran into this documentation about email routing and figured out that there could be an issue with it's configuration.

Here's what I did:

  1. Open cPanel
  2. Search or look for Email Routing
  3. Click on Email Routing
  4. If your MX records are not pointing to the IP address of the hosting server, then select Remote Mail Exchanger
  5. Save changes

After following these steps, I was able to receive mails on the same domain!

So what really caused the issue?

Since, we didn't have a default email address set up in cPanel, the current mode to send all unrouted emails was set to :blackhole:, by default. I guess, it's set up that way to prevent the server from sending/receiving spam mails from the domain.

This makes sense because:

  1. The MX records are not pointing to the current server
  2. There are no email accounts created for the domain on cPanel
  3. By setting the mode to :blackhole, all emails with the same domain are being discarded or rejected

Not really sure if this is what caused the issue but judging from the facts, I was able to reach to this conclusion.

Hope you found this tip useful.

Reference

Convert string from snake case to camel case

Thought of sharing a simple regular expression that I use on VIM to convert snake_case letters to camelCase letters (see what I did there) 😜

Here's the pattern for you to use:

:s/ \([a-zA-Z]\)/\u\1/g

Hope you found this tip useful!

Make your own generative pixel art in less than 100 lines of code

By modifying my old random pixel generator, I was able to generate a Space Invaders-esque pixel art.

Try it out!

Refresh the page to generate unique Space Invader-esque patterns as the results are unpredictable!

Generative art is a topic that still fascinates me because of the fact that you can produce something unique by just writing few (sometimes, more) lines of code. Especially, if it's self-generating art that makes use of fixed rules and a slight dash of randomness to produce unique results.

When it comes to writing code, it's quite straightforward. You come up with the rules and constraints and voila, you have something that works. Having said that, setting up rules for generative art can get quite tricky.

You might have read about my previous post about The Game of Life, it contains only four rules and each of them took a part in evolving the system through each generation. With generative systems like that, you can never predict the results as complex patterns will emerge due to it's randomness.

In my view, a combination of predictability and randomness is needed in order to create a good looking generative art.

Why you should explore it?

There could be many reasons, maybe you're bored, curious or passionate to learn something new. Who knows? Open up your editor and try it for yourself.

Exploring the craft of making generative art has allowed me to:

  • Gain different experiences — It allows you to sharpen your algorithms & data structures and maybe even, learn a new technique.
  • Create something visually appealing — A picture is equal to a thousand words.
  • Instant results that makes you feel good — I mean, it's hard to explain but y'know what I mean, right?

Where to start?

Just like any other project, you just need:

  • An inspiration or an idea that you can work on.
  • The right kind of technology to use.

With today's article, I'll be showing you how I built a Space Invader-esque pixel art generator in JavaScript that makes use of the Canvas API.

Building a generator

I'd like to give a shout out to the person who built a twitterbot that generates random sprites using Python's Pillow image library.

I was inspired and I thought of writing it in JavaScript and as you can see above, it did turn out pretty well.

Here's the code for your reference and please read the comments to know how it functions:

// To store any used colors
var colorStack = [];

// Selected color palette
var colors = [
    '#30e3ca',
    '#ff5a5f',
    '#40514e',
    '#e4f9f5',
    '#40514e',
    '#e4f9f5',
    '#e4f9f5',
];

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext('2d');

var width = canvas.width;
var height = canvas.height;

function createSquare(squareDimensions, color, element, spriteDim) {
    const {squareX, squareY, squareWidth, squareHeight} = squareDimensions;

    // If it's a middle element, apply a color
    if (element == parseInt(spriteDim/2)) {
        ctx.fillStyle = color;
        ctx.fillRect(parseInt(squareX), parseInt(squareY), parseInt(squareWidth/squareX)+3, parseInt(squareHeight/squareY)+3);
    }
    // If it's the last element, then use the color that you saved previously
    else if (colorStack.length == element + 1) {
        ctx.fillStyle = colorStack.pop();
        ctx.fillRect(parseInt(squareX), parseInt(squareY), parseInt(squareWidth/squareX)+3, parseInt(squareHeight/squareY)+3);  
    }
    // Else, apply a color and save this for the last element.
    else {
        colorStack.push(color);
        ctx.fillStyle = color;
        ctx.fillRect(parseInt(squareX), parseInt(squareY), parseInt(squareWidth/squareX)+3, parseInt(squareHeight/squareY)+3);      
    }
}

function createInvader(invaderDimensions, spriteDim) { 

    var {posX, posY, invaderWidth, invaderHeight} = invaderDimensions;
    var squareSize = (invaderWidth - posX) / spriteDim;

    var cellPosition = 1;
    var element = 0;

    for(var y=0; y<spriteDim; y++){
        // Starts from the left side of the grid.
        // Think of it as something like this:
        // [-3,-2,-1,0,1,2,3]
        cellPosition *= -1;

        // First element
        element = 0;

        for(var x=0; x<spriteDim; x++) {
            squareX = x * squareSize + posX;
            squareY = y * squareSize + posY;
            squareWidth = squareX + squareSize;
            squareHeight = squareY + squareSize;

            // Pick a random color from the color palette
            var color = colors[Math.floor(Math.random() * colors.length)];

            var squareDimensions = {
                'squareX': squareX+2,
                'squareY':squareY+2,
                'squareWidth':squareWidth,
                'squareHeight':squareHeight,
            };

            // Create a square with a color and desired dimensions.
            createSquare(squareDimensions, color, element, spriteDim);

             // If it's the middle element or the starting element, 
             // then shift it's position to the leftmost.
            if(element == parseInt(spriteDim/2) || element == 0) {
                cellPosition *= -1;
            }

            element += cellPosition;
        }
    }
}

function main() {
    var spriteDim = 7;
    var numberOfInvaders = 15;
    var invadersSize = parseInt(width / numberOfInvaders);
    var padding = parseInt(invadersSize / spriteDim);

    for(var x=0; x<numberOfInvaders; x++) {
        for(var y=0; y<numberOfInvaders; y++) {
            var posX = (x * invadersSize) + padding + 2;
            var posY = (y * invadersSize) + padding + 2;
            var invaderWidth = posX + invadersSize - (padding * 3);
            var invaderHeight = posY + invadersSize - (padding * 3);

            var invaderDimensions = {
                'posX': posX,
                'posY': posY,
                'invaderWidth': invaderWidth,
                'invaderHeight': invaderHeight
            };

            createInvader(invaderDimensions, spriteDim);
        }
    }   
}

main();

Well, I won't say that is a perfect solution but hey, it works and yes, it doesn't take a lot of code to achieve something like this.

Explanation

I'll try my best to explain how this whole thing works.

First, you need to initialize a <canvas> DOM element of the desired width and height. Then in the main() function, you determine the size of each invader by specifying the number of invaders and dividing it with the width of the canvas. These values will then be used to determine the coordinates for each invader.

Second, the function createInvader() follows nearly the same process as the main function except that the coordinates for each pixel is determined by calculating the width of the invader and subtracting it's x position divided by the dimensions of each invader.

Third, as you can see in the function createSquare(), it contains 3 simple rules in which all of them draws a square with a color but with an emphasis that each invader has a symmetrical pattern.

The code looks deceptively simple but achieving this complexity did take a lot of trial and error and a little bit of simple calculus 😂.

Conclusion

Generative art might be something that you may not need to explore but it's quite fun and you may never know what you might be able to produce by combining both code and visuals.

Hope you liked reading this article.

Stay tuned for more! 🤘

Built a new static site generator using Python 3.7

Thought of giving it some new upgrades and finally decided to open-source it.

Since 2019, I always used a custom static site generator for the website. The previous one was written in Python 2.7 but ever since Python decided to sunset it, I decided to rewrite it using Python 3.7.

Unlike the previous one, it's quite flexible and I thought of giving it some new features that would help me maintain it with ease.

The new features I have added are:

  • A neat CLI to build the entire site or certain parts of the website
  • Able to switch between different templates
  • Archive mode
  • Pagination
  • Generates RSS Feeds and JSON files

Why rewrite it again?

Over the past few months, I didn't really maintain my blog and when I visited the old codebase, I realized it wasn't flexible and it didn't have many features and it was slow, too.

Recently, I got new ideas of building different sections for the website and thus, is why I had the motivation to rewrite everything and make it modular and flexible enough to build a powerful yet simple custom static site generator.

Have a look

I have decided to open-source my static site generator on my GitHub repository and I'm having plans of writing a new documentation for it, so that if people are interested, they could contribute or use it for their own personal uses.

Conclusion

If you've been following my blog posts, you may know that I have a knack of displaying JavaScript widgets on some of my previous blog posts. Well, I've decided to rewrite all of those widgets, one-by-one, using ReactJS and hopefully, write more tutorials for each of them.

Hope you liked reading this article.

Find and remove duplicate lines using Regular Expressions

Open up your text editor and use the following RegEx pattern to find and remove the duplicate lines:

^(.*)(\r?\n\1)+$

I found this technique on Regular-Expressions.info and I'm going to quote their explanation over here:

The caret will match only at the start of a line. So the regex engine will only attempt to match the remainder of the regex there. The dot and star combination simply matches an entire line, whatever its contents, if any. The parentheses store the matched line into the first backreference.

Next we will match the line separator. I put the question mark into `\r?\n` to make this regex work with both Windows `(\r\n)` and UNIX `(\n)` text files. So up to this point we matched a line and the following line break.

Now we need to check if this combination is followed by a duplicate of that same line. We do this simply with `\1`. This is the first backreference which holds the line we matched. The backreference will match that very same text.

If the backreference fails to match, the regex match and the backreference are discarded, and the regex engine tries again at the start of the next line. If the backreference succeeds, the plus symbol in the regular expression will try to match additional copies of the line. Finally, the dollar symbol forces the regex engine to check if the text matched by the backreference is a complete line. We already know the text matched by the backreference is preceded by a line break (matched by `\r?\n`).

Therefore, we now check if it is also followed by a line break or if it is at the end of the file using the dollar sign.

The entire match becomes `line\nline` (or `line\nline\nline` etc.). Because we are doing a search and replace, the line, its duplicates, and the line breaks in between them, are all deleted from the file. Since we want to keep the original line, but not the duplicates, we use `\1` as the replacement text to put the original line back in.

Hope you found this tip useful!