• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer
  • Home
  • Create a VM ($25 Credit)
  • Buy a Domain
  • 1 Month free Back Blaze Backup
  • Other Deals
    • Domain Email
    • Nixstats Server Monitoring
    • ewww.io Auto WordPress Image Resizing and Acceleration
  • About
  • Links

IoT, Code, Security, Server Stuff etc

Views are my own and not my employer's.

Personal Development Blog...

Coding for fun since 1996, Learn by doing and sharing.

Buy a domain name, then create your own server (get $25 free credit)

View all of my posts.

  • Cloud
    • I moved my domain to UpCloud (on the other side of the world) from Vultr (Sydney) and could not be happier with the performance.
    • How to buy a new domain and SSL cert from NameCheap, a Server from Digital Ocean and configure it.
    • Setting up a Vultr VM and configuring it
    • All Cloud Articles
  • Dev
    • I moved my domain to UpCloud (on the other side of the world) from Vultr (Sydney) and could not be happier with the performance.
    • How to setup pooled MySQL connections in Node JS that don’t disconnect
    • NodeJS code to handle App logins via API (using MySQL connection pools (1000 connections) and query parameters)
    • Infographic: So you have an idea for an app
    • All Development Articles
  • MySQL
    • Using the free Adminer GUI for MySQL on your website
    • All MySQL Articles
  • Perf
    • PHP 7 code to send object oriented sanitised input data via bound parameters to a MYSQL database
    • I moved my domain to UpCloud (on the other side of the world) from Vultr (Sydney) and could not be happier with the performance.
    • Measuring VM performance (CPU, Disk, Latency, Concurrent Users etc) on Ubuntu and comparing Vultr, Digital Ocean and UpCloud – Part 1 of 4
    • Speeding up WordPress with the ewww.io ExactDN CDN and Image Compression Plugin
    • Setting up a website to use Cloudflare on a VM hosted on Vultr and Namecheap
    • All Performance Articles
  • Sec
    • Using the Qualys FreeScan Scanner to test your website for online vulnerabilities
    • Using OWASP ZAP GUI to scan your Applications for security issues
    • Setting up the Debian Kali Linux distro to perform penetration testing of your systems
    • Enabling TLS 1.3 SSL on a NGINX Website (Ubuntu 16.04 server) that is using Cloudflare
    • PHP implementation to check a password exposure level with Troy Hunt’s pwnedpasswords API
    • Setting strong SSL cryptographic protocols and ciphers on Ubuntu and NGINX
    • Securing Google G Suite email by setting up SPF, DKIM and DMARC with Cloudflare
    • All Security Articles
  • Server
    • I moved my domain to UpCloud (on the other side of the world) from Vultr (Sydney) and could not be happier with the performance.
    • All Server Articles
  • Ubuntu
    • I moved my domain to UpCloud (on the other side of the world) from Vultr (Sydney) and could not be happier with the performance.
    • Useful Linux Terminal Commands
    • All Ubuntu Articles
  • VM
    • I moved my domain to UpCloud (on the other side of the world) from Vultr (Sydney) and could not be happier with the performance.
    • All VM Articles
  • WordPress
    • Speeding up WordPress with the ewww.io ExactDN CDN and Image Compression Plugin
    • Installing and managing WordPress with WP-CLI from the command line on Ubuntu
    • How to backup WordPress on a host that has CPanel
    • Moving WordPress to a new self managed server away from CPanel
    • Moving a CPanel domain with email to a self managed VPS and Gmail
    • All WordPress Articles
  • All

code

Check the compatibility of your WordPress theme and plugin code with PHP Compatibility Checker

November 7, 2018 by Simon

This is how I checked the compatibility of my WordPress theme and plugin (code) with PHP Compatibility Checker

Aside

I have a number of guides on moving away from CPanel, Setting up VM’s on AWS, Vultr or Digital Ocean along with installing and managing WordPress from the command line. PHP is my programming language of choice.

Now on with the post

Snip from: https://wordpress.org/plugins/php-compatibility-checker/

What is PHP Compatibility Checker

> The WP Engine PHP Compatibility Checker can be used by any WordPress website on any web host to check PHP version compatibility.

> This plugin will lint theme and plugin code inside your WordPress file system and give you back a report of compatibility issues for you to fix. Compatibility issues are categorized into errors and warnings and will list the file and line number of the offending code, as well as the info about why that line of code is incompatible with the chosen version of PHP. The plugin will also suggest updates to themes and plugins, as a new version may offer compatible code.

> This plugin does not execute your theme and plugin code, as such this plugin cannot detect runtime compatibility issues.
Please note that linting code is not perfect. This plugin cannot detect unused code-paths that might be used for backwards compatibility, and thus might show false positives. We maintain a whitelist of plugins that can cause false positives. We are continuously working to ensure the checker provides the most accurate results possible.
This plugin relies on WP-Cron to scan files in the background. The scan will get stuck if the site’s WP-Cron isn’t running correctly. Please see the FAQ for more information.

Install PHP Compatibility Checker

PHP Compatibility Checker

I instaled by SSH’ing to my server and opening my WP Plugins folder

cd /www-root/wp-content/plugins/

I grabbed the latest download URL from here (hover over the download button), at the time of writing this was the latest version: https://downloads.wordpress.org/plugin/php-compatibility-checker.1.4.6.zip

I downloaded the plugin on my server (then unzipped it and deleted the zip)

wget https://downloads.wordpress.org/plugin/php-compatibility-checker.1.4.6.zip
unzip php-compatibility-checker.1.4.6.zip
rm php-compatibility-checker.1.4.6.zip

Enable PHP Compatibility Checker Plugin

I enabled the plugin

Enable the Plugin

I clicked on the following message

> You have just activated the PHP Compatibility Checker. Start scanning your plugins and themes for compatibility with the latest PHP versions now!

Start Scan

I already have PHP 7.2 installed so let’s scan my site. PHP 7.3 will be available in December and it is already being tested in beta.

Scan PHP 7.2

PHP Versions

PHP Versions

Site Scanning

PHP Compatibility Checker site scanning is very business-like

Site Scan Progress

PHP Compatability Checker Scan Results

2 of 22 plugins I use were not PHP 7.2 compatible (WordFence and WP Meta SEO)?

PHP Compatibility Report

I read on twitter that Wordfence may be a false positive.

Clicking toggle details reveal why the scan failed. A Two Factor Auth plugin was all OK.

Scan Results

Your results will hopefully be…

> PHP 7.2 compatible

Of if errors exist it should explain why it did not pass.

FILE: /www-root/wp-content/plugins/wp-meta-seo/jutranslation/jutranslation.php
> —————————————————————————————-
> FOUND 1 ERROR AFFECTING 1 LINE
> —————————————————————————————-
> 251 | ERROR | The function is_countable() is not present in PHP version 7.2 or earlier
> —————————————————————————————-

I can’t wait for PHP 7.3 scanning.  I will update this post in December 2018 after PHP 7.3 is released.

Good luck and I hope this guide helps someone

Ask a question or recommend an article

[contact-form-7 id=”30″ title=”Ask a Question”]

Revision History

v1.0 Initial post

Filed Under: Compatibility, PHP Tagged With: and, check, Checker, code, compatibility, of, php, plugin, the, theme, with, wordpress, your

Useful Java FX Code I use in a project using IntelliJ IDEA and jdk1.8.0_161.jdk

September 15, 2018 by Simon

This is some useful Java FX Code I use in a project using IntelliJ IDEA and jdk1.8.0_161.jdk. I am sharing this code here for the #100DaysOfCode readers and people looking for code answers.

Aside

If you have not read my previous posts I have now moved my blog to the awesome UpCloud host (signup using this link to get $25 free UpCloud VM credit). I compared Digital Ocean, Vultr and UpCloud Disk IO here and UpCloud came out on top by a long way (read the blog post here). Here is my blog post on moving from Vultr to UpCloud.

Buy a domain name here

Domain names for just 88 cents!

As promised, Java code.

Background

I am developing a Java (Windows/Mac/Linux) JavaFX app to assist me (and others) click their way through a Server deployment (domain name purchase, email setup, DNS etc) to the configuration (server host, operating, web server, database etc) to securing (DNSSEC, SPF, DMARC, Firewall etc).

I want to automate much of what I have learned over the last 2 years building apps and services (see all blog DevSecOps posts here: https://fearby.com/all/ ) on a self-managed Linux stack. I love the lower cost, higher security and flexibility of deploying self-managed servers on Linux (I love UpCloud) but not the command line interactions (that’s why I am learning Java, I do not want to develop another web-based GUI as I find them less secure than a good SSH connection). I have been developing on Windows since 1999.

Now show me Jave code.

Save date-time variables in Controller Initialize event to use in Logging

I like to log console events to a filename that is the date-time an app was started.  Add this to “public class Controller implements Initializable”

public Date todaysDateTime = new Date();
DateFormat datetimeFileNameCompatible = new SimpleDateFormat("dd-MMM-yyyy HH-mm-ss.S");
public String strLogFileTimeFilename = "zAPPDISCO - " + datetimeFileNameCompatible.format(todaysDateTime);

Now the log filename can be used below in a log function (DoLog).

Read Ini File

Download http://ini4j.sourceforge.net/ (binary files) and add ini4j-0.5.4.jar to your source folder (or use Maven etc to download the package)

Import the ini4j class to your Controller.

import org.ini4j.Ini;

Sample appname.ini file

# Ini file comment goes here

[config]
forceoffline = false
log = true

[settings]
checkipatstartup = true
checkinternetconnectionatstartup = true

[app]
name=blah blah app name
app_major = 1
appminor = 0
apprevision = 18

[mainwindow]
mainwidth = 1619.0
mainheight = 1119.0
mainleft = 147.0
maintop = 44.0

[settingswindow]
settingswidth = 1286.0
settingsheight = 1010.0
settingsleft = 9.0
settingstop = 153.0

Load an Ini file

objIni = new Ini();
System.out.println("  - Opening app.ini" );
try {
    objIni.load( new FileReader("src/appname/appname.ini"));
    System.out.println("   - Loaded INI (OK)" );

} catch (IOException ex) {
    System.out.println("   - Error Loading appname.ini ( " + ex.toString() + ")");

}

Now we are ready to load values from the loaded Ini file.

Load a Boolean from Ini file

I like to set if an app can talk to the net (by checking an Ini file to see if a user does not want online activity).

private Boolean FORCE_OFFLINE = false;
FORCE_OFFLINE = objIni.get("config","forceoffline",boolean.class);

Load String from an Ini File

System.out.println (" - App Name: " + objIni.get("app","name"));

Global Variables Class

package appname;

public class GlobalVariables {

    public int APP_MAJOR = 0;
    public int APP_MINOR = 0;
    public int APP_REVISION = 18;

    //etc
}

Copy the global variables class in a new controller, add the following code to your new controller’s “public class Controller implements Initializable” function

GlobalVariables global = new GlobalVariables();

Read the constants in the global variable class (copy)

DoLog("Started App Disco (v" + global.APP_MAJOR + "." + global.APP_MINOR  + "." + global.APP_REVISION + ") - https://fearby.com");

Log function that writes to the stdout console and physical log file if desired (set in the ini file)

private void DoLog(String logThis) { 
    // Log to std out
    System.out.println(logThis); 

    // Write to log file
    try{
    	// Declare a new Ini object
        objIni = new Ini();

        System.out.println("  - Opening appname.ini" );
        try {
            objIni.load( new FileReader("src/appname/appname.ini"));
            System.out.println("   - Loaded INI (OK)" );
        } catch (IOException ex) {
        	// Error
            System.out.println("   - Error Reading from appname.ini ( " + ex.toString() + ")");
        }

        // Check the ini file and see if the user wants to out output a log file.
        System.out.println("    - Reading [config] section in Ini file" );

        Boolean DO_LOG;
        DO_LOG = objIni.get("config","log",boolean.class);
        System.out.println("     - DO_LOG = " + DO_LOG.toString() );

        // Does the use want the console to be logged to a date stamped file too?
        if (DO_LOG == true) {
            
            // Append To File
            FileWriter fstream = new FileWriter( strLogFileTimeFilename.toString() + ".log", true);
            BufferedWriter out = new BufferedWriter(fstream);

            // Get Latest Time to prefix to the log entry
            Date todaysDateTimeLog = new Date();
            DateFormat datetimeHumanReadableFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
            String strLogFileTimeHuman = datetimeHumanReadableFormat.format(todaysDateTimeLog);

            // Log Desired Line
            String strLogThisTS = strLogFileTimeHuman.toString() + " = " +  logThis;
            out.write(strLogThisTS + "\n");

            //Close the output stream
            out.close();

        } else {
            //System.out.println("      - Skipping logging as set in the ini file.." );
        }


    } catch (Exception e){
    	//Catch exception if any
        // todo: Need to write to System.out.printl to prevent loop
        System.out.println ("Error: " + e.getMessage());  
        
    }
}

Get Contents from URL

private static String getContentsFromURL(String theUrl)
{
    StringBuilder content = new StringBuilder();

    try
    {
        // create a url object
        URL url = new URL(theUrl);

        //todo: Add Newwor check code
        
        URLConnection urlConnection = url.openConnection();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));

        String line;

        while ((line = bufferedReader.readLine()) != null)
        {
            content.append(line + "\n");
        }
        bufferedReader.close();
    }
    catch(Exception e) {
        e.printStackTrace();
    }

    return content.toString();
}

