Friday, November 7, 2014

Copy to FTP in Classic ASP (JScript)

Recently I had the need to FTP some files in the old Classic ASP platform. The catch is that I need it to be in JScript (Javascript for IIS). In my experience most people use VB script in their ASP environment,. the past few years I have grown to prefer using JScript. If you'd like to use VBScript to FTP then might I suggest this great source. It is from this that I have adapted my JS version.

FTP in ASP (JScript)

In my current environment I never use serverside JScript to render HTML, rather only to serve in a JSON based API format. For the purposes of sharing, I trimmed down the scaffolding into the bare necessities and was left only needing a JSON polyfill: JSON polyfill that works in ASP JScript.

var ftp = (function() { /* * Copy a file(s) to a directory on a remote FTP server. * * Adapted from the very usefull post @ http://benmeg.com/code/asp/ftp.asp.html */ function copyTo(address, username, password, remote_directory, files_to_put, isBinary) { var objFSO = Server.CreateObject("Scripting.FileSystemObject"), oScript = Server.CreateObject("WSCRIPT.SHELL"), oFileSys = Server.CreateObject("Scripting.FileSystemObject"), objTextFile, oScriptNet, oFile, strCMD, strTempFile, strCommandResult = '', uniqueNumber = '__'; // This is for you to implement a random key on your system (if required). // Build our ftp-commands file objTextFile = objFSO.CreateTextFile(Server.MapPath('ftpCommand' + uniqueNumber + '.ftp')); objTextFile.WriteLine('lcd ' + Server.MapPath('.')); objTextFile.WriteLine('open ' + address); objTextFile.WriteLine(username); objTextFile.WriteLine(password); // Check to see if we need to issue a 'cd' command if (remote_directory != '') objTextFile.WriteLine('cd ' + remote_directory); objTextFile.WriteLine('prompt'); // If the file(s) is/are binary (i.e. .jpg, .mdb, etc..) if (isBinary) objTextFile.WriteLine('binary'); // If there are multiple files to put, we need to use the command 'mput', instead of 'put' if (files_to_put.indexOf('*') > -1) objTextFile.WriteLine('mput ' + files_to_put); else objTextFile.WriteLine('put ' + files_to_put); objTextFile.WriteLine('bye'); objTextFile.Close(); delete objTextFile; // Pipe output from cmd.exe to a temporary file strTempFile = Server.MapPath('ftpOutput-' + uniqueNumber + '.ftp'); // Use cmd.exe to run ftp.exe, parsing our newly created command file oScript.Run('cmd.exe /c ' + 'ftp.exe -s:' + Server.MapPath('ftpCommand' + uniqueNumber + '.ftp') + ' > ' + strTempFile, 0, true); oFile = oFileSys.OpenTextFile(strTempFile, 1, false, 0); // Grab output from temporary file strCommandResult = oFile.ReadAll(); oFile.Close(); // Delete the temporary & ftp-command files oFileSys.DeleteFile(strTempFile, true); objFSO.DeleteFile(Server.MapPath('ftpCommand' + uniqueNumber + '.ftp'), true); delete oFileSys; delete objFSO; return { result: strCommandResult.split('\r\n') }; } return { copyTo: copyTo }; })();

Which results in:

Friday, July 18, 2014

Chinese Javascript Tools - 中文Javascript的工具

A set of tools and functions for working with Chinese characters in the browser or NodeJS.

Features

  • Generating Pinyin or Zhuyin (Bopomofo) for strings of Chinese text - 翻譯中文到拼音或注音
  • Converting between Traditional and Simplified Chinese - 兌換傳統到簡體漢字而且反之亦然
  • Detecting Chinese characters in strings - 檢測中文字
  • UI elements/facilities for reading Chinese text in the browser - 用拼音和注音便利使用者讀中文字
  • Translating Chinese characters and common phrases to English - 翻譯成語和常見的字

Download

All source and examples can be downloaded from GitHub.

Examples

Tuesday, May 27, 2014

Reading Excel Files in Classic ASP

Recently I had the need to source data from Excel files in the old Classic ASP platform. There are some good resources online which can help you with this, but I thought I'd log my little experience here which may hopefully expedite the process for someone else someday :)

In my experience most people use VB script in their ASP environment,. the past few years I have grown to prefer using JScript. I'll provide my testing in both.

A Little Environment Preface

In my examples I will have a file called unlocodes.xlsx placed in the directory c:\temp\
The content of the Excel file looks like this:

ASP (VB)

Here is a barebones ASP sample connecting to the Excel file.

This resulted in:

ASP (JScript)

Here is a JScript sample connecting to the Excel file. In my current environment I never use serverside JScript to render HTML, rather only to serve in a JSON based API format. I trimmed down the scaffolding into the bare necessities: an Excel interface and a JSON polyfill that works in ASP JScript.

This resulted in:

Some Extra Notes

I crossed paths with two errors, both of which were resolved by simply choosing the correct connection string.
This error:
ADODB.Connection error '800a0e7a'

Provider cannot be found. It may not be properly installed.

and this error:
Microsoft JET Database Engine error '80004005'

External table is not in the expected format.

The ConnectionStrings.com website is a great resource for finding a connection string compatible with your installed version of Excel. I found that on my machine with Excel 2010 this connection string worked:
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\somefile.xlsx;Extended Properties="Excel 12.0 Xml;HDR=YES;IMEX=1";

Whereas on our production server we have 2013 installed:
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\somefile.xlsx;Extended Properties="Excel 8.0;HDR=YES;IMEX=1";

If you continue to have problems finding the correct driver, or it complaining it's not installed, then be sure to download and install the Microsoft Access Database Engine 2010 Redistributable. This includes the latest ACE drivers which come in 32 and 64 bit flavors. For posterity you may want to try install the 64bit version in command line using the follwoing syntax:
AccessDatabaseEngine_X64.exe /passive

Wednesday, May 7, 2014

Injecting CSS with Javascript

Why injectCSS? Why make it? What is it solving?

  • The primary goal was to create an easy way to include multi-line (lots) of CSS using Javascript.
  • Can reduce number of files in a JS plugin or project (My goal was one).
  • A test run at jsperf.com shows that injecting CSS rules for a vast number of elements is very fast.
There are already some existing CSS injection tools, but I wanted something dead-simple. There is a great library called VeinJS, which does so much more than mine in many different ways. But after perusing through the examples I knew that I would have to dismantle my CSS too much. What I wanted was something like what you will see in the example below.

Example Usage

With RequireJS

With no dependencies

Compatability

Tested successfully on:

  • Chrome (+mobile)
  • Firefox
  • Safari (+mobile)
  • IE 10+
Due to the older IE browsers not allowing the innerHTML property to be set on certain elements, this will not work in them.

Download

The code is on GitHub. Download, use and modify as you please.

Tuesday, April 15, 2014

The Curiosity of _blank Anchor Tags

I'm often curious how so many websites still serve anchor <a> tags with targets set to "_blank".

I recently started browsing through www.104.com.tw, and was horrified to see how many times I was forced onto a new tab. A quick analysis showed me that 43% of the links on my profile editing page had a blank target set. ermahgerd.

This leads me to wonder if this is a conscious decision of the 104 developers. As a user I am consciously deciding my target on every single mouse click on an anchor/link. If I want it open in a new tab, then I middle-click (or ctrl-click),.. the ability to choose a new tab vs. current tab has long been given to me and the rest of the users of the world,.. why would some websites still decide to try force the user to use a new target?

I ran the following snippet of Javascript over a small sample of websites (some from Alexa top 10, some drawn from a hat).
Resulted in this log of results, which I've tried to summarize below.

The average use of _blank targets per country looked something like this for my sample:

Now I understand my sample is small (<50 pages); Edge cases may be skewing the statistic, but I it's fairly evident that some countries are definitely more accustomed to closing browser tabs than middle-clicking their mouse.

The top 13 results from my sample (excluding search result pages) looked like this:


Looking past the fact the top few sites have such a huge ratio of _blank targeted links, it's amazing that on the landing page of these Chinese sites the links number in the order of thousands.

It was also interesting comparing Bing's, Yahoo's and ebay's localized sites across the countries in question. It seems these sites have tailored their UX appropriately for their market.

Bing

Yahoo

ebay

If I had time to do this again properly, I would like to automatically crawl a more substantial sample of sites. The manual nature of my data-capture forced my sample to be focused and probably unfit for using in any real diagnosis.

Here's a good article to read. Agree or disagree with the use-cases, either way I hope more developers choose to use blank or new targets more appropriately.

Monday, March 31, 2014

Collect - A PHP/JQM Mobile Framework

For nearly as long as I can remember, I've been trying to simplify my programming projects by breaking down long repetitive tasks down into as short and concise steps as I can. I shudder to think of the hours in my life spent putting together a web page that reads a list of items from a database, filters or transforms them, then renders out the appropriate html and attachments. So many times have I done this, across many languages, projects, and technologies.

For the past two years I've been reforming my interest in web, to an interest in mobile web. During this time, I've also run through all my regular distractions like creating a little mobile RSS reader, a mobile client profile database for a cousin, a mobile plumbing inspection checklist for another friend. All these very different projects have a lot in common. They need to capture, edit, delete and list objects. Throw in a little menu navigation and there you have a system. My goal with this PHP/JQM MVC project is to turn my dev cycle for small projects into 90% deciding what I want, 10% typing it in.

Now since I'm targeting mobile devices, form layout can simply default to a vertical list of form controls down the page. All that's really left is deciding what data needs to be captured in my simple data capture app. Here's an example set of definitions...

The Client Profile Demo

There are three object models there: A client, a client state, and a product. Clients have several details, among which is a state. They can be in only one state at a time. Clients can have many products. That may or may not look like a lot,.. but what does it get you?

  • Six tables in your database, three data tables, each with a respective log table tracking all changes
  • An API on the serverside to manipulate that data
  • Clientside forms to edit instances of each of the models
  • Some simple regex error detection in the forms
  • Overview and list pages to navigate the data
  • A dashboard to hold it all together
  • The login procedure and managing users are also thrown in already
Here's some screen grabs of the app produced by the above definitions:

Download and Setup

You can freely download, copy, hack and sell this project from GitHub. To setup your own mobile app, the general process is as follows:

  • Copy this project folder into your htdocs or respective web directory
  • Edit the app/schema.json file to define your models and views
  • Delete any existing app/database.sqlite files (if you want to start from a clean slate)
  • Open api/check.php in a browser. This will create any tables that don't exist
  • Now open your mobile web app in a browser window

Some Caveats

As per usual, I offer this simply as a mostly working prototype. I was actively working on this project more than a year ago, but since then time and priority has led to the inevitable disregard of maintaining it. I still use it often when I need a little admin panel for a website or project I'm working on. I find it workable, but there are definitely bugs, and features half baked in. Have fun with it.

Tuesday, March 4, 2014

PHP Image Server

One of my latest projects requires an image server which had to fulfill these two API requirements:

  • Storing: Accept a URL as an image source then provide a token to address the cached/stored image.
  • Reading: Accept a token to provide an image in a specified resolution and/or format.
Some secondary features required:
  • The read API should provide a method to crop and resize images.
  • For the purposes of my project, I require the machine to...
    • accept JPEG, GIF, PNG, and SVG
    • only serve JPG's
This image store facility is only going to be used by an automated robot, so no pretty human interface is required.

Download

The code is on GitHub. Download and modify as you please.

Basic API format

  • Storing:
    /store/secret-key/base64_encoded_URL
  • Reading:
    /key/token/size

Storing an Image

Calling the API with parameters something like this:

http://localhost/imagemachine/store/123/aHR0cHM6Ly91cGxvYWQud2lraW1lZGlhLm9yZy93aWtpcGVkaWEvY29tbW9ucy9iL2IwL05ld1R1eC5zdmc=
Where store is the action, 123 is the secret key to store images, and the last parameter is the base64 encoded result of "https://upload.wikimedia.org/wikipedia/commons/b/b0/NewTux.svg"
Should result in JSON looking something like this:
{
 status: "ok",
 msg: "stored",
 guid: "de683d6b2e298de8e831b2f632132269"
}
The above means that the imageserver has decoded the URL, downloaded it, saved it in JPEG format (configurable), and returned a key for you to address that image in the future. The key is simply a hash of the URL passed in.

Reading an Image

Calling the API with parameters something like this (using the token from above):

http://localhost/imagemachine/~/de683d6b2e298de8e831b2f632132269
Will return an image in the default size and cropping.
The read key in this example is simply set to a tilde (~) as security for reading images out of this store is of no concern. To specify a size/cropping scheme, append one of the predefined sizes as another parameter:
http://localhost/imagemachine/~/de683d6b2e298de8e831b2f632132269/s
Where s has been setup as a "small" version of the image.

Demo Settings File

My Experience on a Hosted Solution

I use the GridService product offered by MediaTemple for my hosting. I followed this article to get the ImageMagick PECL working. But ended up discovering that the extension was quite limited compared to the native console convert. So I fell back to using PHP's exec.

Sunday, February 9, 2014

Blender and X3D Tattoo

So lately I've been putting a lot of thought into what I'll have chopped onto my arm next. The space I have parked for said tattoo is the back of my upper arm, an area I can't really see without aid of a mirror or contorting my head in directions I shouldn't be. So for the third or fourth time in my life now I jumped head first into Blender, with the primary goal of just being able to view my tattoos (and potentials) from another persons point of view.

It didn't take long for me to circle round back to web technologies, and found the fabulous x3dom project. They have a myriad of easy-to-follow tutorials and examples which show you how to export X3D from Blender, and then manipulate/interact with your model/scene in the browser.

I claim no special intimate knowledge of the technology, but I was quite pleased with the features I stumbled across. By simply including a few lines in my HTML, along with one JS and one CSS resource provided by x3dom, a scene is able to be built in the browser on canvas. Very little leg work required to get a basic explorable model onto a web page. The 3D scene is rendered to canvas, then also updated in a DOM structure, both staying in sync. So in order to manipulate your scene you can simply fiddle with the DOM objects (using JQuery or something similar if you wish) - and since X3D is an XML/tag based format, learning what to change and discovering properties is as simple as perusing through the source of your scene file.

Some short-comings may be browser support. x3dom has a comprehensive list of supported platforms and browsers. It seems that Chrome and Firefox are the safest bets, and thankfully the world has slowly moved away from the failures of the previous IE development teams. The other shortcoming that my little test suffers from is too-large-a-size that is preferable for the web. I guess I could have spent more time trying to simplify the model I found online and shrinking my images to more optimal sizes. If only time was not such a precious commodity.

Well enough jibber-jabber, here is the output of approximately 5 hours of fumbling through Blender, Photoshop, and some fiddling in the final HTML.

  • Left mouse drag to rotate
  • CTRL-left mouse to drag the object
  • Mouse scroll to zoom in and out

My final thought or idea that I will probably never end up doing, but seems really easy to achieve now in retrospect, is to create a webpage or mobile app that could grab an image, and paste it to a variety of locations on a model's body. Probably also allow someone to selfie and paste their mugshot on the model, a little bit of fine tuning controls, and upload to Facebook. Boom. Who wouldn't want to download that app?

Monday, February 3, 2014

Object Persistence in NodeJS

pst-obj is a rudimentary utility for setting up a persistence layer in your app for node. It extends an object with a single non-enumerable function that allows you to persist that object to a specified file location. When stored the object is serialized to JSON format and stored in a UTF-8 character encoded file.

Install

npm install pst-obj

Download

You can download it here or peruse the code on github: https://github.com/patcullen/pst-obj.

Why

Quite often now I'm finding myself creating little doodads in nodejs. My latest invention [read distraction] was a small app to control the light overhead in the room via a relay. It had some automatic triggers defined to flip once text had been detected in certain RSS streams, and of course a small one page one button interface to change the state of the light (mostly to play disco-tech in the office).

It's these low volume low risk types of applications I don't really want to setup a database or any third party services for. I had considered settings file type interfaces, but really much preferred the idea of JSON. (I also wanted half a good reason to publish to npm for a first time.) I've used pst-obj to persist single attribute objects, and some with fairly large (long and deep) data structures - the general rule is, if you know your data can be JSON'ed, then this should suffice as a usable, albeit rudimentary, persistence option.

Example

The above example when started and stopped a few times while also refreshing the page in a browser, should give a result similar to this:

In the Console

In the Browser

Thursday, January 16, 2014

Javascript載入動畫的plugin

在從前當我想要在網頁中載入自己的javascript於標頭時,通常會將其包含於page load script中。然而隨著時代的轉移,我們有著AMD/CMD (異步載入)的組件了,例如:RequireJSSeaJS,CurlJS等等。因此現在我可以寫許多的JS組件並且僅在我需要它的時候將其異步載入。

在從前要在網頁內載入我們的JS時,通常我們需要某些UI控制器來指定何種資源是需要被載入的。當使用RequireJS後,此loading 時間是可以被分割到許多短暫的時間中的。 不過有時在載入JS resource 時仍然會花不少時間,也許是某些resource很大或複雜性比較高。然而理由到底為何,其實並不是很重要。最重要的是要讓用戶知道目前發生了什麼事, 故UI必須要可即時回應。

若用戶按某一個一個需要遠端載入resource的按鍵時,而RequireJS若只在resource完全載入後才回應使用者的話,當時間一久,使用者很可能會非常困惑且感到沮喪。因此,當然使用任何XHR 或遠端要求時,我也會希望如何UI 一樣的即時回應,來告知使用者目前發生了什麼事。

載入JS,當需要使用者等待時,你需要一個考慮周全的設備(device)用來顯示回應訊息於你的UI上。你可以從GitHub下載所有的程式碼,或是從下面另外一個分流的版本。

下載

使用範例

JQuery & SeaJS

Example Usage

JQuery & RequireJS

Mootools with no module loader

謝謝Hector Yeh幫我翻譯。
英文版