Category Archives: Code

Coding Amazon Echo Skills for Alexa with C#

Amazon Echo

Amazon Echo

I was reading this months CODE Magazine and there is an article about coding new Skills for Amazon Echo and Echo Dot to extend Alexa’s functionality. When you think about how you could extend Alexa to fit into your life, it could be well worth adding C# into your life. Amazon Echo is currently on offer for Mothers Day, with a £15 discount, maybe the time to get one. 

Lets say you want to check if a domain is registered, you could say “Alexa ask NominetTool if steven.uk is registered ?” or Alexa ask NominetTool who steven.uk is Registered to ?”. I guess depending on how accurate Alexa turns out to be, you could even try “Alexa ask NominetTool to Register steven.co.uk”.

I don’t have an Echo or Echo Dot, nor do I code in C# but this article does make it seem like a fun reason to learn. Its been maybe 10 yrs or more since I last opened VC++, and probably longer than that since I last wrote any reasonable amount of code. Looking at C# it doesn’t look that difficult once the new syntax makes sense. If I can pick up a cheap Echo or Echo Dot, I may just delve in to this. 

Looking at the code sample they provided…

HowTo.prototype.intentHandlers = {
   "RecipeIntent": function (intent, session, response) {
      var itemSlot = intent.slots.Item, itemName;
      
      if (itemSlot && itemSlot.value) {
         itemName = itemSlot.value.toLowerCase();
      }
      
      var cardTitle = "Recipe for " + itemName,
         recipe = recipes[itemName],
         speechOutput,
         repromptOutput;
      
      if (recipe) {
         speechOutput = {
            speech: recipe,
            type: AlexaSkill.speechOutputType.PLAIN_TEXT
         };
      
         response.tellWithCard(speechOutput, cardTitle, recipe);
      } else {
         var speech;
      
         if (itemName) {
            speech = "I'm sorry, I currently do not know the
                       recipe for " + itemName + ". What else can I help
                       with?";
         } else {
            speech = "I'm sorry, I currently do not know that
                       recipe. What else can I help with?";
         }
      
         speechOutput = {
            speech: speech,
            type: AlexaSkill.speechOutputType.PLAIN_TEXT
         };
      
         repromptOutput = {
            speech: "What else can I help with?",
            type: AlexaSkill.speechOutputType.PLAIN_TEXT
         };
      
         response.ask(speechOutput, repromptOutput);
      }
   },
      
   "AMAZON.StopIntent": function (intent, session, response) {
      var speechOutput = "Goodbye";
      response.tell(speechOutput);
   },
      
   "AMAZON.CancelIntent": function (intent, session, response) {
      var speechOutput = "Goodbye";
      response.tell(speechOutput);
   },
      
   "AMAZON.HelpIntent": function (intent, session, response) {
      var speechText = "You can ask questions such as, what's the
                 recipe, or, you can say exit... Now, what can I help you
                 with?";
      
      var repromptText = "You can say things like, what's the
                 recipe, or you can say exit... Now, what can I help you
                 with?";
      
      var speechOutput = {
         speech: speechText,
         type: AlexaSkill.speechOutputType.PLAIN_TEXT
      };
      
      var repromptOutput = {
         speech: repromptText,
         type: AlexaSkill.speechOutputType.PLAIN_TEXT
      };
      
      response.ask(speechOutput, repromptOutput);
   }
};

It looks quite simple to program, I guess you would use a PHP or C# web interface to execute the Recipes section, or in the example I gave to handle the domain name queries. Port the Whois Family Parser over to C# and you would be able to ask questions about whois result. 

Exciting times ahead. 

Updating the Drop List Download Application

I received an email from someone who wanted to download the output of an MySQL Query from a DropList Database, but it were to use on a windows client. The code snippet series I posted used /n instead of the /r/n, and would require the use of unix2dos, even a simple str_replace, but while looking for a solution on another project I came across Stream Filters, which can be applied in this instance quite elegantly.