Test the internet connection by downloading the contents of a URL

String isup = getContentsFromURL("https://audit.fearby.com/isup/");
System.out.println( "Is UP: " + isup.trim().toUpperCase().toString());

Get the IPV4 address of the calling client

String isup = getContentsFromURL("https://audit.fearby.com/ip/");
System.out.println( "Is UP: " + isup.trim().toUpperCase().toString());

The IP page contains

<?php
echo htmlspecialchars($_SERVER['REMOTE_ADDR'], ENT_QUOTES, 'UTF-8');
?>

SSH to a server and run a command

This is handy for connecting to a server via SSH (and using an SSH passphrase, not a system username password). This is using the Jsch library from http://www.jcraft.com/jsch/

try {
    JSch jsch = new JSch();

    String user = "sshusername";
    DoLog("User: " + user);

    String host = "yourserver.com";
    DoLog("Host: " + host);

    int port = 22;
    DoLog("Port: " + port);

    String privateKey = System.getProperty("user.dir") + "/" +  "yourserver.rsa";
    DoLog("Private Key: " + System.getProperty("user.dir") + "/" +  "yourserver.rsa");

    String sshPassPhrase = "@dd-y0ur-really-str0ng-ssh-pa$word-h3r3";

    DoLog("Adding ssh key passphrase to session");
    jsch.addIdentity(privateKey, sshPassPhrase);
    DoLog("Private Key added to ssh session");

    Session session = jsch.getSession(user, host, port);
    DoLog("Session Created");

    java.util.Properties config = new java.util.Properties();
// see http://stackoverflow.com/questions/30178936/jsch-sftp-security-with-session-setconfigstricthostkeychecking-no

    DoLog("SSH Config: StrictHostKeyChecking: no");
    config.put("StrictHostKeyChecking", "no");
    session.setConfig(config);

    DoLog("Connecting");
    session.connect();

    DoLog("Preparing Remote Command");
    String command = "uptime";

    Channel channel = session.openChannel("exec");
    ((ChannelExec)channel).setCommand(command);
    channel.setInputStream(null);
    ((ChannelExec)channel).setErrStream(System.err);

    InputStream input = channel.getInputStream();
    channel.connect();

    try {
        InputStreamReader inputReader = new InputStreamReader(input);
        BufferedReader bufferedReader = new BufferedReader(inputReader);
        String line = null;
        while((line = bufferedReader.readLine()) != null){
            System.out.println(line);
        }
        bufferedReader.close();

        inputReader.close(); }
    catch (IOException ex) {
        ex.printStackTrace();
    }
    channel.disconnect();

    session.disconnect();
    DoLog("SSH session disconnected.....");


} catch (Exception e) {
    System.err.println(e);
}

Output:

16:32:06 up 7 days, 14:59, 1 user, load average: 0.08, 0.02, 0.01

Read more on RSA keys here.

Generate an RSA key here.

Upload a file to a server via SCP over SSH

try {
    JSch jsch = new JSch();

    String user = "sshusername";
    DoLog("User: " + user);

    String host = "yourserver.com";
    DoLog("Host: " + host);

    int port = 22;
    DoLog("Port: " + port);

    String privateKey = System.getProperty("user.dir") + "/" +  "yourserver.rsa";
    DoLog("Private Key: " + System.getProperty("user.dir") + "/" +  "yourserver.rsa");

    String sshPassPhrase = "@dd-y0ur-really-str0ng-ssh-pa$word-h3r3";
    DoLog("Adding ssh key passphrase to session");
    
    jsch.addIdentity(privateKey, sshPassPhrase);
    DoLog("Private Key added to ssh session");

    Session session = jsch.getSession(user, host, port);
    DoLog("Session Created");

    java.util.Properties config = new java.util.Properties();

    //session.setConfig(
    //        "PreferredAuthentications",
    //        "publickey,gssapi-with-mic,keyboard-interactive,password");

    // disabling StrictHostKeyChecking may help to make connection but makes it insecure
    // see http://stackoverflow.com/questions/30178936/jsch-sftp-security-with-session-setconfigstricthostkeychecking-no

    DoLog("SSH Config: StrictHostKeyChecking: no");
    config.put("StrictHostKeyChecking", "no");
    session.setConfig(config);

    DoLog("Connecting");
    session.connect();


    DoLog("Preparing SFTP");
    Channel channel = session.openChannel("sftp");
    channel.setInputStream(System.in);
    channel.setOutputStream(System.out);
    channel.connect();

    ChannelSftp c = (ChannelSftp) channel;
    String fileName = "upload.txt";
    DoLog("Uplaoding file: " + fileName + " to " + "/");
    c.put(fileName, "/");
    c.exit();
    DoLog("Done Uploading File");
    channel.disconnect();



} catch (Exception e) {
    System.err.println(e);
}

On the server:

cat /upload.txt
>Hello World

Encrypt Text (AES/CBC/PKCS5/SHA-256)

public static byte[] encrypt(String strInput, String strPasswordKey) throws Exception {
    System.out.println("\n\nEncrypt()");
    byte[] clean = strInput.getBytes();

    // Generating IV
    int ivSize = 16;

    byte[] iv = new byte[ivSize];
    SecureRandom strRandom = new SecureRandom();
    
    strRandom.nextBytes(iv);
    IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
    
    // Hashing key
    MessageDigest strDigest = MessageDigest.getInstance("SHA-256");
    
    strDigest.update(strPasswordKey.getBytes("UTF-8"));
    byte[] keyBytes = new byte[16];
    
    System.arraycopy(strDigest.digest(), 0, keyBytes, 0, keyBytes.length);
    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
    
    // Encrypt
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParamSpec);

    byte[] encrypted = cipher.doFinal(clean);
    
    // Combine IV and encrypted part
    byte[] encryptedIVAndText = new byte[ivSize + encrypted.length];

    System.arraycopy(iv, 0, encryptedIVAndText, 0, ivSize);
    
    System.arraycopy(encrypted, 0, encryptedIVAndText, ivSize, encrypted.length);

    String senctext = new String(encrypted, StandardCharsets.UTF_8);

    System.out.println("   encrypted: " + senctext.toString() + ", encryptedIVAndText: " + encryptedIVAndText.toString() + ", size: " + ivSize + ", length: " + encrypted.length);

    return encryptedIVAndText;
}

Decrypt Text (AES/CBC/PKCS5/SHA-256)

public static String decrypt(byte[] encryptedIvTextBytes, String strPasswordKey) throws Exception {
    System.out.println("\n\ndecrypt()");
    int ivSize = 16;
    int keySize = 16;

    // Extract IV
    byte[] iv = new byte[ivSize];
    System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
    IvParameterSpec ivParamSpec = new IvParameterSpec(iv);

    // Extract encrypted part
    int encryptedSize = encryptedIvTextBytes.length - ivSize;
    byte[] encryptedBytes = new byte[encryptedSize];
    System.arraycopy(encryptedIvTextBytes, ivSize, encryptedBytes, 0, encryptedSize);

    // Hash key
    byte[] keyBytes = new byte[keySize];
    MessageDigest strDigest = MessageDigest.getInstance("SHA-256");
    strDigest.update(strPasswordKey.getBytes());
    System.arraycopy(strDigest.digest(), 0, keyBytes, 0, keyBytes.length);
    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");

    // Decrypt
    Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParamSpec);
    byte[] decrypted = cipherDecrypt.doFinal(encryptedBytes);

    return new String(decrypted);
}

Input Dialog and Display the Input text in a Dialog

// Input Dialog
TextInputDialog dialog = new TextInputDialog("Simon");
dialog.setTitle("Text Input Dialog");
dialog.setHeaderText("Look, a Text Input Dialog");
dialog.setContentText("Please enter your name:");
Optional<String> result = dialog.showAndWait();
System.out.println("Dialog Result: " + result);
Alert alertinputdialog = new Alert(AlertType.INFORMATION);
alertinputdialog.setTitle("Input Result");
alertinputdialog.setHeaderText(null);
if (result.isPresent()) {
    alertinputdialog.setContentText( "Result: " + result.get().toString());
} else {
    alertinputdialog.setContentText("Result: ");
}
alertinputdialog.showAndWait();

Input:

Java Input Box

GUI Output:

Java Dialog

Standard Message Box

// Standard Message Box
Alert alertmessagebox = new Alert(AlertType.INFORMATION);
alertmessagebox.setTitle("Base64 (Style 1/2)");
alertmessagebox.setHeaderText(null);
alertmessagebox.setContentText("About to convert '" + result.get().toString() + "' to Base64");
alertmessagebox.showAndWait();

Output:

Standard Message Box

Detailed Message Box

// Detailed Message Box
Alert alertwarning = new Alert(AlertType.WARNING);
alertwarning.setTitle("Base64 (Style 2/2)");
alertwarning.setHeaderText("About to convert '" + result.get().toString() + "' to Base64");
alertwarning.setContentText("Base64 strings can be reversed");
alertwarning.showAndWait();

GUI Output:

Detailed Java Message Box

Exception Dialog

//Exception Message Box
Alert alertexception = new Alert(AlertType.ERROR);
alertexception.setTitle("Exception Dialog");
alertexception.setHeaderText("Look, an Exception Dialog");
alertexception.setContentText("Could not find file blablah.txt!");
Exception ex = new FileNotFoundException("Could not find file blablah.txt");
// Create expandable Exception.
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
String exceptionText = sw.toString();
Label label = new Label("The exception stacktrace was:");
TextArea textArea = new TextArea(exceptionText);
textArea.setEditable(false);
textArea.setWrapText(true);
textArea.setMaxWidth(Double.MAX_VALUE);
textArea.setMaxHeight(Double.MAX_VALUE);
GridPane.setVgrow(textArea, Priority.ALWAYS);
GridPane.setHgrow(textArea, Priority.ALWAYS);
GridPane expContent = new GridPane();
expContent.setMaxWidth(Double.MAX_VALUE);
expContent.add(label, 0, 0);
expContent.add(textArea, 0, 1);
// Set expandable Exception into the dialog pane.
alertexception.getDialogPane().setExpandableContent(expContent);
alertexception.showAndWait();

GUI Output:

Exception dialog with a label textbox, textfield and button.

Close Application

Platform.exit();
System.exit(0);

Close Child Windows

  1. Add Label to the scene (so we can get the parent scene later)
  2. Declare the label in the Controller initialize function ( “public Label lblTitle;”)
  3. Close the stage
Stage stage = (Stage) lblTitle.getScene().getWindow();
stage.close();

Handle Listview Item Select

try{
	DoLog("Selected Server: " + lvwServers.getSelectionModel().getSelectedItem().toString() );
} catch( java.lang.NullPointerException null_error ) {
	return;
}

Open URL in Browser

try {
    Desktop.getDesktop().browse(new URI("https://fearby.com"));
} catch (IOException e1) {
    e1.printStackTrace();
} catch (URISyntaxException e1) {
    e1.printStackTrace();
}

Ask for Input, Add to listview and soft the listview

// Get Parent Stage (use existing label in scene)
Stage stage = (Stage) lblTitle.getScene().getWindow();

// Input Dialog
TextInputDialog dialog = new TextInputDialog("Apple");
dialog.setTitle("Enter a Fruit");
dialog.setHeaderText("Enter a Fruit");
dialog.initOwner(stage.getScene().getWindow());
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.setResizable(Boolean.FALSE);
dialog.setContentText("e.g enter a long description here...");

Optional<String> result = dialog.showAndWait();

if (result.isPresent()) {
    System.out.println( "Fruit: " + result.get());
    lvwFruit.getItems().add(result.get());
} else {
    System.out.println("Result: ");
}

// Sory Listview
lvwFruit.getItems().sorted();

Open FXML Scene File and Modal Child Window

        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("childscene.fxml"));
            Parent root1 = (Parent) fxmlLoader.load();
            Stage stage = new Stage();
            stage.initModality(Modality.APPLICATION_MODAL);
            stage.initStyle(StageStyle.UNDECORATED);
            stage.initStyle((StageStyle.UTILITY));
            stage.setTitle("Child Scene Window Title");
            stage.setScene(new Scene(root1));
            stage.show();
        }
        catch(IOException e) {
            e.printStackTrace();
        }

Base64 Encode and Decode

// Base 64
String sString = result.get().toString();
System.out.println("String sString: " + sString);
try {
    byte[] sbString = sString.getBytes("UTF-8");
    System.out.println("Byte Array - sbString: " + sbString);

    for(byte b : sbString){
        System.out.println(b);
    }
}
catch (Exception ex2)
{
    ex2.printStackTrace();
}
String sbbase64EncodedString = Base64.getEncoder().encodeToString(sString.getBytes());
System.out.println("Base64 Encoded - base64EncodedString: " + sbbase64EncodedString);
byte[] sbbase64DecodedString = Base64.getMimeDecoder().decode(sbbase64EncodedString);
String sbase64DecodedString = new String(sbbase64DecodedString);
System.out.println("Base64 Decoded - sbase64DecodedString: " + sbase64DecodedString);

