Simple image uploads in Meteor

While working on a simple online yearbook for my high school class of ’16 in Meteor, I ran into the issue of uploading images to Meteor. Turns out, it’s not uncomplicated at all.

I messed around with CollectionFS, but unfortunately had the issue of images not loading and returning 503s, or taking a long while to load.

I decided to turn to the most popular and developer-friendly image host I know: Imgur.


I used the simple:imgur package. The upload() function takes two arguments, options and callback.

The options require an apiKey, the Imgur Client ID and image, the base64-encoded image data string. The callback function receives two arguments, the first being a Meteor.Error object and the latter being an object containing the response from Imgur.

apiKey: Registering an Imgur Application

The first step is to get an apiKey by registering your application at Imgur’s OAuth 2 page. We need to choose ‘OAuth 2 authorization without a callback URL’, and once done, get the client ID (You’ll get an email about it, too).

image: Converting file to base 64

In the submit event of my upload form, I add a line to get the file that the user uploaded:

var file = $form.find('input[type="file"]')[0].files[0]  

I also check if the file is an image or not:

if ( file && !file.type.match('image.*') ) return alert('Upload must be an image')  

We’re now going to use the FileReader API to get the base-64 representation of the image.

We’ll need to create a new reader and add a function to it’s onload event, where we handle the image upload logic.

var reader = new FileReader()

reader.onload = function(e) {  
  // e.target.result holds the file's text
}

We’re going to convert the text into a Uint8Array, convert it to a string, and then finally use btoa() to convert the string to base-64 encoded ASCII string.

I directly do this in a convoluted one liner and a custom function inside an options object I created to call Imgur.upload().

var options = {  
  apiKey: 'XXXXXXXXXXXXXXX',
  image: btoa(uint8ToString(new Uint8Array(e.target.result)))
};

The uint8ToString function is simple: it converts the Unicode values we get from the Uint8Array representation of e.target.result into ASCII strings, which can be converted to base-64 easily.

function uint8ToString(buffer) {  
  var length = buffer.length, str = ''

  for ( var i = 0; i < length; i++ ) {
    str += String.fromCharCode( buffer[i] )
  }

  return str
}

And with this, we’re able to create our options object easily.

Uploading

I created a data object to handle all data entered in the form by our user. In the Imgur.upload() function, I add to it.

Imgur.upload(options, function(errMsg, imgurData) {  
  if ( errMsg ) return alert('File upload failed. Please upload an image of a smaller file size')
    var imgData = {
      link: imgurData.link,
      deletehash: imgurData.deletehash
    }
    data.photo = imgData
  })
}

I only store the two important parts of the response: the link to the file and the deletehash. I can easily show the file by using <img src="{{ currentUser.data.photo.link }}">.

And we’re done!

Discuss on Twitter

3D In 2D Canvas

In my recent simulation of an AC generator, I show the same device from two different views: A top view and a front view. To accomplish that, I used a clever technique called 3D Projection. Here, I’m going to talk about how I did that in JavaScript and rendered it on canvas.

What is 3D Projection?

Basically, it means that I define items in 3D space (each point is defined as an array [x, y, z]) and that I plot them in 2D space. For simplification, the 2D render can only be seen in the xy, xz, or yz plane.

Defining in 3D

Each point is defined as an array, [x, y, z].

Since we are using Canvas, it is easiest to define a rectangular face as a 2D array of 5 points: The first vertex, the remaining 3 vertices, and then the initial vertex again. This allows us to moveTo() the first index and then lineTo() till the remaining length of the array.

Since faces exist in 2D, and we’re defining 3 coordinates per point, for a single face, either the x, y, or z, coordinate will remain constant for all points.

A cuboid is defined a 3D array of faces. Depending on our views, we might not need all 6 faces to define a cuboid and can get away with only two or three faces.

Example:

var cuboid = [  
  // xy face
  [
    [xa1, ya1, za],
    [xa2, ya2, za],
    [xa3, ya3, za],
    [xa4, ya4, za],
    [xa5, ya5, za],
  ],
  // xz face
  [
    [xb1, yb, zb1],
    [xb2, yb, zb2],
    [xb3, yb, zb3],
    [xb4, yb, zb4],
    [xb5, yb, zb5],
  ],
  ...
]