I would have gone around the issue by processing the query output before producing the download. However this email weren’t asking for that, so I thought of a different solution, of which I came up with 2 or 3 different ways. I always think of Larry Wall the creator of PERL who once said “Theres always more than one way to do it”, which is nigh on a PERL Mantra but in PHP there are usually half dozen different ways to do it, then a dozen more overkill ways on top. 

I hadn’t really used Stream Filters that much, and only then for handling affiliate feeds which are CSV files. This function’s code is by a chap called Torge, and can be found on this StackOverflow post Fputcvs and New Lines. Bending and fusing the function to this purpose is actually quite elegant… and I like it.  

<?php 
include('../con.sql.php'); 
$today = date("Y-m-d");

class StreamFilterNewlines extends php_user_filter {
    function filter($in, $out, &$consumed, $closing) {
        while ( $bucket = stream_bucket_make_writeable($in) ) {
            $bucket->data = preg_replace('/([^\r])\n/', "$1\r\n", $bucket->data);
            $consumed += $bucket->datalen;
            stream_bucket_append($out, $bucket);
        }
        return PSFS_PASS_ON;
    }
}

$query = "SELECT domain FROM `zonefile` WHERE `dropdate` = '$today';";
$result = mysql_query($query); 
$fp = fopen('php://output', 'w'); 
if ($fp && $result) {     
       stream_filter_register("newlines", "StreamFilterNewlines"); 
       stream_filter_append($fp, "newlines");        
       header('Content-Type: text/csv');
       header('Content-Disposition: attachment; filename="'.$today.'.txt"');
       header('Pragma: no-cache');    
       header('Expires: 0');

       while ($row = mysql_fetch_row($result)) {
          fputcsv($fp, array_values($row)); 
       }
die; 
}
?>

The above fusion of Torge’s code and my code creates a windows encoded text file based on the MySQL query output and starts/prompts a download of said file. It could be neatened up, and for public deployment certain needs some bomb proofing. 

How you modify the date / change the query is down to you. I would perhaps use a form with a submit via post with some sanitising, but this works for a simple download todays list script.

Extending The Drop List Application

You could even modify the download aspect and have it write to a file or email the download to you or a client.

In a similar tool, I have something like this which runs on a cron at midnight to create a downloadable file, which also becomes a historic record for the days list. This way multiple people can download the list without the server having to process the MySQL and increase the server load every time.

Before I used a Cron like above, the first user of the day ran the query and subsequent users downloaded the output. The problem were the first user could end up loading it during a critical time or it would take too long. 

I used a simple if…FileName…Exist…PromptDownload…else…RunQuery type switch, ultimately the CRON method is faster and better to maintain, the code above can be modified this way.

WordPress Plugin Errors and Clearing All Plugins

Slimstat WordPress Plugin Error

Slimstat WordPress Plugin Error

A recently plugin which were auto-updated by WordPress didn’t execute properly. I have no idea why or what happened, the logs didn’t show anything special.

This error meant that: 1, My website were down with an error and 2, Even worse that my uptime checker script, failed to notice this. As it happened I were due to update some files and found the site were down, it had been down for anywhere between 3 and 4 hours.

Fixing The Problem

The problem is quite easy to fix, you need to disable the particular plugin or all plugins directly from your database. This is useful not only when WordPress plugin updates go wrong, but times when WordPress is loading blank pages or you’re unable to access the admin pages after a new version of WordPress is installed.

You can easily disable all WordPress plugins directly from your database. This is useful when you have some problems with your WordPress installation such as not being able to log in to the admin area and/or having blank pages.

You need to login to your WebHosting control panel, which is probably cPanel.

From here you need to select phpMyAdmin, which will probably redirect you. From here select the appropriate WordPress Database from the list on the left hand side.

Scroll down the list of tables until you find the one called “wp_options”. I suggest you click on the column names (option_name ^)and set them to Alphabetic. Look for “active_plugins” which should be on the first page..

MySQL Active Plugins

MySQL Active Plugins

In a clean install this will likely have 2 plugins enabled on this list, which are Akismet and Hello Dolly. This means the “wp_options”.”active_plugins” column will look like:

a:2:{i:0;s:19:”akismet/akismet.php”;i:1;s:9:”hello.php”;}