// Message Box Result of Base64
Alert alertresult = new Alert(AlertType.INFORMATION);
alertresult.setTitle("Base64");
alertresult.setHeaderText("Input String: " + sString);
alertresult.setContentText("Base64 Encoded: " + sbbase64EncodedString + "\nDecoded Base64: " + sbase64DecodedString);
alertresult.showAndWait();

CLI Output:

> Base64 Encoded – base64EncodedString: U2ltb24=
> Base64 Decoded – sbase64DecodedString: Simon

GUI Output:

Message box with base64 text

OK and Cancel Confirmation Box

// MessageBox with Buttons
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirmation Dialog");
alert.setHeaderText("Look, a Confirmation Dialog");
alert.setContentText("Are you ok with this?");

Optional<ButtonType> result2 = alert.showAndWait();
if (result2.get() == ButtonType.OK){
    System.out.println("OK Clicked");
} else {
    System.out.println("Other Clicked");
}

GUI Output:

OK Cancel Dialog Box

Confirmation Box with four options

// Messagebox with many buttons
Alert alertmessaegmanyoptions = new Alert(AlertType.CONFIRMATION);
alertmessaegmanyoptions.setTitle("Confirmation Dialog with Custom Actions");
alertmessaegmanyoptions.setHeaderText("Look, a Confirmation Dialog with Custom Actions");
alertmessaegmanyoptions.setContentText("Choose your option.");
ButtonType buttonTypeOne = new ButtonType("Ubuntu", ButtonData.HELP_2);
ButtonType buttonTypeTwo = new ButtonType("Debian");
ButtonType buttonTypeThree = new ButtonType("Windows");
ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeTwo, buttonTypeThree, buttonTypeCancel);
Optional<ButtonType> result3 = alert.showAndWait();
if (result3.get() == buttonTypeOne){
    System.out.println("Ubuntu Clicked");

} else if (result3.get() == buttonTypeTwo) {
    System.out.println("Debian Clicked");

} else if (result3.get() == buttonTypeThree) {
    System.out.println("Windows Clicked");

} else if (result3.get() == buttonTypeCancel) {
    System.out.println("Cancel Clicked");

} else {
    System.out.println("Nothing Clicked");
}

GUI Output:

Confirmation box with four choices

Encrypt, Base64, AES/CBC/SHA-256 Encryption and Decrypt

fyi: Encrypt and Decrypt functions are above.

String sInputString = result.get().toString();
String sInputStringBas64 = Base64.getEncoder().encodeToString(sInputString.getBytes());
String sEncryptionKey = "pa$w1rd1";

try {
    byte[] encrypted = encrypt(sInputStringBas64, sEncryptionKey);

    String sEncryptedText = new String(encrypted, StandardCharsets.UTF_8);
    System.out.println(sEncryptedText);

    try {
        String sDecryptedText = decrypt(encrypted, sEncryptionKey);
        System.out.println("decrypted: " + sDecryptedText);

        byte[] sbbase64EncryptedDecodedString = Base64.getMimeDecoder().decode(sDecryptedText);
        String sbase64EncryptedDecodedString = new String(sbbase64EncryptedDecodedString);

        // Encryption Message Box
        Alert encryptionmessagebox = new Alert(AlertType.INFORMATION);
        encryptionmessagebox.setTitle("Encryption");
        encryptionmessagebox.setHeaderText(null);
        encryptionmessagebox.setContentText("Input String:\n" + sInputString
                        + "\n\n  Input as Base64:\n   " + sInputStringBas64
                        + "\n\n  Encryption Key:\n  " + sEncryptionKey
                        + "\n\n  Encryption Method:\n  AES/CBC/PKCS5Padding SHA-256 IV"
                        + "\n\n    Encrypted Text:\n    " + sEncryptedText
                        + "\n\n  Decrypted Text:\n  " + sDecryptedText
                        + "\n\nDecoded Base64:\n" + sbase64EncryptedDecodedString
        );
        encryptionmessagebox.showAndWait();
    }
    catch (Exception ee)
    {
        ee.printStackTrace();
    }
}
catch (Exception ex2)
    {
        ex2.printStackTrace();
    }

GUI Output:

Encrypt and decrypt

Credits 

Encryption Help: https://proandroiddev.com/security-best-practices-symmetric-encryption-with-aes-in-java-7616beaaade9

Dialogue Help: https://code.makery.ch/blog/javafx-dialogs-official/

General JavaFX Help: http://tutorials.jenkov.com/javafx/index.html

Ini File Help: Simple Java API Windows style .ini file handling. Also provide Java Preferences API
functionality on top of .ini file. https://sourceforge.net/projects/ini4j/

SSH JScH Help – JSch is a pure Java implementation of SSH2: http://www.jcraft.com/jsch/

JSch 0.0.* was released under the GNU LGPL license. Later, we have switched
over to a BSD-style license.

——————————————————————————
Copyright (c) 2002-2015 Atsuhiko Yamanaka, JCraft,Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.

3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
——————————————————————————

——————————————————————————

I hope this guide helps someone.

Please consider using my referral code and get $25 UpCloud VM credit if you need to create a server online.

https://www.upcloud.com/register/?promo=D84793

Ask a question or recommend an article

[contact-form-7 id=”30″ title=”Ask a Question”]

Revision History

v1.0 Initial Post

Filed Under: Code, Java Tagged With: code, java, jdx

PHP 7 code to send object oriented sanitised input data via bound parameters to a MYSQL database

November 1, 2017 by Simon

Sanitising user input is a golden rule with web developing (see https://www.owasp.org/index.php/Input_Validation_Cheat_Sheet ), here is my code snippet to sanitise and parameterise MySQL queries in PHP 7.0.

First, watch and follow @jawache (Asim Hussein) demo how common hacks happen and why you should update and patch software often, sanitise user data and set up a firewall.

I have blogged before on how to set up a Vultr server and configure it, How to secure Ubuntu in the Cloud, How to run an Ubuntu System Audit and Beyond SSL with Content Security Policy, Public Key Pinning etc but a 100% secure server is impossible as zero-day exploits and flaws (e.g WPA WiFi) remind us how limited technology lifespans can be. Yes, you can setup firewalls on Ubuntu and WordPress but you are only one exploit away from being hacked. Below is my code snippet (in PHP) to sanitise incoming data, query a MySQL database with object-oriented calls in PHP 7.0 and return data in variables. I have set up a firewall to block access to MySQL and non-essential ports (use https://www.shodan.io/ to test your server’s ports). I was using older deprecated PHP 5 era database calls and I researched newer calls available in PHP 7.0.

When you log in to an Ubuntu server and it says the following you should update

89 packages can be updated.
35 updates are security updates.

Also update software, node, npm etc

This code outputs too much information but will help you setup and get data on your servers (as long as you replace your database, table and field names).

<?php
echo "Last modified: " . date ("F d Y H:i:s.", getlastmod()) . "<br /><br />";
date_default_timezone_set('Australia/Sydney');

$dbhost = '127.0.0.1';
$dbusername = 'themysqlaccount';
$dbpassword = 'themysqlpassword';
$dbname = 'thedatabasename';
$con = mysqli_connect($dbhost, $dbusername, $dbpassword, $dbname);

//Debug stuff
//echo var_dump($con);
//printf(" - Error: %s.\n", $stmt->error);

if($con->connect_errno > 0){
    printf(" - Error: %s.\n", $stmt->error);
    die("Error: Unable to connect to MySQL (E001)");
} else {
 echo "Charset set to utf8<br />";
 mysqli_set_charset($con,"utf8");
}

if (!$con) {
    echo "Error: Unable to connect to MySQL (E002)" . PHP_EOL;
    echo "Debugging errno: " . mysqli_connect_errno() . PHP_EOL;
    echo "Debugging error: " . mysqli_connect_error() . PHP_EOL;
    exit;
} else {
    echo "Database Connection OK<br />";

    echo "&nbsp; Success: A proper connection to MySQL was made! The my_db database is great." . PHP_EOL . "<br />";
    echo "&nbsp; &nbsp;- Host information: " . mysqli_get_host_info($con) . PHP_EOL . "<br />";
    echo "&nbsp; &nbsp;- Server Info: '" . mysqli_get_server_info($con) . "'<br />";
    echo "&nbsp; &nbsp;- Server Protocol Info : ". mysqli_get_proto_info($con) . "<br />";
    echo "&nbsp; &nbsp;- Server Version: " . mysqli_get_server_version($con) . "<br />";
    //echo " - Server Connection Stats: " . print_r(mysqli_get_connection_stats($con)) . "<br />";
    echo "&nbsp; &nbsp;- Client Version: " . mysqli_get_client_version($con) . "<br />";
    echo "&nbsp; &nbsp;- Client Info: '" . mysqli_get_client_info() . "'<br />";

echo "Ready to Query the database '$dbname'.<br />";

// Input Var's that are parameterized/bound into the query statement
// I pre fill three vaiables with known fields in my users table
// Goot article in manual sanitization of strings in PHP http://php.net/manual/en/filter.filters.sanitize.php
    $in_username = mysqli_real_escape_string($con, 'FearTec');
    $in_f_guid = mysqli_real_escape_string($con, '5161a571-4a51-468d-9e96-6a5db5d35b1c');
    $in_mobile = mysqli_real_escape_string($con,'0456629533');

// Output Var's that the query fills after querying the database
// These variables will be filled with data from the current returned row
    $out_id = "";
    $out_f_guid = "";
    $out_username = "";
    $out_mobile = "";

echo "1. About to query the database: '$dbname'<br />";
$stmt = mysqli_stmt_init($con);
if (mysqli_stmt_prepare($stmt,"SELECT id, username, guid, user_mobile FROM thedatabasename WHERE username = ? AND guid = ? AND user_mobile = ?")) {

        echo "2. Query Returned<br />";

        /*
            Type specification chars
            Character   Description
            i   corresponding variable has type integer
            d   corresponding variable has type double
            s   corresponding variable has type string
            b   corresponding variable is a blob and will be sent in packets
        */
        mysqli_stmt_bind_param($stmt, 'sss', $in_username, $in_guid, $in_mobile);

        mysqli_stmt_execute($stmt);

        mysqli_stmt_bind_result($stmt, $out_id, $out_username, $out_guid, $out_mobile);

        mysqli_stmt_fetch($stmt);

        // Do something with the 1st returned row        
        echo " - Row: ID: $out_id, GUID: $out_guid, USR: $out_username, MOB: $out_mobile";//
        // Do we have more rows to process
        while($stmt->fetch()) { 
                // Deal with other rows
                echo " - Row: ID: $out_id, GUID: $out_f_guid, USR: $out_username, MOB: $out_mobile<br />";
        }
        mysqli_stmt_close($stmt);
        
        echo "c<br />";
    }
     else {
        echo "3. Error Querying<br/>";
        printf(" - Error: %s.\n", $stmt->error);
    }

}    

?>

Returned Data

Last modified: November 01 2017 16:43:01.
Charset set to utf8
Database Connection OK
  Success: A proper connection to MySQL was made! The my_db database is great. 
   - Host information: 127.0.0.1 via TCP/IP 
   - Server Info: '5.7.19-0ubuntu0.16.04.1'
   - Server Protocol Info : 10
   - Server Version: 50719
   - Client Version: 50012
   - Client Info: 'mysqlnd 5.0.12-dev - 20150407 - $Id: b5########################

Variable Bind Parameter Types

When you bind an incoming variable you can inform MySQL what the data type is expected to be.

mysqli_stmt_bind_param: Type specification chars
Character   Description
i   corresponding variable has type integer
d   corresponding variable has type double
s   corresponding variable has type string
b   corresponding variable is a blob and will be sent in packets

Debug Options

Errors Enabled: Turn on PHP Debug Errors On

Turning on errors on production servers is bad but on development.

First, find php.ini files

locate php.ini
/php.ini.bak
/.c9/metadata/workspace/etc/php/7.0/fpm/php.ini
/etc/php/7.0/apache2/php.ini
/etc/php/7.0/cli/php.ini
/etc/php/7.0/fpm/php.ini
/etc/php/7.0/phpdbg/php.ini
/usr/lib/php/7.0/php.ini-development
/usr/lib/php/7.0/php.ini-production
/usr/lib/php/7.0/php.ini-production.cli

Edit your appropriate PHP file

sudo nano /etc/php/7.0/fpm/php.ini

And turn on Error reporting.

Restart PHP and NGINX

sudo /etc/init.d/php7.0-fpm restart
sudo /etc/init.d/nginx restart

If you need to view your active php.ini file or see PHP configuration settings, add this to a .php file on your web server and view its contents.

<?php
phpinfo()
?>

It is amazing how clear errors can be

PHP Error

Dump Connection Vars: PHP mysqli_connect: var_dump($con)

echo var_dump($con);

Output:

public 'affected_rows' => int 0
  public 'client_info' => string 'mysqlnd 5.0.12-dev - 20150407 - $Id: b5###############################3

Show Environment Vars: mysqli_get_host_info, mysqli_get_proto_info, mysqli_get_server_version, mysqli_get_client_version and mysqli_get_client_info.

echo "&nbsp; Success: Database connection OK." . PHP_EOL . "<br />";
echo "&nbsp; &nbsp;- Host information: " . mysqli_get_host_info($con) . PHP_EOL . "<br />";
echo "&nbsp; &nbsp;- Server Info: '" . mysqli_get_server_info($con) . "'<br />";
echo "&nbsp; &nbsp;- Server Protocol Info : ". mysqli_get_proto_info($con) . "<br />";
echo "&nbsp; &nbsp;- Server Version: " . mysqli_get_server_version($con) . "<br />";
//echo " - Server Connection Stats: " . print_r(mysqli_get_connection_stats($con)) . "<br />";
echo "&nbsp; &nbsp;- Client Version: " . mysqli_get_client_version($con) . "<br />";
echo "&nbsp; &nbsp;- Client Info: '" . mysqli_get_client_info() . "'<br />";

Output:

Success: Database connection OK. 
   - Host information: 127.0.0.1 via TCP/IP 
   - Server Info: '5.7.19-0ubuntu0.16.04.1'
   - Server Protocol Info : 10
   - Server Version: 50719
   - Client Version: 50012
   - Client Info: 'mysqlnd 5.0.12-dev - 20150407 - $Id: b5########################################

Show errors in failed if  statements: mysqli_stmt_prepare else

printf(" - Error: %s.\n", $stmt->error);

Output:

Error: Table 'thedatabasename.invalidtablename' doesn't exist.

Debugging is your friend.

More to come..

Donate and make this blog better


Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]

V 1.0 initial post

Short (Article):

Ready to Query the database 'thedatabasename'. 1. About to query the database: 'thedatabasename' 2. Query Returned - Row: ID: 1, GUID: 0000000-0000-0000-0000-000000000001, USR: Bob, MOB: 1234567890 - Row: ID: 2, GUID: 0000000-0000-0000-0000-000000000002, USR: Joe, MOB: 1234567891 - Row: ID: 3, GUID: 0000000-0000-0000-0000-000000000003, USR: Jane, MOB: 1234567892

Variable Bind Parameter Types

When you bind an incoming variable you can inform MySQL what the data type is expected to be.


Debug Options

Errors Enabled: Turn on PHP Debug Errors On

Turning on errors on production servers is bad but on on development.

First, find php.ini files


Edit your appropriate PHP file


And turn on Error reporting.

Restart PHP and NGINX


If you need to view your active php.ini file or see php configuration settings, add this to a .php file on your web server and view it’s contents.


It is amazing how clear errors can be

PHP Error

Dump Connection Vars: PHP mysqli_connect: var_dump($con)


Output:


Show Environment Vars: mysqli_get_host_info, mysqli_get_proto_info, mysqli_get_server_version, mysqli_get_client_version and mysqli_get_client_info.


Output:


Show errors in failed if  statements: mysqli_stmt_prepare else


Output:


Debugging is your friend.

More to come..

Donate and make this blog better


Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]