Rendering in 2D.

Since we’re defining faces parallel to the primary planes, it is easiest to render the views of the primary planes themselves.

Imagine a shape on the xy plane. All points that define it can be written as (xi, yi, 0). Similarly, any shape on the xz plane defines all points as (xi, 0, zi). Basically, whichever axis you’re not rendering the shape on is 0.

This makes things easy for us.

Creating a function called plotFace, which takes three parameters:

  • face: The 2D array of points
  • path: The path to plot the shape on
  • a: The first axis of the plane
  • b: The second axis of the plane

Since in our arrays, the 0 index represents x and so on, we can simplify the function if a and b are directly passed as integers.

The plotFace function basically movesTo the initial point and linesTo the remaining ones.

function plotFace(face, path, a, b) {  
  var len = face.length;
  path.moveTo( face[a], face[b] );
  for ( var i = 0; i < len; i++ ) {
    var point = face[i];
    path.lineTo( point[a], point[b] );
  }
}

A simple map through all faces and using plotFace on each can plot the entire shape to a single path.

path = new Path2D();  
ctx.beginPath();  
item.faces.map(function(face) {  
  plotFace(face, path, a, b);
})
ctx.closePath();  

Finally, rendering the context using fill() will get our shape.

ctx.fill(path);  

…And we’re done!

What’s next

Currently, we’re only projecting in the xy, xz, or xy plane. Next would be to be able to project in any arbitrary plane. I have yet to figure out the math for it, and I’m trying to do it without external help, so it might be a while before I publish a new article.

After that, perhaps manually raycasting to create shadows? That could be interesting, both aesthetic and performance wise.

Further Reading

Discuss on Twitter

Two really cool Node MySQL tips

Node MySQL is a great traditional alternative to mongo and all the jazz youngins are using. One important advice – never use + to concatenate queries unless you know what you’re doing.

1. Always escape using ? as placeholders

Queries are usually written as:

connection.query('SELECT * FROM foo WHERE bar = baz', function(err, results) {  
    // ...
});

If you want to check against a custom property, don’t do this.

connection.query('SELECT * FROM foo WHERE bar = ' + someVariable, function(err, results) {  
    // ...
});

Instead,

connection.query('SELECT * FROM foo WHERE bar = ?', [someVariable], function(err, results) {  
    // ...
});

You can use multiple ? like so:

connection.query('SELECT * FROM foo WHERE ? = ?', [someProperty, someValue], function(err, results) {  
    // ...
});

2. Use the SET ? syntax

Node MySQL converts objects from { a: 'b' } to a = 'b' when escaped. Insertions with objects is thus easy:

var user = { id: 42, name: "Namanyay Goel" };  
connection.query('INSERT INTO users SET ?`, user, function(err, result) {  
    // ... 
}); 

Then you never have to do this


Learn more about Node MySQL’s escaping

Discuss on Twitter

Selling online allows retailers to sell their merchandise in any part of the world without additional expense, this allows online retailers to give better prices which is what customers are looking for, they usually visit websites likeĀ Raise in order to find the coupon codes from multiple retailers. It can also allow for free shipping, saving on the costs of transport. But with online shopping, retailers have an incentive to use a website or app that helps them to automate the process of selling a good or service.

Fintech firms, like the ones mentioned above, can help to automate the process by helping retailers collect data from a customer base as well as using mobile phones to direct them to the best products, products from a specific store and more.

But these companies will also need to be cognizant of all the risks and regulatory barriers as they work to break through the often labyrinthine regulatory hurdles.

The new industry is in its infancy with relatively little regulation and very little infrastructure in place for those starting the fintech industry. In fact, there are many fintech startups and a number of big players who are either active in the space or have already established themselves. These companies can help retailers move away from brick and mortar stores and into online locations, as well as make it easier for customers to discover and shop for a range of products.