Option 1: Disable ALL Plugins

Simple click the little pencil icon or “Edit” (see above pic), or double click the line underneath “option_value” and delete all the text, and click save/done, so its now empty.

You should now be able to load wordpress without any problems.

Option 2: Selectively Disable Plugins

If you know which plugin is at fault, you can delete that 1 plugin. If you wanted to disable “hello dolly”, you would change it to:

a:2:{i:0;s:19:”akismet/akismet.php”;}

Each item looks like

i:0;s:19:”akismet/akismet.php”;

i:1;s:9:”hello.php”;

This means deleting everything between i: and which is the line for each plugin, ensure you delete the whole section. If you don’t correctly edit it, WordPress to clear the list and disable all plugins anyway.

You should now be able to login again to WordPress.

Option 3: MySQL Query

There is an easier option, and that’s to run a MySQL query like this…

UPDATE wp_options SET option_value = '' WHERE option_name = 'active_plugins';

Once the above is completed, you should be able to login to WordPress.

Reactivate WordPress Plugins

Now you can login back in to WordPress, you will need to reactivate all your chosen plugins. I would recommend doing this 1 by 1 so you verify each one is functioning correctly. You should also take this opportunity to delete any unused plugins and update any out of date plugins.

In my case, it were simply updating the plugin, and re-activating it and all done.

Extracting a Zip file with PHP

I recently had to make a quick script to extract the contents of a zip file, this zip file is copied via ftp from a remote server and stored locally. The file name to request and transfer is set via URL Encoding. This were originally a function, which I converted into a class and now devolved totally for this small script.

Sometimes quick and dirty tasks, require quick and dirty code, using the class would have been overkill. As usual there are a dozen ways to do this, and you could remove the error checks and echo’s to make the code even more compact.

// get the absolute path to $file ($file is set via the transfer process, but is JUST the file name no extension).
$path = pathinfo(realpath($file.'.zip'), PATHINFO_DIRNAME);
$link = $path.'/'.$file.'.zip';
$linkz = $path.'/'.$file.'.csv';
// assuming file.zip is in the same directory as the executing script.
	if (file_exists($linkz)) {
		die("<p>The .csv file exists, exit processs.</p>");
	} 
	if(file_exists($link)){
		echo "<p>The $link exists, and $linkz file doesn't exist.</p>";		
		//prepare for handling a zip file.
		$zip = new ZipArchive; 
		// load the zip file.
		$res = $zip->open($file.'.zip');
		if ($res === TRUE) { // check the file has been loaded.
			echo "<p>Extracting File...</p>";
			$zip->extractTo($path); //begin extracting file
			$zip->close(); //unloa and release the zip file.
			echo "<p>$file.zip extracted to $path</p>";
		} else {
			echo "<p>Doh!, stupid $file.zip wouldn't open.</p>";
		}
	}else{

		die("<p>$file.zip doesn't exist, exit process.</p>");

	}

Its a little messy, but were procedural code, converted into a function, then part of a class and back to a procedural layout.

.UK Family Whois Splitter

I were looking for a snippet of code for someone when I came across an old tool. This isn’t a parser or a tool like phois or similar, its just a usable snippet of code to do a job. Really I should update it, and maybe use a function to handle the job, but it works just fine for its use.

The job in this instance were to monitor my domains for changes in status, in a few situations.

1, When a domain were sold, I monitored the tag and registrant name (now I’m using the DAC I only monitor the tag for .uk).
2, When using another registrar/registry I monitored expiry to avoid losing domains due to non-renewal or errors.

In order to do this, I needed code to (1), connect to a whois server (this is easy),  (2), split the required bits of info from the result (not so easy) and (3), place it in a database (easy). Then work on the data from there, (4), load the “watched”, “sold” or “close to expiry” domains, (5), scan the whois and compare, then (6), act on the result.

90% of the various registries whois outputs, out there are fairly uniform, but much like Nominets EPP, their whois is non-standard, so I needed a custom splitter. I’m not sure I would do it the same if I wrote the code now… some years later.

I have updated the code a little to include a ROFR (Right of First Refusal) detection, this won’t be needed come june (2019) when the period expires.