V 1.0 initial post

Short (Article):

(length=79) public 'client_version' => int 50012 public 'connect_errno' => int 0 public 'connect_error' => null public 'errno' => int 0 public 'error' => string '' (length=0) public 'error_list' => array (size=0) empty public 'field_count' => int 0 public 'host_info' => string '127.0.0.1 via TCP/IP' (length=20) public 'info' => null public 'insert_id' => int 0 public 'server_info' => string '5.7.19-0ubuntu0.16.04.1' (length=23) public 'server_version' => int 50719 public 'stat' => string 'Uptime: 1828089 Threads: 1 Questions: 15702 Slow queries: 0 Opens: 1529 Flush tables: 1 Open tables: 1461 Queries per second avg: 0.008' (length=142) public 'sqlstate' => string '00000' (length=5) public 'protocol_version' => int 10 public 'thread_id' => int 7367 public 'warning_count' => int 0

Show Environment Vars: mysqli_get_host_info, mysqli_get_proto_info, mysqli_get_server_version, mysqli_get_client_version and mysqli_get_client_info.


Output:


Show errors in failed if  statements: mysqli_stmt_prepare else


Output:


Debugging is your friend.

More to come..

Donate and make this blog better


Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]

V 1.0 initial post

Short (Article):

Ready to Query the database 'thedatabasename'. 1. About to query the database: 'thedatabasename' 2. Query Returned - Row: ID: 1, GUID: 0000000-0000-0000-0000-000000000001, USR: Bob, MOB: 1234567890 - Row: ID: 2, GUID: 0000000-0000-0000-0000-000000000002, USR: Joe, MOB: 1234567891 - Row: ID: 3, GUID: 0000000-0000-0000-0000-000000000003, USR: Jane, MOB: 1234567892

Variable Bind Parameter Types

When you bind an incoming variable you can inform MySQL what the data type is expected to be.


Debug Options

Errors Enabled: Turn on PHP Debug Errors On

Turning on errors on production servers is bad but on on development.

First, find php.ini files


Edit your appropriate PHP file


And turn on Error reporting.

Restart PHP and NGINX


If you need to view your active php.ini file or see php configuration settings, add this to a .php file on your web server and view it’s contents.


It is amazing how clear errors can be

PHP Error

Dump Connection Vars: PHP mysqli_connect: var_dump($con)


Output:


Show Environment Vars: mysqli_get_host_info, mysqli_get_proto_info, mysqli_get_server_version, mysqli_get_client_version and mysqli_get_client_info.


Output:


Show errors in failed if  statements: mysqli_stmt_prepare else


Output:


Debugging is your friend.

More to come..

Donate and make this blog better


Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]

V 1.0 initial post

Short (Article):

Show errors in failed if  statements: mysqli_stmt_prepare else


Output:


Debugging is your friend.

More to come..

Donate and make this blog better


Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]

V 1.0 initial post

Short (Article):

Ready to Query the database ‘thedatabasename’. 1. About to query the database: ‘thedatabasename’ 2. Query Returned – Row: ID: 1, GUID: 0000000-0000-0000-0000-000000000001, USR: Bob, MOB: 1234567890 – Row: ID: 2, GUID: 0000000-0000-0000-0000-000000000002, USR: Joe, MOB: 1234567891 – Row: ID: 3, GUID: 0000000-0000-0000-0000-000000000003, USR: Jane, MOB: 1234567892

Variable Bind Parameter Types

When you bind an incoming variable you can inform MySQL what the data type is expected to be.


Debug Options

Errors Enabled: Turn on PHP Debug Errors On

Turning on errors on production servers is bad but on on development.

First, find php.ini files


Edit your appropriate PHP file


And turn on Error reporting.

Restart PHP and NGINX


If you need to view your active php.ini file or see php configuration settings, add this to a .php file on your web server and view it’s contents.


It is amazing how clear errors can be

PHP Error

Dump Connection Vars: PHP mysqli_connect: var_dump($con)


Output:


Show Environment Vars: mysqli_get_host_info, mysqli_get_proto_info, mysqli_get_server_version, mysqli_get_client_version and mysqli_get_client_info.


Output:


Show errors in failed if  statements: mysqli_stmt_prepare else


Output:


Debugging is your friend.

More to come..

Donate and make this blog better


Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]

V 1.0 initial post

Short (Article):

(length=79) public ‘client_version’ => int 50012 public ‘connect_errno’ => int 0 public ‘connect_error’ => null public ‘errno’ => int 0 public ‘error’ => string ” (length=0) public ‘error_list’ => array (size=0) empty public ‘field_count’ => int 0 public ‘host_info’ => string ‘127.0.0.1 via TCP/IP’ (length=20) public ‘info’ => null public ‘insert_id’ => int 0 public ‘server_info’ => string ‘5.7.19-0ubuntu0.16.04.1’ (length=23) public ‘server_version’ => int 50719 public ‘stat’ => string ‘Uptime: 1828089 Threads: 1 Questions: 15702 Slow queries: 0 Opens: 1529 Flush tables: 1 Open tables: 1461 Queries per second avg: 0.008’ (length=142) public ‘sqlstate’ => string ‘00000’ (length=5) public ‘protocol_version’ => int 10 public ‘thread_id’ => int 7367 public ‘warning_count’ => int 0

Show Environment Vars: mysqli_get_host_info, mysqli_get_proto_info, mysqli_get_server_version, mysqli_get_client_version and mysqli_get_client_info.


Output:


Show errors in failed if  statements: mysqli_stmt_prepare else


Output:


Debugging is your friend.

More to come..

Donate and make this blog better


Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]

V 1.0 initial post

Short (Article):

Ready to Query the database ‘thedatabasename’. 1. About to query the database: ‘thedatabasename’ 2. Query Returned – Row: ID: 1, GUID: 0000000-0000-0000-0000-000000000001, USR: Bob, MOB: 1234567890 – Row: ID: 2, GUID: 0000000-0000-0000-0000-000000000002, USR: Joe, MOB: 1234567891 – Row: ID: 3, GUID: 0000000-0000-0000-0000-000000000003, USR: Jane, MOB: 1234567892

Variable Bind Parameter Types

When you bind an incoming variable you can inform MySQL what the data type is expected to be.


Debug Options

Errors Enabled: Turn on PHP Debug Errors On

Turning on errors on production servers is bad but on on development.

First, find php.ini files


Edit your appropriate PHP file


And turn on Error reporting.

Restart PHP and NGINX


If you need to view your active php.ini file or see php configuration settings, add this to a .php file on your web server and view it’s contents.


It is amazing how clear errors can be

PHP Error

Dump Connection Vars: PHP mysqli_connect: var_dump($con)


Output:


Show Environment Vars: mysqli_get_host_info, mysqli_get_proto_info, mysqli_get_server_version, mysqli_get_client_version and mysqli_get_client_info.


Output:


Show errors in failed if  statements: mysqli_stmt_prepare else


Output:


Debugging is your friend.

More to come..

Donate and make this blog better


Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]

V 1.0 initial post

Short (Article):

Filed Under: Code, PHP, Security, Tech Advice, Ubuntu Tagged With: a, and, bound, code, data, database, MySQL, object, oriented, parameters, PHP 7, sanitise, send, to

NodeJS code to handle App logins via API (using MySQL connection pools (1000 connections) and query parameters)

August 7, 2017 by Simon

The below code is part of what I use to handle logins in an app. You can use this as a base for a NodeJS login routine (in a file called app.js). I was going to use StormPath API but was too slow and unreliable for  (as it turns out StormPath are merging with Okta and are closing down services).

This code is not functionally complete but you can hack out what you need. Rolling your own solution can be faster and slow you to fully embed in server side logic but make sure it is secure.
I am using these node modules (app.js).

var app = require('express')();
var http = require('http').Server(app);
var mysql = require('mysql');
var uuid = require('node-uuid');
var Type = require('type-of-is');
var jsesc = require('jsesc');
var bcrypt = require('bcrypt');
var filessystem = require('fs');

The following code is located in myutils.js is a  handy place to place your common code.  You don’t need it but it is demonstrated here.

module.exports = function(){ 
this.sum = function(a,b){
    return a+b
};
this.multiply = function(a,b){
    return a*b
    
  };
this.samplefunction = function(a){
    return 'Hello World'
    
  };
}

Don’t forget to include it myutils.js in app.js

require('./myutils.js')();  //Remove this if you dont use it

Declare the body parser module (app.js).

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

Set the MySQL connection details and you can setup the number of ready MySQL connections in the pool here (app.js).

console.log(' mysql_pool.createPool()');
var mysql_pool  = mysql.createPool({
  connectionLimit : 1000,
  host            : 'localhost',
  database        : 'thedatabasename',
  user            : 'thedatabaseuser',
  password        : 'thedatabasepassword'
  
});

Create a static API endpoint (app.js).

// Generic static API Point
app.get('/api/myappname/v1/hello/world/',function(req,res){
	var data = { "Version":"" };
	data["Version"] = "Hello World"; // Add a JSON value
	res.json(data); // Return the JSON
});

Create MySQL functions (app.js).

mysql_pool.getConnection(function(err, connection){
	// See if a connection is available in the pool by querying the database
	console.log(' mysql_pool.getConnection()');
	  	if (err) {
	  		console.log(' error: ' + err);
	  		throw err;
	  	}
	connection.query('select * from thedatabasename;',  function(err2, rows){
	  	if (err2) {
	  		connection.release();
	  		console.log(' error: ' + err2);
	  		throw err2;
	  	} else {
	  		console.log( rows );
	  		console.log('Ready');
	  	}
	  	connection.release();
	});
	console.log(' mysql_pool.release()');
});

mysql_pool.on('connection', function (connection) {
  connection.query('SET SESSION auto_increment_increment=1')
  console.log(' mysql_pool.on(connection) - Set session increment');
});

mysql_pool.on('enqueue', function () {
  console.log(' mysql_pool.on(enqueue). Waiting for available connection slot.');
});

/api/myappname/v1/login function (app.js).