With that in mind, it makes sense to start with companies that provide service for those seeking to shop for things online. I decided to explore the list of fintech startups in this space and find out which are the biggest players out there. I’ve created a short list of these companies below, broken into two distinct categories: those that work exclusively with brick-and-mortar stores and those that offer services in addition to online stores.

 

Discuss on Twitter

Software for malicious programs

You can make use of a wide range of software in order to prevent or block malicious programs from getting into your system or running within the network.

We’ve reviewed some of the most popular anti-malware solutions, and while they all have their pros and cons, this article focuses on what we’ve found to be the best and safest anti-malware solution available.

The Top 4 Cybersecurity Trends to Watch Out for in 2021 and Beyond

Here at Malwarebytes, we recommend all of our users try out at least one of the anti-malware solutions we review and recommend. Whether it’s a free anti-malware solution or paid program, your computer should have a few anti-malware programs installed.

Some anti-malware solutions install a Windows Service and get all your Internet traffic and files automatically. If you prefer not to install a Windows Service and instead opt to install your own anti-malware software, you can download a couple of programs that will perform the same purpose.

What are the best anti-malware programs?

If you’re new to ant-malware software and need some good start-up advice, we recommend you read the below guides.

In the following guides, we’ll show you how to protect your Windows computer from all the malware, protect your sensitive information, and make sure your personal information stays safe from unauthorized access.

Listed below are the best free anti-malware programs available on the market, each with its own unique set of features. We also have a free copy of Windows Defender that has a handy Internet security suite built into it.

Witsec Anti-Malware

Witsec Anti-Malware is a powerful anti-malware solution that performs automatic scanning, blocking malicious websites and viruses from appearing on your computer. This tool is capable of blocking all the malicious programs available on the Internet. The free version of Witsec Anti-Malware does a pretty good job at keeping malicious programs from getting into your system, but doesn’t have the features of a premium product such as a paid product.

You can get access to a free trial version of the paid product if you prefer. If you prefer not to use an online account and instead want to use a downloadable version of Witsec Anti-Malware, you can download this free version by clicking here.

Get Witsec Anti-Malware from the link below.

Witsec Anti-Malware Free Trial

Anti-MalwareBytes Anti-Malware

Anti-Malwarebytes Anti-Malware is another powerful anti-malware solution available in both a free and a paid version. It provides instant, automatic, and very comprehensive security protection for your computer, and is good enough to stop many of the more common threats to your privacy.

One of the main reasons to use this anti-malware product is that it blocks malicious websites and programs, and forces Google Chrome to automatically download the latest version of Chrome, thus avoiding unauthorized downloads and updates.

If you’d like to learn more about cyber and network security, we suggest checking https://www.fortinet.com/solutions/enterprise-midsize-business/network-access/application-access

Discuss on Twitter

Jade locals with Gulp

One of the coolest features of Jade is the concept of locals: An object that can be passed to the compiler and used in the Jade code, allowing better separation of content and templates. Ideally, these locals are held in an external file.

After much tinkering, I figured something out:

var fs = require('fs');  
...
.pipe( p.jade({ 
    pretty: uglyLevel,
    data: JSON.parse( fs.readFileSync('src/data.js', { encoding: 'utf8' }) )
}) )

…What?

  • Gulp Jade’s docs show that the data or locals option to could be used to pass in a single object holding all the external data.
  • File I/O, or fs is node’s way of reading files. Using fs.readFileSync, I used a JSON file to hold all the data.
  • JSON.parse() is a native JS method to convert a string (The output of fs.readFileSync with utf8 encoding) to JSON.

Combining the three resulted in the above one liner, allowing me to use a data.js file to host all raw data and use loops to better template the code within. Win!

PS: If you’re wondering what the uglyLevel bit is…

Discuss on Twitter

Images and excerpts – A few practical problems with Ghost

Ghost is awesome, it really is! I’ve just started using and developing on it, but I love it already. It’s simple, smooth, and fast. You can feel the speed when you compare it to traditional CMS’ like WordPress or static generators like Jekyll – I find it to triumph both.

