case
ADM Blog
23Jun/100

How to run python code in Windows batch (bat) files

Here’s the bit of tricky batch file magic that does it:

1
2
3
@setlocal enabledelayedexpansion && python -x "%~f0" %* & exit /b !ERRORLEVEL!
#start python code here
print "hello world"

The way it works is that the first line of the file does two different things.

1. starts python interpreter passing the name of the file in, and the -x option will tell it to skip the first line (containing .bat file code)
2. When python finishes the script exits.

This nifty trick makes it much nicer for writing admin scripts with python on Windows.

21May/100

FlashBuilder network issue

Like most of my articles here, I try to post solutions for unusual problems I encounter now and then that may help someone someday. And this one almost made me scream.

So here's the story. My DEV environment (http://dev/) is a Virtual Host mapped in the Windows host file to point to a sandboxed directory somewhere on my hard drive. The Flex project I'm building uses a RemoteObject and tries to communicate with a AMFPHP gateway to do it's stuff. All good till here.

The weird part is that when I try to run the app, even though my flash is coming from the DEV host and the path to the gateway points to the same DEV host, the AMF calls either failed with a security exception or if they worked, they were extremely slow. The delay between a service call and a response/error was somewhere between 6 and 10 seconds.

Why oh why !? The AMFPHP Browser app that comes with the package works just fine so my app was at fault somehow. Tried some investigations and thanks to Firebug I found the vital clue.

It seems that my app was trying to make the connection to the gateway through http://localhost:37813/. WTF ?? I didn't had any reference to 'localhost' in my code, yet the app was trying to connect using that address for some reason. And quite often, the crossdomain.xml failed to load resulting in a security error.

So what in the world is the problem then ? Well, Flash Builder seems to be the problem (and me for not RTFM).

It seems that if you compile your swf with Network Monitor active, which you may not realize, especially if the window is not even opened, you have just told your swf to redirect all traffic to localhost:37813. It will compile the redirect info into your flash. Traffic may work if you have Flash Builder debugger running but try to deploy that somewhere. Heh.

All you have to do is turn network monitor off. Recompile your swf. Redeploy.

Ta da !

11May/100

Zen Coding

If you write HTML for a living, and you don't know Zen Coding yet, you are missing out big time.

Zen Coding is build as a plugin for commonly used editors (including Notepad++, yey!) that allows you to write HTML, CSS and XML code 20 time faster. So writing:

1
html:xt>div#header>div#logo+ul#nav>li.item-$*5>a

with a keystroke converts to:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
	<title></title>
</head>
<body>
	<div id="header">
		<div id="logo"></div>
		<ul id="nav">
			<li class="item-1"><a href=""></a></li>
			<li class="item-2"><a href=""></a></li>
			<li class="item-3"><a href=""></a></li>
			<li class="item-4"><a href=""></a></li>
			<li class="item-5"><a href=""></a></li>
		</ul>
	</div>
</body>
</html>

Don't get this wrong, like the man said, "The purpose of ZC is not to write a full HTML page with a single line, but to help you write smaller code chunks.". Here is a video introducing the system in further detail.

It is easier than it looks actually, and looking a bit over the syntax will make total sense. Printing the cheat sheet also helps :)

Also worth noticing that in Notepad++ (the only one I tried) the plugin added few more functions that help with the coding that I'm sure you'll enjoy (Jumping to the edit points is a God given). This project inspired another neat tool for PHP developers to output HTML using this syntax from code. You can find more here

I have only touched briefly on what it can do but I will certainly not author another single HTML document without the benefit of Zen Coding.

11May/100

Check if user visited certain websites

Today I found a website called http://www.stayinvisible.com/ that uses a really clever technique to peak in your browser history. They can't see everything of course but they can see whatever they are interested in and that is a list of web-proxy websites.

So how are they doing it ?

First, they have a list of websites they are interested in, like i said, a list of web-proxies.

1
2
3
4
5
6
7
var sites = {
    "hidemyass.com": ["http://www.hidemyass.com", "http://forum.hidemyass.com"],
    "freeproxy.ca": ["http://www.freeproxy.ca"],
    "proxy4free.com": ["http://www.proxy4free.com"],
    ....
    ....
    }

Second, they create a temporary IFRAME where they write a simple 2 lines CSS that does the magic