// Login ----------------------------------------------------------------------- 
app.post('/api/myappname/v1/login',function(req,res){
	console.log('API CALL: /api/myappname/v1/login');

	var errData = "";

	// Check to see if the users posted token is valid
	var useraccesstoken = req.headers['x-user-access-token'];
	if (appaccesstoken == undefined) {
		// If a user token is missng then block the login, we only process logins whre valid user tokens are posted. Users are generated a token at acount creation
		console.log(" 498 token required");
		errData = {"Status": "498", "Error": "Invalid user token. Please login again (error 498)."};
		res.statusCode = 499;
		res.send(errData);
		res.end();
	}

	// I usually send an x-access-token in the posted JSON payload to eliminate older apps.
	var appaccesstoken = req.headers['x-access-token'];
	if (appaccesstoken == undefined) {
		// If an app  token is missng then block the login, we only process logins whre valid app tokens are posted.
		console.log(" 499 token required");
		errData = {"Status": "499", "Error": "Invalid app token. Please update your app (error 499)."};
		res.statusCode = 499;
		res.send(errData);
		res.end();

	} else {
		// ok we have a token posted
		var appaccesstokenpassed = false;

		// Check the API Key against known API Keys
		if (appaccesstoken == "appname33ffda6d-4303-4c65-81ca-0ccf0f172a37") { appaccesstokenpassed = true;} // Debug API Key for ICS 0.9.1
		
		// OK Process the posted data
		if (appaccesstokenpassed == true) {
			
			var userenteredemail = req.body.email;
			var userenteredpass = req.body.password; //todo: Add Encryption/Decryption (currenty a BCrypt Hash is sent from the app)

			// If this is Yes a new session token is sent to the user later, this will in valitae older logged in sessions.
			var resetsessions = req.body.resetsessions;
			if (req.body.resetsessions == undefined) {
				resetsessions = "Yes";
			}
			
			// Log for debugging
			console.log(' Email: ' + userenteredemail);
			console.log(' Password: ' + pass);
			console.log(' Reset Sessions: ' + resetsessions);
			
			var data = {}
			
			mysql_pool.getConnection(function(err, connection) {
			if (err) {
				console.log(' mysql_pool.release()');
				connection.release();
		  		console.log(' Error getting mysql_pool connection: ' + err);
		  		throw err;
		  	}
		  		// Revised SQL
		  		connection.query("SELECT * FROM usertablename WHERE usertablename.active=1 AND usertablename.lockedout=0 AND usertablename.email=? LIMIT 1",[userenteredemail],function(err, rows, fields){
				
					if (err) {

						// Log database errors
						console.log(" 503 Service unavailable (database error)");
						errData = {"Status": "503", "Error": "Service unavailable (database error)"};
						res.statusCode = 503;
						res.send(errData);	
						res.end();

					} else {
						
						// Do we have  a recordset
						if (rows.length != 0) {
							
							// Check password hash - https://github.com/ncb000gt/node.bcrypt.js
							var salt = rows[0].password_salt;
							var hash = rows[0].password_hash; 		// bcrypt.hashSync(pass, salt);
							
							hash = hash.replace(/^\$2y(.+)$/i, '\$2a$1');
							var passwordok = false;
							console.log(' About to check password.');
							
							passwordok = bcrypt.compareSync(userenteredpass, hash);

							console.log(passwordok);
							if (passwordok == true) {
							
							// Allow access to records
								var userid = rows[0].id;									// User ID
								var user_guid = rows[0].user_guid;							// Internal App Guid
								var push_guid = rows[0].push_guid;							// Internal GUID user for Push Notifications
								
								
								var newkey = rows[0].usertokenkey;								// Generate a new API secret key
								var newpass = rows[0].usertokenpassword;								// Generate a a new API secret pass

								// This will create two guids to use for all future api hiots from the user
								if (resetsessions == "Yes") {
									newkey = uuid.v4();										// Generate a new API secret key
									newpass = uuid.v4();									// Generate a a new API secret pass
								}

								var stat_total_logins = rows[0].stat_total_logins;			// Read total Logins are stored in my usedatabase
									stat_total_logins = stat_total_logins + 1;				// Increment total logins for later saving 
								
								var username = rows[0].username;							// Read the user Username from the database
								var usertag = rows[0].usertagline;							// Read the user Tagling from the database
								var email = rows[0].email;									// Read the user Email from the database
								
								var block_transactions = rows[0].block_transactions;		// Has the User Blocked Transactions
								var credit = rows[0].credit;								// Credit Remaining
								var currency = rows[0].currency;							// Users Currency (used for the log)

								var smssendalertatlogin = rows[0].user_pref_sms_alert_at_login;  	// Does the user want SMS Sent a Login
								var emailsendalertatlogin = rows[0].user_pref_email_alert_at_login; 	// Does the user want an email
								var pushsendalertatlogin = rows[0].user_pref_push_alert_at_login;	// Push alert the user at login
								
								var user_pref_timezone = rows[0].user_pref_timezone;
								var user_pref_timezone_int = rows[0].user_pref_timezone_int;
								
								var stat_total_password_resets = rows[0].stat_total_password_resets;		// Pass this throgh to the App
								
								var active = rows[0].active;								// Is the user active
								var lockedout = rows[0].lockedout;							// Is the user locked ut
								var changing_password = rows[0].changing_password;

								var querylimit5min = rows[0].QueryLimit5Min;				// Read from he databse how manu API hits the user has a minute
								
								// I like to return the api version and version int with all api JSON payloads (makes checking on the App side easier)
								var jsonvalid = "yes";
								var jsonversion = "2017.01.01.22.00";
								var jsonversionint = "102";
								
								//Update API Keys
								mysql_pool.getConnection(function(err, connection) {
									if (err) {
										console.log(' mysql_pool.release()');
										connection.release();
								  		console.log(' Error getting mysql_pool connection: ' + err);
								  		throw err;
								  	}
								  	// Update the users logins and new keys if thye asked to wipe all past logins.
									connection.query('UPDATE usertablename SET usertokenkey = ?, usertokenpassword = ?, stat_total_logins = ?, last_login = NOW() WHERE id = ?', [newkey, newpass, stat_total_logins, userid],function(errupdate, rowsupdate, fieldsupdate){
										if (errupdate) {
											console.log(" 503 service unavailable (database update error)");
											errData = {"Status": "503", "Error": "503 service unavailable (database update error)"};
											res.statusCode = 503;
											res.send(errData);
											res.end();
										} else {
											if (rowsupdate.length != 0) {
												// Inform User of Valid  Login
												res.statusCode = 200;
												data["Data"] = "Successfully logged in..";									// statis string thta reports the successfull login
												
												// The Key and Pass are used liek OAUTH tokens and are stored in the app and user database. All API hits check these tokens. 
												data["Key"] = newkey;                       								//LOADS IN XCODE v0.9.1
												data["Pass"] = newpass;                      								//LOADS IN XCODE v0.9.1
												
												// User guids are used to store the unique user rather than the database record ID
												data["user_guid"] = user_guid;
												data["push_guid"] = push_guid;												// Internal GUID user for Push Notifications

												data["Logins"] = stat_total_logins;											// Total Logins are stored in my usedatabase
												data["Username"] = username;												// Username
												data["Email"] = email;														// Email
												
												// The notify user code ay ogin has been removed byt can be called here
												data["SMSAtLogin"] = smssendalertatlogin;
												data["EmailAtLogin"] = emailsendalertatlogin;
												data["PushAtLogin"] = pushsendalertatlogin;
												
												// What is the users timezome
												data["timezone"] = user_pref_timezone;
												data["timezoneint"] = user_pref_timezone_int;
												
												
												data["stat_total_password_resets"] = stat_total_password_resets;			// How many times has the user changed passwords
												
												data["active"] = active;													// Is the user active
												data["lockedout"] = lockedout;												// Is th user currently locked out
												data["changing_password"] = changing_password;								// Is the user currebtky changing a password
												
												data["levelquerylimit5min"] = querylimit5min;								// How any times can the user hit the API (handled by the app)
	
												data["jsonvalid"] = jsonvalid;												// JSON ID
												data["jsonversion"] = jsonversion;											// JSON Version
												data["jsonversionint"] = jsonversionint;									// JSON Version
												
												// Send the JSON back to the user
												res.json(data);
												res.end();
												
												//Login Confirmed
												console.log("User " + username + " / " + email + " logged in.");
												
											} else {
												console.log(" 504 service unavailable (database update error)");
												errData = {"Status": "504", "Error": "504 service unavailable (database update error)"};
												res.statusCode = 504;
												res.send(errData);
												res.end();		
											}
										}
										console.log(' mysql_pool.release()');
										connection.release();				// release the MySQL connection pool connection
									});	
								});
								
							} else {
								console.log('402 Invalid Login (' +  req.body.email + ', ' + req.body.password + ')');
								errData = {"Status": "402", "Error": "Invalid Login"};
								res.statusCode = 402;
								res.send(errData);
								res.end();								
							}
	
						} else {
							console.log('403 Account is locked out, not active or unknown. Please visit https://www.myappname.com to reactivate your account. (' +  req.body.email + ')');
							errData = {"Status": "403", "Error": "Account is locked out, not active or unknown."};
							res.statusCode = 403;
							res.send(errData);
							res.end();	
						}
					}
					console.log(' mysql_pool.release()');
					connection.release();
					
				});
			});

		} else {
			console.log("499 token required");
			errData = {"Status": "499", "Error": "Invalid app token. Please update your app (error 499)."};
			res.statusCode = 409;
			res.send(errData);	
			res.end();
		}
	}
});

/api/myappname/v1/verifylogin verify login function (app.js).

// Verify Login ----------------------------------------------------------------------- 
app.post('/api/myappname/v1/verifylogin',function(req,res){
	console.log('API CALL: /api/myappname/v1/verifylogin');
	
	// check to see if the App included an api key
	var appaccesstoken = req.headers['x-access-token'];

	var errData = "";
	if (appaccesstoken == undefined) {
		console.log(" 499 token required");
		errData = {"Status": "499", "Error": "valid token required"};
		res.statusCode = 499;
		res.send(errData);
		res.end();

	} else {

	//console.log(" Received appaccesstoken: " + appaccesstoken);
		var appaccesstokenpassed = false;
		// Check the API Key against known API Keys
		if (appaccesstoken == "ics201701-1d95-9271-a6c7-a9a33770287") { appaccesstokenpassed = true;} // Debug API Key
		if (appaccesstokenpassed == true) {
			var key = req.body.key;
			var pass = req.body.pass;
			var data = {} 

			console.log(" - Key: " + key )
			console.log(" - Pass: " + pass )
			
			// Grab the user IP and log it
			var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
			console.log(" - IP: " + ip );
			
			mysql_pool.getConnection(function(err, connection) {
			if (err) {
				console.log(' mysql_pool.release()');
				connection.release();
		  		console.log(' Error getting mysql_pool connection: ' + err);
		  		throw err;
		  	}
		  	// Check the user record (only if the user is active and provided thier token key and passowrd)
		    connection.query("SELECT * FROM usertablename WHERE active=1 AND usertokenkey=? AND usertokenpassword=? LIMIT 1",[key, pass],function(err, rows, fields){
				if (err) {
					console.log(" 405 Login Session Expired");
					errData = {"Status": "405", "Error": "Login Session Expired"};
					res.statusCode = 405;
					res.send(errData);	
					res.end();
				} else {
					if (rows.length != 0) {
						console.log(" 200 Login Session OK");
						res.statusCode = 200;
						data["Status"] = "OK";
						res.json(data);
						res.end();
					} else {
						console.log(" 405 Login Session Expired");
						errData = {"Status": "405", "Error": "Login Session Expired"};
						res.statusCode = 405;
						res.send(errData);	
						res.end();
					}
				}
				console.log(' mysql_pool.release()');
				connection.release();
			});
			});
		} else {
			console.log("499 token required");
			errData = {"Status": "499", "Error": "valid token required"};
			res.statusCode = 409;
			res.send(errData);	
			res.end();
		}
	}
});

Start the web service (app.js).

http.listen(3000,function(){
	console.log("Connected & Listen to port 3000 at /api/myappname/v1/ ..");
	console.log(" Do..");
	
});

Hope this helps

Donate and make this blog better




Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]

V1.0 Initial Post

Filed Under: API Tagged With: code, MySQL, NodeJS

Setting up GitHub on an iMac and creating a project

June 25, 2017 by Simon

Here is my quick guide on setting up a new GitHub repository on an iMac adding files and syncing with a  repository. Read the GitHub 101 if you are a beginner. Read my BitBucket guide here.

Why

Using git allows you to make backups, use code versioning, rollback code, use multiple development machines/have multiple users, auto merging code etc.

Github can be cheaper, more flexible and offer more features than something like Dropbox.

How