switch(trim($ext)){
	case "uk":
		$def = array();
		if(preg_grep("/Right of reg/", $arr)){
			$def['domain'] = $arr[1];
			$def["rofr"] = $arr[3]; 
			$type = "rofr";			
			break;	
		}

		$def['domain'] = $arr[1];
		$def['registrant'] = $arr[3]; 

		preg_match('/Tag = (.*)]/', $res, $matches);
		$def['tag'] = trim($matches[1]);
			
		preg_match("/Registered on: (.*)/", $res, $matches);
		$def['created'] = date("Y-m-d",strtotime(trim($matches[1])));
			
		preg_match("/Last updated: (.*)/", $res, $matches);
		$def['updated'] = date("Y-m-d",strtotime(trim($matches[1])));
				
		preg_match("/Expiry date: (.*)/", $res, $matches);
		$def['expiry'] = date("Y-m-d",strtotime(trim($matches[1])));

		$type = "uk";	
		break;

	default:
		break;
}

This will produce an array called $def, which when calling a valid name would look like…

Array
(
    [domain] => steven.uk
    [registrant] => Steve Morley
    [tag] => MORLEY
    [created] => 2014-06-12
    [updated] => 2016-02-29
    [expiry] => 2024-06-12
)

or if the the .UK has right of first registration intact…

Array
(
    [domain] => steven.uk
    [rofr] => steven.co.uk
)

Working from this array, you can you can put these into a database, compare them to the database return and act on it from there. I suggest sending yourself an email or text message (api’s are easy to follow).

Synology Root Access Denied or Wrong Password

I’m a huge fan of Synology NAS units, not so much of the camera licenses but thats a minor niggle and for another time. I recently found my root password appeared to have been change but I didn’t remember changing it. I rarely login to the root account so it could have been altered a while ago.

RED ALERT!

Synology Root Password Change

Synology Root Password Change

Instantly I assumed I had been compromised, so I logged in as Admin via SSH using PuTTy and changed the root password. Next logged in to DSM (The Synology OS) as Admin user, checked the firewall, and went to Auto Block finding a few IP addresses on the list, but the last one dated back months. Entirely possible it had been that long since I logged in last as root. I checked for other “users” and various other security checks and all seemed ok.

Once the Red Alert has subsided and back to Amber Alert I started to look around on the net and found many comments to the effect “my root password has changed” and “my root account is blocked” and with some further digging found references to the last major DSM Update which were DSM 6.0.

DSM 6.0 Root Password Change

It seems something DSM 6.0 did, caused a reasonable amount of Synology owners root passwords to either change, become corrupt or expire. The solution were to simply change the root password to a new one or back to the old one (I would NEVER recommend the latter). I had inadvertently already done this with my first reaction, so had already fixed it on that particular server.

It dawned on that lots of users wouldn’t find this nugget of information or know how to do this since the reason you buy Synology is so you don’t have to get knee deep in linux but have all the power, so figured I’d blog it.

Exactly what you type into the prompt is in bold, and hit enter after each command.

  1. Using PuTTy enter your Servers IP (probably 192.168.0.2 or enter your servers hostname).
  2. Enter username as admin.
    (if you have changed your admin users name, change it here)
  3. Enter your admin password (same as used to access DSM).
  4. Enter the command sudo su.
    (this upgrades you to SuperUser)
  5. Enter admin password again when prompted.
  6. Enter the command synouser –setpw root ‘newpassword’.
    (use the single quotes around password)
  7. Enter exit, this returns you to normal user.
  8. Enter exit, this closes PuTTy.

You can now login as root user once again. I highly recommend using 2 different passwords for Admin and Root users.

Auto Block

Synology has a feature called “Auto Block” which automatically blocks IP addresses when they get the password wrong a number of times. You can find this under the Security Tab in the DSM. You may find your local network IP (192.168.0.*) or wherever you tried to access root from has been blocked, so its as well to check here and remove your IP remembering to save your changes.

Otherwise you find your connection by PuTTy being refused or randomly disconnected as happened on one of my units.