1
2
a { color: #000; display: none}
a: visited { color: #F00; display: inline }

... and in the body they append all the links from the sites list.

The browser renders the links, and all the sites that appear in your history will use the "a:visited" CSS class. The others use the normal "a" class that has a display:none property and will be hidden.

What's left to do is iterate all the links from the frame and check if they are visible or not to know which of them are in your history and which of them aren't. Pretty simple eh ?

So here's the class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
var bHistory = function(){
  var sites = {
    "hidemyass.com": ["http://www.hidemyass.com", "http://forum.hidemyass.com"],
    "freeproxy.ca": ["http://www.freeproxy.ca"],
    "proxy.org": ["http://www.proxy.org", "http://www.proxy.org/cgi_proxies.shtml", "http://www.proxy.org/forum/index.html"]
  };
  var visited = {};
  function getStyle(el, scopeDoc,styleProp) {
    if (el.currentStyle) var y = el.currentStyle[styleProp];
    else if (window.getComputedStyle) var y = scopeDoc.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp);
    return y;
  }
  function remove( el ) {
    el.parentNode.removeChild( el );
  }
  function createIframe() {
    var iframe = document.createElement("iframe");
    iframe.style.position = "absolute";
    iframe.style.visibility = "hidden";
    document.body.appendChild(iframe);
    if(iframe.contentDocument) iframe.doc = iframe.contentDocument;
    else if(iframe.contentWindow) iframe.doc = iframe.contentWindow.document;
    iframe.doc.open();
  	iframe.doc.write('<style>');
  	iframe.doc.write("a{color: #000000; display:none;}");
  	iframe.doc.write("a:visited {color: #FF0000; display:inline;}");
  	iframe.doc.write('</style>');
    iframe.doc.close();
    return iframe;
  }
  var iframe = createIframe();
  function embedLinkInIframe( href, text ) {
    var a = iframe.doc.createElement("a");
    a.href = href;
    a.innerHTML = site;
    iframe.doc.body.appendChild( a );
  }
  for( var site in sites ) {
    var urls = sites[site];
    for( var i=0; i<urls .length; i++ ) {
      embedLinkInIframe( urls[i], site );
      if( urls[i].match(/www\./) ){
        var sansWWW = urls[i].replace(/www\./, "");
        embedLinkInIframe( sansWWW, site );
      } else {
        var httpLen = urls[i].indexOf("//") + 2;
        var withWWW = urls[i].substring(0, httpLen ) + "www." + urls[i].substring( httpLen );
        embedLinkInIframe( withWWW, site );
      }
    }
  }
  var links = iframe.doc.body.childNodes;
  for( var i=0; i<links.length; i++) {
    var displayValue = getStyle(links[i], iframe.doc, "display");
    var didVisit = displayValue != "none";
    if( didVisit ){
      visited[ links[i].innerHTML ] = true;
    }
  }
  remove( iframe );
  var usedSites = [];
  for( var site in visited ){
    usedSites.push( site );
  }
  return usedSites;
}

To use it:

1
2
   var visited = new bHistory();
   alert(visited); // an array with visited websites from the defined list

All credits go to the smart man who did this. Cheers!

5May/100

Open and Save files to Desktop without going to Server

Few days ago I was working on a jQuery based tool to QA the JavaScript functionality of a website and I was in need of a method to save and load my scripts to Desktop.
In most cases this require a server script where you send the content and it will serve it to download and same for loading it. But a colleague suggested a better solution: to use the FileReference class.
First step was to create a simple flash with the required functionality and send/retrieve data with ExternalInterface. Failed miserably. Why ? Because it seems Flash will not allow you to open a File Dialog from script only. You literally have to click a button from the movie interface to be able to do that. If you knew that good for you, I didn't.

So, I've created another flash movie, where you pass the open and save image and callback and it will insert the flash with the specified images in place and look just like any other buttons.

Here's a small demonstration (other buttons beside open and save are just for show):

So what do you need to set it up ?

First, you have to include the FileDialogs.js in your document (or just paste the code inside it into your own script).

Second, you need your JavaScript callbacks.

1
2
3
4
5
6
7
function openCallback(input) {
     document.getElementById('text').value = input;
}
 
function saveCallback() {
     return document.getElementById('text').value;
}

openCallback() will be called once the user will select a file from the desktop and pass it's content as a parameter
saveCallback() will be called when the user clicks save, before the dialog to choose a file name opens, and it must return the content you want to save to disk

Third, you must setup the whole thing.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// call this function on the onload event so the placeHolder element gets created
function onLoad() {
    // Create a config object
    var config = new FileDialogsConfig();
    // width of the entire flash movie (buttons width + padding)
    config.width = 45;
    // height of the movie
    config.height = 16;
    // padding between buttons
    config.padding = 5;
    // open dialog button image and javascript callback function
    config.open.image = "open.png";
    config.open.handler = "openCallback";
    // save dialog button image and javascript callback function
    config.save.image = "save.png";
    config.save.handler = "saveCallback";
    // create the movie inside an element with the given id and configuration
    new FileDialogs("placeHolder", config);
}

Note: Handler callbacks in the config must be declared as String and not reference. IE will freak out and I don't want to fix it.

You can have only one button (open or save) if you chose so. Just don't set the other one.

That's about it. The placeHolder can be any container element. The script will set it's style size based on the configuration, the movie will have transparent background so don't worry about that, and it will set it's float property to left so you can add other stuff after it. But all those things are easy to configure if you mess a bit with the FileDialogs.js file.

Cheers!

Download Source and Demo