Create an account at GitHub and Login ( https://github.com/login ).

Don’t forget to set up Two Factor Authentication for extra security.

Login to GitHub (signup for a free account if need be).

Enter your Two Factor Authentication code every time you login.

Before you can read or write to your Git repository you need to set up a link between your computer (Mac) and GitHub by Setting up a Secure SSH Key with GitHub. About SSH.

If you have read any of my guides on setting up servers (e.g The quickest way to setup a scalable development IDE and web server, How to buy a new domain and SSL cert from NameCheap, a Server from Digital Ocean and configure it or Connecting to an AWS EC2 Ubuntu instance with Cloud 9 IDE as user ubuntu and root ) you will be familiar with SSH keys.

You can check your existing SSH Keys by typing the following.

ls -al ~/.ssh

Follow this GitHub guide on creating a new SSH key to use with GitHub.

I found I had to do the following in the Mac terminal to get this to work.

eval "$(ssh-agent -s)"
mkdir /gitrsatemp
cd /gitrsatemp
sudo ssh-keygen -t rsa -b 4096 -C "[email protected]"
# specify output as /gitrsatemp/githubrsa
# used a passphrase from https://www.grc.com/passwords.htm
mv /gitrsatemp/* ~/.ssh/
cd ~/.ssh/
ssh-add -K ./githubrsa

You can now add your SSH key to GitHub. 

cd ~/.ssh/ 
sudo pbcopy < ./githubrsa.pub

You can then add your public key to https://github.com/settings/keys

Add the SSH Key.

You can then test the SSH connection to GitHub.

At first, I tried this but got an error.

sudo ssh -T [email protected]
The authenticity of host 'github.com (192.30.255.113)' can't be established.
RSA key fingerprint is SHA256:key_redacted.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.30.255.113' (RSA) to the list of known hosts.

This is what I got when I added my SSH Key to my GitHub account. This worked for me (this updated my known_hosts file).

sudo ssh -T [email protected]
Hi SimonFearby! You've successfully authenticated, but GitHub does not provide shell access.

Tip: Don’t forget to save adding your SSH Key to GitHub

If you need help contact GitHub.

GitHub Pricing

GitHub offers free public repository pricing or $7 a month for unlimited personal repositories for personal use. Bitbucket is the Atlassian owned alternative to GitHub, they have free repositories for up to 5 users with 1TB.

Read my Setting up BitBucket on an iMac and creating a project guide.

Read on the differences between GitHub and BitBucket.

Create your first test public Repository. 

Load https://www.github.com and click Start a Project, or go to https://github.com/new

To specify a Readme file and an ignore file if need be (we can do this later). You will need to be a paid Git member to create private repositories.

When your repository is created it will be ready to upload files: https://github.com/SimonFearby/testgitproject001

Creating a local folder

Create a local folder for the repository etc.

# create a folder on your desktop
cd ~/Desktop/
mkdir testgitproject001
cd testgitproject001/

# Check the git status
git status
fatal: Not a git repository (or any of the parent directories): .git

# the folder is now ready files from the repository.

Liking the remote repository to the local folder.

First, we need to initialize git locally by typing the following.

git init
> Initialized empty Git repository in /Users/simon/Desktop/testgitproject001/.git/

Now we can add the remote “origin” repository to the local repo.

git remote add origin [email protected]:SimonFearby/testgitproject001.git

We can now see connected remote repositories by typing the following

git remote -v
origin	[email protected]:SimonFearby/testgitproject001.git (fetch)
origin	[email protected]:SimonFearby/testgitproject001.git (push)

Syncing (Pulling) the Repository

Generally, you want to pull all files from the remote repository after you create it (and the readme file).

git pull origin master

This worked 🙂

# What directory are we in
pwd
/Users/simon/Desktop/testgitproject001

# No files
ls -al
total 0
drwxr-xr-x   3 simon  staff   102 28 Jun 00:19 .
drwx------+ 53 simon  staff  1802 28 Jun 00:00 ..
drwxr-xr-x  10 simon  staff   340 28 Jun 00:21 .git

# Let's get the repo files

git pull origin master
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (3/3), done.
Unpacking objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
From github.com:SimonFearby/testgitproject001
 * branch            master     -> FETCH_HEAD
 * [new branch]      master     -> origin/master

# Is the readme is there.
ls -al
total 32
drwxr-xr-x   5 simon  staff    170 28 Jun 00:30 .
drwx------+ 53 simon  staff   1802 28 Jun 00:00 ..
drwxr-xr-x  13 simon  staff    442 28 Jun 00:30 .git
-rw-r--r--   1 simon  staff  11357 28 Jun 00:30 LICENSE
-rw-r--r--   1 simon  staff     49 28 Jun 00:30 README.md

Pulling, Pushing, Branches and Forking.

You can read more about pulling, pushing, branches and forking here.

This course helped me https://www.udemy.com/learn-android/

Adding your first local file(s) to the repository

Adding all files to the new directory.

git add -A

Adding a single file:

git add newfilename.txt

Here is an example of adding a new file.

# Create a new file
touch newfilename.txt

#edit the file.
sudo nano newfilename.txt

# Tell git we want this file to be managed
git add newfilename.txt

# What is the status of this repository
git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

Set your default commit username (help)

git config --global user.name "Mona Lisa"

Set your default commit email address (help).

git config --global user.email "[email protected]"

Double-check config here

git config --global --edit

You will need to use vim to insert then save changes. I like the nano text editor better so I am changing the default editor.

Setting your default as nano (and not vim)

nano (and not vim)

git config --global core.editor nano

Submitting (pushing) changes

# Create a new file locally
touch newfilename.txt

# edit the local file
sudo nanonewfilename.txt

# Tell git we want to include it.
git addnewfilename.txt

# commit the file to the remote (origin) server with a commit message
git commitnewfilename.txt -m "addednewfilename.txt"

# Merge all changes with the remote (origin) server
git push origin master

The changes have been pushed (merged)

Adding another file.

This is how I added another single file locally and pushed to the remote (origin) server

# Create a new file locally
touch anothernewfile.txt

# edit the local file
sudo nano anothernewfile.txt 

# Tell git we want to include it.
git add anothernewfile.txt 

# commit the file to the remote (origin) server with a commit message
git commit anothernewfile.txt -m "added anothernewfile.txt"

# Merge all changes with the remote (origin) server
git push origin master

Now we have two new public files in a repository and locally.

README.md and markdown 

Now we need to make the README.MD file look nice and reflect the changes.

More info in markdown formatting here, here, here and here. Here is a good markdown table generator.

I made some changes (see) and pushed to the repository (origin).

# edit the file
sudo nano README.md 

# Tell git we want to commit the changes
git commit README.md -m "edited README.md"

# Merge local changes with the remote repository (origin)
git push origin master

My local README.md markdown changes

# testgitproject001
Simon's Test Git Project 001

# *Added* **two** test __text__ files (~~they are not important~~)

- [x] newfilename.txt
- [x] anothernewfilename.txt
- [ ] notmergedlocalfile.txt

## This is for my (GitHub guide on my blog](https://www.fearby.com/article/setting-up-github-on-an-imac-and-creating-a-project/)

Inline-style: 
![Simon Fearby Avatar](https://fearby.com/Avatar.jpeg "Simon Fearby Avatar")

This is what is looks like on GitHub after I commit and push

You can use pages on GitHub with markdown to create versioned documentation and help.

Commit and check the git status frequently

It is strongly advisable to frequently commit files (to a staging/not master repository) and check local it status for any issues. Commit as frequently as you remember.

# A forgotten local edit
sudo nano README.md 

# Show a gitstatus report
git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")

You can push or delete changes if need be.

Adding many subfolders and many files.

Let’s say you have just added three subfolders (iOS Project Code (12 files), Android Projet Code (1255 items) and a Windows Desktop Project Code (.NET) folder (27 items) and you want to add them all to the remote repository (origin).

Now we need to add the 1,294 files to the local repository.

We can simply type the following to tell git we want it to manage all the local files.

# Add all sub folders and files in tbhis folder.
git add .

# Show a local status report.
simon$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   .DS_Store
	new file:   Android Project Code/.gitignore
	new file:   Android Project Code/.idea/.name
	new file:   Android Project Code/.idea/compiler.xml
	new file:   Android Project Code/.idea/copyright/profiles_settings.xml
.. 1000+ orther files are listed

Now you can merge the files top remote repository (origin).

git push origin master

Don’t forget to updates your README.md file with changes.

fyi: GitHub may take a minute or two to show changes.

# Edt the README.md
sudo nano README.md 

# Commit the changed file
git commit README.md -m "edited README.md again"

# merge chnages.
push origin master

Ignoring local files

You may want to ignore local files or folders.  In your git folder type.  I like to ignore all files with “secret” in the filename.

AWS recommend you ignore secret keys and logs to prevent inadvertent account access via sharing secret keys.

# Edit your repositories ignore file
sudo nano .git/info/exclude

# Add These exclusions
secret*.*
*secret.*
*secert*.*
*.secret*
*.*secret
*.*secret*

You can find other things to ignore here. You can setup global ignore list by reading this.

You can see I have created a few secret files and new thirdnewfile.txt (and added it to git) and committed and pushed and the secret files remain local (they will remain local while they match the ignored list).

ls -al
total 112
drwxr-xr-x  15 simon  staff    510 28 Jun 15:31 .
drwx------+ 53 simon  staff   1802 28 Jun 14:53 ..
[email protected]  1 simon  staff  12292 28 Jun 15:00 .DS_Store
drwxr-xr-x  14 simon  staff    476 28 Jun 15:34 .git
drwxr-xr-x  15 simon  staff    510 28 Jun 14:59 Android Project Code
-rw-r--r--   1 simon  staff  11357 28 Jun 00:30 LICENSE
-rw-r--r--   1 simon  staff    544 28 Jun 15:19 README.md
drwxr-xr-x   6 simon  staff    204 28 Jun 15:00 Windows Desktop Project Code
-rw-r--r--   1 simon  staff     10 28 Jun 14:06 anothernewfile.txt
drwxr-xr-x   5 simon  staff    170 28 Jun 14:49 iOS Project Code
-rw-r--r--   1 simon  staff     17 28 Jun 15:30 my.secret
-rw-r--r--   1 simon  staff     10 28 Jun 01:10 newfilename.txt
-rw-r--r--   1 simon  staff     26 28 Jun 15:23 secertapikey.txt
-rw-r--r--   1 simon  staff     22 28 Jun 15:23 secretfile.txt
-rw-r--r--   1 simon  staff     21 28 Jun 15:31 thirdnewfile.txt

GitHub view.

Local Git View

Note the secret files.

GitHub Desktop Application

I checked out the GitHub Desktop application at https://desktop.github.com/.

The downloaded compressed file.

I extracted and copied the app to the Applications folder.

Now I logged into to the application.

Much respect to GitHub for integrating Two Factor Authentication into the login.

Unfortunately, GitHub Desktop thinks I have zero repositories (I have 9 repositories when I log in via the web using the same email address). I contacted support on Twitter but have not had a response yet?

I was able to clone the repository I made via the command line earlier or add a local repository.

I added a new text file (afileaddedwithgithubdesktop.txt) to the folder and GitHub Desktop noticed this new file straight away. I added this file to the repository.

I pushed all local changes to the origin/remote master repository.

All local changes were merged with the remote origin master (I could never do this with Atlassian’s SourceTree application).

Conclusion

Now I can sync up my projects that to GitHub repositories from the terminal and GitHub Desktop application and benefit from the features of git (backups, versioning, rollbacks, multiple machines/multiple users, auto merging etc).

Next

I will add how to pull a repository to a $5 month Digital Ocean and or AWS (Ubuntu) VM.

Read my Setting up BitBucket on an iMac and creating a project guide.

Git repositories on Raspberry Pi’s.

Related guides

Setting up a development environment on Digital Ocean 14.04

https://www.digitalocean.com/community/tutorials/how-to-install-git-on-ubuntu-14-04

Tips and Troubleshooting

GitHub has a good tips page here.  I had @GitHubHelp pro-actively contact me for support on Twitter. Contact GitHub here.

How to add all local files and commit all local files.

git add -A && git commit

I hope this is helpful to someone.

20 essential git tips. 

P.S Don’t edit live code, use GitHub.

Agile Project Management

Read my blog post on developing software and staying on track here.

I highly recommend you follow Dmitri Iarandine at http://joinagile.com/ (Agile Coach, Trainer, Host of Lean and Mean Agile). Podcast. Author of GET HIRED as SCRUM MASTER).

Dmitri can be found here too.

Soundcloud (Lean and Mean Agile Podcast):
https://soundcloud.com/user-364782318

iTunes:
https://itunes.apple.com/au/podcast/lean-and-mean-agile-podcast/id1269551866

YouTube:
https://www.youtube.com/channel/UC00OZqfM9VmznEOTVzrQQxw

Twitter:
http://twitter.com/iarandine

Udemy:
https://www.udemy.com/agile-coaching-101/

Amazon:
https://www.amazon.com/author/iarandine

Donate and make this blog better




Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]

v1.7 added info on agile and staying on track,

Filed Under: Git, GitHub Tagged With: add, code, git, merge, pull, push, rfep[ository, rollback, versions

How to get started in programming

June 22, 2016 by Simon Fearby

Today I was asked: Should I learn to code in Swift and what can I build? Swift 1.0 (http://www.swift.org) was launched in 2014 by Apple and it is a multi-platform programming language for iOS, macOS and Linux (but not Windows). Swift has gone through rapid changes recently and Swift 4.0 is the latest stable version. Swift updates can break a number of previous swift coding standards set in Swift 1.x, 2.x and 3.x so don’t get comfortable.

Should a beginner learn Swift? Yes if you only want to develop apps for iOS and macOS and ignore Windows and Android platforms. Apple has released a learn to code in Swift app that will make learning swift much easier http://www.apple.com/swift/playgrounds/

Previously apple recommended developers use the Objective C language to code and compile apps for iOS and macOS. Objective C has been in production since 1983 and is very complex (loads of squiggles, square brackets and legacy classes).

Most smartphones and tablets run Android, not because they are better but because they are cheaper (that’s my opinion). A top of the line iPhone 6S+ costs $1500 where a reasonable Android phone will set you back about $130 to $400. I personally think Apple devices are faster, better and more secure but if you are developing you need to publish apps on android also.  Apple devices are supported for a lot longer than Android devices ( Android support lifetime v Apple iOS ).  Even the 5-year-old iPad 2 is getting the iOS 10 software update in September 2016.  In 2017 iOS 11 does not run on an iPad 2.

If you wanted to native develop android apps you would need to learn Java in the https://developer.android.com/studio/index.html IDE. Be prepared to be confused as the Android Studio has a steep learning curve.

Ok so where do beginners start.

What Companies look for when hiring programmers

https://youtu.be/QbSD4EtpVdY

Jumping right into Swift, Java, Objective C or Lua may not be a good idea if a plain old website will do. It depends on what you want to develop before you start coding. All developers should be able to knock up a website and database before jumping into making mobile apps. PHP ( http://www.php.net ) and MySQL ( http://www.mysql.com ) are good options for beginners making websites.

http://www.udemy.com and http://www.w3schools.com/ is a great place to go to learn more about coding. If you want to see what the Pro’s are doing check out http://www.sitepoint.com are great places for learning WHAT you need to know fast.

But I really want to develop a mobile app.

Development platforms like the Corona SDK http://www.coronalabs.com are a great option for beginners as it is easy to pick up and is super fast and supports eye-popping OpenGL animations and apps along with business apps. Corona allows you to code in a programming language called Lua ( https://www.coronalabs.com/learn-lua ) and compiles your app to the iOS/Android/macOS or Windows desktops. How cool is that.

Corona APp

Another possible solution is using the Electron technology

Corona wraps a common interface (API  https://docs.coronalabs.com/API/index.html) over each platforms API so your code calls the corona API and when you compile your app the platforms native API methods are called.

Corona has great guides and support pages:

https://docs.coronalabs.com/guide/programming/index.html – Getting Started

https://docs.coronalabs.com/guide/index.html –

https://coronalabs.com/blog – Keep up to date with Corona and read guides on many topics.

https://coronalabs.com/resources – Corona Resources.

https://www.youtube.com/user/CoronaGeek – Weekly Corona video podcast.

https://forum.coronalabs.com – Talk to hundreds of Corona developers and ask questions.

https://docs.coronalabs.com/api/index.html – Corona API

What tools do you need

  • A Mac Computer with a retina display.
  • Sublime text Editor https://www.sublimetext.com/3 (and Sublime to Corona Plugin https://coronalabs.com/products/editor/ )
  • Source Version Software http://www.zenaware.com/cornerstone
  • A good code snippet saving app is http://snippets.me/
  • Patience and drive.

Knowing what you want to develop will narrow down the technologies you need to learn.

Summary:

  • If you want to make websites learn HTML and PHP.
  • If you want to build business apps inside corporations learn Visual Studio.NET
  • If you want to make mobile apps fast learn Corona.
  • If you want to make advanced iOS apps learn Swift
  • If you want to make advanced Android apps learn Android Studio
  • If you want to make online database learn MySQL

Check out my guides here on:

How to build your first cross-platform mobile app with corona

Creating a development server for $5 a month

What is the difference between a website, app, web app, hybrid app and software?

..and many more free guides here.

Happy coding.

Still reading?  Check out the beginner guides on Sitepoint.

Donate and make this blog better




Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]

V1.2. Added short link

Sort: https:/fearby.com/go2/learn/

Filed Under: Apple, Cloud, CoronaLabs, Development, MySQL, Scalable, Security Tagged With: Android, build, code, corona, iOS, test

Computer hardware, clock cycles and code ramblings

April 18, 2016 by Simon Fearby

Modern computers have insane amounts of processing power compared to computers from 5 years ago. Computer memory and storage is cheap but that is no excuse to design and develop bloated webpages and apps. Consumers and customers are very impatient and there are loads of statistics on users abandoning an app or website because it takes more than three seconds to respond or load an app.

You can control the speed of software running on your home computer by upgrading it but you cannot guarantee the performance of apps that run on shared hosting platforms or web hosts.  You can buy a CPanel based web-host or a dedicated server from $5 a month, how can they make money? They do this by virtually hosting your service (web server etc) alongside other hosts and running multiple services on a single processor core. Shared servers are very economical but you are sharing the resources with other users.

If you want maximum performance you can always buy a dedicated server from a cloud server provider but each provider may secretly share the resource’s of that server (more information here: http://blog.cloudharmony.com/2014/07/comparing-cloud-compute-services.html ) and performance may be impacted. Dedicated servers can be very expensive and can run into thousands of dollars per month.

So what can I control?

Writing (or installing) good code is essential, try and optimize everything and know your server’s limitations and bottlenecks. To understand bottlenecks, you need to know about computer hardware. A few lines of code can trigger millions or billions of actions inside a processor.

A computer has the following major components:

  • Hard drive (HDD/SSD): This is where your operating system, software and files are stored when the computer is turned off. Hard drives store magnetic charges (0’s and 1’s) onto spinning round metal platters. A zero is a negative charge and a 1 is a positive charge. Hard drives spin at 5400~15,000 RPM. Data is written with a read/write needle that needs to be positioned over the data bit to read and write. Hard drives are very slow but reliable and each data bit can be read/written to tens of thousands of times. Faster solid-state drives don’t use spinning metal platters and work a bit like memory (see below). Solid-State drives have limited writes per sector though. Read More: https://en.wikipedia.org/wiki/Hard_disk_drive
  • Memory (RAM): Computer memory is basically a large array or very fast storage that the processor reads and writes data (0’s and 1’s). Memory is like a massive spreadsheet grid and accessing data from memory is 1000x faster than accessing data from a hard drive.  Memory stores data as static charges in silicon microchips and each storage bit can be changed millions of times. When a computer is turned off the memory is wiped. Read More: https://en.wikipedia.org/wiki/Computer_memory
  • Processor (CPU): This is the chip that does the primary calculations and controls just about everything. A processor can perform various predetermined functions and read and write to memory/hard drives or send data over a USB cable or network connection. Processors are quite dumb and it has to keep queues (pipelines) of things to do in it’s the internal cache (memory) between cycles.  A clock cycle is single step where the processor (and all of it’s cores) do one thing and get ready for the next clock cycle, all clock cycles in a software routine are linked and if one instruction fails all following linked instructions have to be cleared and dealt with or errors and blue screens can happen. A processors speed is a total of how may clock cycles it can perform in a second and a modern computer can process 3,500,000,000 (3.5 Ghz) cycles a second. A processor can calculate one complex instruction or multiple simple instructions in one cycle. Most processors have multiple cores that can each perform calculations in a clock cycle. But don’t be fooled many clock cycles are spent waiting for data to be read/written from memory/hard drive or loaded from the processor’s cache. A processors instruction pipeline has 4 main states for each possible action in a cycles execution pipeline (“Fetch”, “Decode”, “Execute” and “Write back”). (e.g The processor may be asked to add (fetch) variable1+variable2, the (decode) gets the values from memory, (execute) performs the calculation and “write back” writes the result back to memory. ) See a complete list of Intel instruction here and here ). Read More: https://en.wikipedia.org/wiki/Central_processing_unit

Processors are mostly waiting for data to be fetched to be processed.  There is no such thing as 100% efficient code.

If software needs to read a file from a spinning hard drive has a mandatory latency period (https://en.wikipedia.org/wiki/Hard_disk_drive_performance_characteristics ) where the hard drives read needle moves in or out and reads the data form the right sectors and returns the data.  A 3.5 Ghz computer has to wait for an approximate 19,460,000 clock cycles for a sector on a hard drive to be under the read head. The data still has to be moved from the hard drive through the processor and into memory.  Luckily processors have fantastic calculation branch prediction abilities ( https://en.wikipedia.org/wiki/Branch_predictor) and even though the software has asked for a file to be read the processor can work on 19 million other cycles before checking to see if the data has returned from the hard drive.

Caching content

One solution is to have software or servers cache certain files in memory to speed up the delivery of files. The latest DDR4 computer memory runs as blistering speeds of 2,400Mhz (2,400,000,000 cycles a second) so it should keep up with a 2.4Ghz computer? Memory is cheap and fast but computer memory has a huge limitation.  You can’t just ask memory to return the value of a memory cell and expect it in a few cycles. The processor has to essentially guide the memory module to activate the required electrical columns and rows to allow that that value to be read and return it to a processor. This is like a giving instruction to a driver over a phone, it takes time for the driver to listen, turn a corner, drive down a street and then turn another corner just to get to the destination.  The processor has to manage millions of memory read and writes a second. Memory can’t direct itself to the memory value, the processor has to do that.

Memory timings are called RAM timings and it is explained better here ( http://www.hardwaresecrets.com/understanding-ram-timings/ ).  It takes modern DDR4 memory module about 15 clock cycles to just enable the column circuit for a memory cell to be activated, then another 15 clock cycles to activate the row and a whole load of other cycles to read the data. Reading a 1 MB file from memory may take 100,000,000 clock cycles (and that is not factoring in the processor is working on other tasks. A computer process is a name given to software code that has been handed over to the processor, software code is loaded into the processor/memory as instructions and depending on the code and user interactions different parts of the software’s instructions are loaded into the processor. In any given second a computer program may enter and leave a processor over 1,000 times and processors internal memory is quite small.

Benchmarking

Choosing a good host to place your website/mobile app or API’s is very important, sometimes the biggest provider is not the fastest. You should benchmark how long actions take on your site and what the theoretical maximum limit is. Do you need more memory or cores? Hosts will always sell you more resources for money.

http://www.webpagetest.org/ is a great site to benchmark how long your website takes to deliver each part of your website to customers around the world.  You can minify (shrink) your code and images to reduce the processing time per page load.

If you are keen research PHP caching plugins like OpCache ( http://php.net/manual/en/book.opcache.php ), MemcahedD (https://www.digitalocean.com/community/tutorials/how-to-install-and-use-memcache-on-ubuntu-14-04) for PHP or MySQL  or WordPress WP-Total-Cache (https://wordpress.org/plugins/w3-total-cache/ ) plugin.

Placing your website or application databases close to your customers.  In Australia, it takes 1/5 of a second minimum for a server outside of Australia to respond.  A website that loads 30 resources would also add the delays between your server and customers (30×1/5 of a second add’s up).

Consider merging and minifying website resources ( http://www.minifyweb.com/ ) to lower the number of files and file sizes that you deliver to users. Most importantly monitor your website 24/7 to see if it is slowing down. I use http://monitis.com to monitor server performance remotely.

Summary

I hope I have not confused you too much. Try some videos below to learn more.

Good Videos: 

How a CPU Works:

How Processors are Made:

How a Hard Drive works in Slow Motion – The Slow Mo Guys

What’s Inside a CPU?

Zoom Into a Microchip (Narrated)

How computers work in less than 20 minutes

Read some of my other development-related guides here https://fearby.com/
Donate and make this blog better




Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]

Filed Under: Cloud, Development, Domain, Hosting, MySQL, Security, VM, Wordpress Tagged With: code, hard drive, memory, optimize, processor, solid state

The quickest way to setup a scalable development ide and web server

June 8, 2015 by Simon Fearby

fyi: Consider reading this first (newer blog post):  How to buy a new domain and SSL cert from NameCheap, a Server from Digital Ocean and configure it.

Buying a Domain

Buy a domain name from Namecheap here.

Domain names for just 88 cents!

Why do I need a free Development IDE/VM

  • You already have heaps of sub domains/sites/blogs on one CPanel domain and you don’t want to slow down your server anymore.
  • You need a new collaboration web server setup in minutes.
  • You want a server where you have full control to install the latest widgets (NGNIX, NodeJS etc).
  • You want a single interface where you can deploy, develop and test online.
  • You want to save money
  • You want to access and edit your sites from anywhere.

The Solution

Cloud9 ( http://www.c9.io ) combines a powerful online code editor with a full Ubuntu server in the cloud. Simply pick your configuration, develop an app, invite others in to preview and help code.

Update 2018: For the best performing VM host (UpCloud) read my guide on the awesome UpCloud VM hosts (get $25 free credit by signing up here).

Now there is no need to spend valuable development time on setting up hardware/software platform. You can create, build and run almost any development stack in minutes. Cloud9 maintain the server and you have full control it.

Signing up for a C9 account.

Cloud 9 offer a number of hosting plans (one free) with a range of hardware resources for when you want to scale up.  The free tier is great if you want to keep your development environment closed.  Use this link and get $19 free credit https://c9.io/c/DLtakOtNcba

c92016

Before you connect to your digital ocean VM connect to the server via the console in the digital ocdan admin pane (you may need to reset your root password) and then install NodeJS (Required by c9.io IDE).

Installing NodeJS

  • curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash –
  • sudo apt-get install -y nodejs
  • node -v

Now you will have node v6.3.0

Create a development Workspace.

Once you create a Cloud 9 account you can create a VM workspace. You can choose some common software packages to installed by default.  Don’t worry you can install anything you want later from the command line in the VM.

c92016b

How simple is that, a new development environment in minutes.

Development Workspace

You can edit new code, play with WordPress or NodeJS all from the one Cloud9 IDE. The Cloud 9 IDE allows you to open a “bash terminal” tab, folder list, web browser, code window and debug tools (all from the web).

Code on the left, WordPress on the right, terminal on the bottom 🙂

Edit and View Code Workspace
Edit and View Code Workspace

C9 IDE

You can Install what you want

Because you have access to the Linux bash terminal you can for example type the following to install an NGNIX web server.

  1. sudo apt-get update
  2. sudo apt-get install nginx
  3. sudo service nginx start

Full Bash Terminal

Full Bash Terminal

As usual installing stuff in Linux requires loads of googling and editing config files so beware.

What are the downsides of a c9.io Ubuntu server?

Your development environment (public of private) is mostly off limits to the outside world unless you invite people in who have a Cloud 9 account.  This is great if you want to develop a customers website off the grid and keep is secure or share the development with other developers.  Cloud 9 don’t really have a “goto production plan” so you will need to find a host to deploy to when you are ready.

Luckily this is where http://www.digitalocean.com comes in, Digital Ocean allow you to create a real/public VM (just like Cloud 9) and best of all you can connect it to the Cloud 9 IDE..

The only downside is you will need to move on from the free Cloud 9 account and pay $9 a month to allow you to connect securely (via SSH) to your new (Real) Digital Ocean VM.  On the up side the $19 month plan gives you twice the ram (1GB) and 10x the storage (10GB) and you can have 2 premium (private accounts).

Signing up for a Digital OceanAccount

The cheapest Digital Ocean Hosting plan is $5 a month. If you want $10 free credit at Digital Ocean (two months free) please use this link: https://www.digitalocean.com/?refcode=99a5082b6de5

Tip:

Granting SSH Access (before you create a server (droplet))

Tip: Add your Cloud 9 SSH key to your account before creating a droplet (VM). I added my SSH key when the VM/Droplet was create and I could not connect to it from Cloud 9. I then deleted the droplet, added the SSH key to my Digital Ocean account here then created the Droplet (VM) and all was ok.  You can find your SSH key on the front page of your cloud 9 desktop.

do2016b

This is the magic option, if you skip this you will be emailed a password to your VM and you will be on your own connecting to it with a secure terminal window. If you add your Cloud 9 SSH key ( found in your Cloud 9 IDE https://cloud.digitalocean.com/settings/security ) you can connect to and control your new Digital Ocean VM from the Cloud 9 UI.

Now you can create a server (droplet)

do2016

A digital ocean server can be setup in minutes. If you only use it for 2 weeks you will only be charged for 2 weeks. If you use my link your first 2 months are free (if you select a $5 server).

Your server should be created in well under 5 minutes. Write down your VM’s IP.

Digital Ocean Droplet (VM) Created
Digital Ocean Droplet (VM) Created

Connecting your C9 account to Digital Ocean Droplet

Now go back to Cloud 9 and login. Go here ( https://c9.io/account/ssh ) and add your SSH key from Digital Ocean.

Cloud 9 guide on setting up SSH on your server: https://docs.c9.io/docs/running-your-own-ssh-workspace

Advertisement:



fyi: Here is a more recent post of how to connect Cloud 9 with AWS.

Create a new workspace with these settings (but use your IP from digital ocean) to connect to your new Digital Ocean VM.

c92016c

Now you can develop like a pro. Cloud 9 will allow you to login to your development environment from anywhere and resume where you left off.

Traps and Tips

  • Consider buying this course: https://www.udemy.com/all-about-nodejs/?dtcode=9TQkocT33Eck 
  • Get your VM/Droplets right (if they don’t work as expected delete them and start again).
  • Know how to safely shutdown a Linux VM.
  • Google.
  • If you receive the error “Could not execute node.js on [email protected] bash: /usr/bin/nodejs:” in C9 when connecting to the server try installing node via the digital oceans manual console window.

Connecting your new Cloud IP to a CPanel sub domain

If you have CPanel domain elsewhere you can link your new Digital Ocean Cloud VM IP to a new sub domain.

  1. Login to your CPanel domain UI.
  2. Click Simple DNS Zone Editor
  3. Type the sub domain name (swap my domain.com to your domain).
  4. Enter the IP for your Digital Ocean domain (you get this from the Digital Ocean account page).
  5. Click Add a record.

    DNS Zone
    DNS Zone
  6. Now when someone types http://newcloud.mydomain.com they get redirected to your new cloud domain but the URL stays the same (how professional is that).
  7. You can add multiple A name records pointing to the same IP.

Summary

$19 a month gives me a kick arse www.c9.io development environment and a few VMs.

$5 a month gives me my own real VM that I can scale up.

Coupon

You can easily deploy an SSD cloud server in 55 seconds for $5 a month. Sign up using my link and receive $10 in credit: https://www.digitalocean.com/?refcode=99a5082b6de5

Security

After a few weeks, do check your website with https://www.shodan.io and see if it has open software or is known to hackers.

Donate and make this blog better




Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]
V1.6 security

Filed Under: Cloud, Development, Domain, Hosting, Linux, Scalable, Security, VM Tagged With: cloud, cloud 9, code, development, digital ocean, ide, vm

Primary Sidebar

Poll

What would you like to see more posts about?
Results

Support this Blog

Create your own server today (support me by using these links

Create your own server on UpCloud here ($25 free credit).

Create your own server on Vultr here.

Create your own server on Digital Ocean here ($10 free credit).

Remember you can install the Runcloud server management dashboard here if you need DevOps help.

Advertisement:

Tags

2FA (9) Advice (17) Analytics (9) App (9) Apple (10) AWS (9) Backup (21) Business (8) CDN (8) Cloud (49) Cloudflare (8) Code (8) Development (26) Digital Ocean (13) DNS (11) Domain (27) Firewall (12) Git (7) Hosting (18) IoT (9) LetsEncrypt (7) Linux (21) Marketing (11) MySQL (24) NGINX (11) NodeJS (11) OS (10) Performance (6) PHP (13) Scalability (12) Scalable (14) Security (45) SEO (7) Server (26) Software (7) SSH (7) ssl (17) Tech Advice (9) Ubuntu (39) Uncategorized (23) UpCloud (12) VM (45) Vultr (24) Website (14) Wordpress (25)

Disclaimer

Terms And Conditions Of Use All content provided on this "www.fearby.com" blog is for informational purposes only. Views are his own and not his employers. The owner of this blog makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site. Never make changes to a live site without backing it up first.

Advertisement:

Footer

Popular

  • Backing up your computer automatically with BackBlaze software (no data limit)
  • How to back up an iPhone (including photos and videos) multiple ways
  • Add two factor auth login protection to WordPress with YubiCo hardware YubiKeys and or 2FA Authenticator App
  • Setup two factor authenticator protection at login on Ubuntu or Debian
  • Using the Yubico YubiKey NEO hardware-based two-factor authentication device to improve authentication and logins to OSX and software
  • I moved my domain to UpCloud (on the other side of the world) from Vultr (Sydney) and could not be happier with the performance.
  • Monitor server performance with NixStats and receive alerts by SMS, Push, Email, Telegram etc
  • Speeding up WordPress with the ewww.io ExactDN CDN and Image Compression Plugin
  • Add Google AdWords to your WordPress blog

Security

  • Check the compatibility of your WordPress theme and plugin code with PHP Compatibility Checker
  • Add two factor auth login protection to WordPress with YubiCo hardware YubiKeys and or 2FA Authenticator App
  • Setup two factor authenticator protection at login on Ubuntu or Debian
  • Using the Yubico YubiKey NEO hardware-based two-factor authentication device to improve authentication and logins to OSX and software
  • Setting up DNSSEC on a Namecheap domain hosted on UpCloud using CloudFlare
  • Set up Feature-Policy, Referrer-Policy and Content Security Policy headers in Nginx
  • Securing Google G Suite email by setting up SPF, DKIM and DMARC with Cloudflare
  • Enabling TLS 1.3 SSL on a NGINX Website (Ubuntu 16.04 server) that is using Cloudflare
  • Using the Qualys FreeScan Scanner to test your website for online vulnerabilities
  • Beyond SSL with Content Security Policy, Public Key Pinning etc
  • Upgraded to Wordfence Premium to get real-time login defence, malware scanner and two-factor authentication for WordPress logins
  • Run an Ubuntu VM system audit with Lynis
  • Securing Ubuntu in the cloud
  • No matter what server-provider you are using I strongly recommend you have a hot spare ready on a different provider

Code

  • How to code PHP on your localhost and deploy to the cloud via SFTP with PHPStorm by Jet Brains
  • Useful Java FX Code I use in a project using IntelliJ IDEA and jdk1.8.0_161.jdk
  • No matter what server-provider you are using I strongly recommend you have a hot spare ready on a different provider
  • How to setup PHP FPM on demand child workers in PHP 7.x to increase website traffic
  • Installing Android Studio 3 and creating your first Kotlin Android App
  • PHP 7 code to send object oriented sanitised input data via bound parameters to a MYSQL database
  • How to use Sublime Text editor locally to edit code files on a remote server via SSH
  • Creating your first Java FX app and using the Gluon Scene Builder in the IntelliJ IDEA IDE
  • Deploying nodejs apps in the background and monitoring them with PM2 from keymetrics.io

Tech

  • Backing up your computer automatically with BackBlaze software (no data limit)
  • How to back up an iPhone (including photos and videos) multiple ways
  • US v Huawei: The battle for 5G
  • Check the compatibility of your WordPress theme and plugin code with PHP Compatibility Checker
  • Is OSX Mojave on a 2014 MacBook Pro slower or faster than High Sierra
  • Telstra promised Fibre to the house (FTTP) when I had FTTN and this is what happened..
  • The case of the overheating Mac Book Pro and Occam’s Razor
  • Useful Linux Terminal Commands
  • Useful OSX Terminal Commands
  • Useful Linux Terminal Commands
  • What is the difference between 2D, 3D, 360 Video, AR, AR2D, AR3D, MR, VR and HR?
  • Application scalability on a budget (my journey)
  • Monitor server performance with NixStats and receive alerts by SMS, Push, Email, Telegram etc
  • Why I will never buy a new Apple Laptop until they fix the hardware cooling issues.

Wordpress

  • Replacing Google Analytics with Piwik/Matomo for a locally hosted privacy focused open source analytics solution
  • Setting web push notifications in WordPress with OneSignal
  • Telstra promised Fibre to the house (FTTP) when I had FTTN and this is what happened..
  • Check the compatibility of your WordPress theme and plugin code with PHP Compatibility Checker
  • Add two factor auth login protection to WordPress with YubiCo hardware YubiKeys and or 2FA Authenticator App
  • Monitor server performance with NixStats and receive alerts by SMS, Push, Email, Telegram etc
  • Upgraded to Wordfence Premium to get real-time login defence, malware scanner and two-factor authentication for WordPress logins
  • Wordfence Security Plugin for WordPress
  • Speeding up WordPress with the ewww.io ExactDN CDN and Image Compression Plugin
  • Installing and managing WordPress with WP-CLI from the command line on Ubuntu
  • Moving WordPress to a new self managed server away from CPanel
  • Moving WordPress to a new self managed server away from CPanel

General

  • Backing up your computer automatically with BackBlaze software (no data limit)
  • How to back up an iPhone (including photos and videos) multiple ways
  • US v Huawei: The battle for 5G
  • Using the WinSCP Client on Windows to transfer files to and from a Linux server over SFTP
  • Connecting to a server via SSH with Putty
  • Setting web push notifications in WordPress with OneSignal
  • Infographic: So you have an idea for an app
  • Restoring lost files on a Windows FAT, FAT32, NTFS or Linux EXT, Linux XFS volume with iRecover from diydatarecovery.nl
  • Building faster web apps with google tools and exceed user expectations
  • Why I will never buy a new Apple Laptop until they fix the hardware cooling issues.
  • Telstra promised Fibre to the house (FTTP) when I had FTTN and this is what happened..

Copyright © 2023 · News Pro on Genesis Framework · WordPress · Log in

Some ads on this site use cookies. You can opt-out if of local analytics tracking by scrolling to the bottom of the front page or any article and clicking "You are not opted out. Click here to opt out.". Accept Reject Read More
GDPR, Privacy & Cookies Policy

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Necessary
Always Enabled
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Non-necessary
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.
SAVE & ACCEPT