Development is pretty damn easy too. Installing Ghost on Windows was a breeze, and starting development even easier. I fired up Prepros, creating a SCSS file for better CSS, and started coding!

Ghost’s writer is it’s biggest advantage, though. Markdown is great to write, and the side-by-side compilation makes writing so much more fun.

However, there are indeed a few practical problems with Ghost that you may encounter soon in one of your projects. I’m going to talk about these here, along with some hacky solutions for them.

  • Images can’t use figure/figcaption: Currently, images on Ghost are simple <img> tags in paragraphs. I was looking around for image captioning and using figure/figcaption there, but with little results. A workaround by Lee Lam could be a quick solution, though.

This is a problem both of Markdown (Which does not seem to support two types of captions, i.e. one for the alt attribute and other a standard caption) and Ghost.

The issue is set to won’t fix until the Haunted Markdown parser is implemented.

  • No support for advanced excerpts: With WordPress, you could simple add a <!-- more --> somewhere and it handled excerpts with read more for you. Unfortuantely, this isn’t the case with Ghost and by default you see a paragraph of plaintext with a trailing …. Not something particularly beautiful.

Kraftner on Ghost Forums gives a great solution to that problem. Using {{ content }} instead of {{ excerpt }} allows you to output HTML instead of plaintext, and combining that with some clever CSS rules displays only one paragraph. I use a similar trick at TLDRtech where all uls are hidden in the ‘excerpt’.

My goal with the post was to highlight some of the common issues, and give hacky solutions for them. That said, I do love Ghost for many, many reasons

  • Ghost is fast. You literally feel the difference on the admin panel of Ghost compared to WordPress’
  • Installing Ghost is a breeze. It took me less than 2 minutes to install Ghost on my Windows computer. Granted, installing it on Apache is a bit more difficult, but there are good guides for that.
  • Theme development on Ghost is fun. Handlebars is fun to write, and I’ve set up SCSS compilation with Prepos as well.

Discuss on Twitter

Debug mode in gulp

I’ve been using gulp a lot lately (as you can see from my posts).

To the uninitiated, gulp is the hottest, sleekest and newest build system in town. Which I’m in love with and use almost everywhere now. Yup, it’s that awesome.

However, I had been having troubles with debugging while using gulp. It’s not exactly easy to debug one-line CSS or mangled JS now, is it?

So I came up with a solution, creating a switch variable and a new task, debug.

The debug variable

Everything will be controlled by a single variable, which I call debug. Set debug to be false at the start of your gulpfile.js.

var debug = false;  

In the default task, write a line:

gulp.task('default', function() {  
  debug = debug || false;
  ...
}

Why? So we can easily switch the variable from other tasks, and this change is passed to the default task.

The debug task

We need to now create a task that achieves three things:

  1. Sets debug to be true.
  2. Logs that gulp is running on ‘debug mode’.
  3. Set easy-debugging configuration options in all tasks.
gulp.task('debug', function() {  
  debug = true;
  gutil.log( gutil.colors.green('RUNNING IN DEBUG MODE') );
  gulp.start('default');
});

That’s my debug task. Here, gutil = require(gulp-util);. This logs a helpful message, and switches the debug variable to be true.

We can now use this information to make debug changes in our existing tasks.

Debug configuration in tasks

I’ve added a simple variable at the top of each task – uglyLevel. Depending on the task, uglyLevel can be true/false, or ‘compress’/’expanded’. The values are toggled using a simple ternary operator.

    var uglyLevel = debug ? true : false;

Then, these are passed on as values depending on the plugin. For example, with gulp-jade, uglyLevel must be a boolean value and will be used like so:

.pipe( p.jade({ pretty: uglyLevel }) )

gulp-uglify is similar:

.pipe( p.uglify({ compress: uglyLevel }) )

However, for gulp-stylus, uglyLevel is either ‘compress’ or ‘expanded’.

var uglyLevel = debug ? 'expanded' : 'compress';

gulp.src( src )  
  .pipe( p.stylus({ set: [uglyLevel] }) )

You can also try toggling sourcemaps if you’re using SASS, unfortunately the option isn’t available in Stylus yet. Many different ways to solve the same problem.

Usage

Simply run gulp debug in the command line instead of gulp. Done! Since debug task runs the default task, all additonal tasks like watch or connect will run automatically.

And there you have it, an easy and quick debug method for gulp.

Discuss on Twitter

Super simple static server in gulp

I recently spent a lot of time looking for a decent way to:

  1. Set up livereload on gulp
  2. Set up a static server.

Here are my findings.

First, I tried using gulp-livereload and gulp-embedlr. Using them together was decent and they were pretty fast, however, they were too complex for my simple goal.

Everything changed when the fire nation attacked once I stumbled upon gulp-connect.

Using gulp-connect

This plugin is extremely simple to use, I set up a server in literally 5 lines of code:

gulp.task('connect', p.connect.server({  
  root: ['_public'],
  port: 4242,
  livereload: true
}));

Yup, that’s it!
(p.connect = require('gulp-connect'), btw).

Live Reload

Now, to actually reaload the page on changes to tasks, we need to pipe p.connect.reload() on each task.

I’ve found that piping it after gulp.dest() is the fastest, so add

  .pipe( gulp.dest( dest ) )
  .pipe( p.connect.reload() );

At the end of each task.
(Where dest refers to the destination path).

Proper watching

I include all ‘partials’ in a subfolder, and all files that are to be compiled in the root folder.

e.g., Jade’s partials/templates go into folders jade/layouts or jade/partials, while main that are to be compiled, like, index.jade or about.jade go in the jade folder.

Therefore, I just run tasks on the root folders, not any of the subfolders.

This creates a problem with live reloading. It would only reload if any of the files from the root folder is changed, but not if the subfolder files are changed.

To fix this, here’s what I changed my watch task to:

gulp.task('watch', ['connect'], function() {  
  gulp.watch( `src/styl/*.styl`, `src/styl/**/*.styl`, ['styles'] );
  ...
});

This runs the styles task, compiles properly, and livereloads on every file changed.

Discuss on Twitter

Checkout git branches through your browser

Most git workflows involve use of multiple branches for different sub-tasks, example, a new branch for an alternative layout for the homepage. However, managing braches on the server quicky gets tedious – SSHing in, navigation to the correct directory, then running git checkout <branch> – is tiring for all, right?.

That’s why I came up with a simple solution that used PHP and GET requests to checkout different branches on the server through the browser.

The Concept

What we’re trying to achieve here is:

  1. An easy way to pass a branch name to a script.
  2. That script uses that branch name to run a checkout in the correct directory.
  3. The output of the command is presented to us, to tell if it ran correctly or not.

Doing this with a small, but powerful, PHP script is our challenge.

The Code

GET Request

We’ll be passing variables as GET requests, because:

  1. It’s easy.
  2. It’s lazy.

So just make a variable holding the GET variable in your PHP

$branchname = $_GET['branch'];

We’ll also need to check if the user has actually supplied a request, if not, echo a helpful message and stop the script from executing further.

if (!$branchname) {  
  echo "Please enter a branchname, ?branch=<name>";
  return false;
}

Executing the command

We need to cd into the correct directory and run git checkout $branchname. We do that using shell_exec().

$command = 'cd <directory> && git checkout ' . $branchname;
$output = shell_exec($command . ' 2>&1');

You might not need to change directory, so feel free to remove cd <directory>. The rest is essential. 2>&1 directs stderr to stdout (Or put simply, outputs the result of the command).

Printing the output would be extremely helpful as well:

echo 'Checking out ' . $branchname . '&hellip;<br>';  
echo $output . '<br>';  

And we’re done. Upload it to your server with a filename like checkout-git-branch.php, and try it out!

Final code

<?php

$branchname = $_GET['branch'];

if (!$branchname) {  
  echo "Please enter a branchname, ?branch=<name>";
  return false;
}

$command = 'cd <directory> && git checkout ' . $branchname;
$output = shell_exec($command . ' 2>&1');

echo 'Checking out ' . $branchname . '&hellip;<br>';  
echo $output . '<br>';  
?>

Discuss on Twitter