Sunday, October 25, 2009

Regex Article in php|a

The August edition of PHP Architect magazine contained my introductory article on regexes. It has a PHP slant but mainly it is about regexes. Well, most of it is introductory but it contains a bonus section at the end using advanced regexes in SQL to repair a database in situ.

The print magazine arrived by air mail a couple of weeks ago and I finally got to read it. I was pleased (and relieved) that it read well. If you have read it I'd love to get some constructive criticism - especially if you are uncomfortable with regexes.

It was also my first print article to use colour, and I think that worked well too.

One correction in the complicated "Repairing With Regexes" section at the end of the article. The text says "So \1 has to be written \\\\1 (that is four backslashes)." That seemed a strange thing to write, so I took a look at the unit test source code (included with the PDF download version of php|a magazine) I had written. Four backslashes is correct when in PHP, but when in SQL it should be "\\1" not "\1".
(I just checked my emails from when we were proof-reading, and one of the edits had removed all those backslashes; I caught that at the time but ironically I got it wrong when putting them back in.)

The other minor correction I only realized after Arne Blanket's column in the same magazine issue! I had written: "...an IP address after that at sign, such as darren@10.0.0.1, which, while unusual, is technically valid". In fact "darren@[10.0.0.1]" is the technically valid form. Which is doubly annoying because my article's regex would reject those square brackets and I hadn't explicitly pointed that out. (No harm done, though, as this email form is highly discouraged.)

Arne's column also points out that top-level domains are no longer just two or three characters. So my '\.[a-zA-Z]{2,3}$' suggestion should really have been '\.[a-zA-Z]{2,}$'. Luckily, that suggestion was just in a list of other ideas, not part of the article's main regex.

(By the way I enjoyed, and will blog about real soon, some other articles in this particular issue; if you are not a subscriber, and your work involves data and PHP, then this is the back issue you should get!)

Wednesday, October 14, 2009

Control firefox from PHP?

Internet Explorer can be controlled from a COM object interface, and therefore from PHP (i.e. any scripting language that has COM support).

But is there a way to get script control of firefox? Ideally I'm looking for a platform-independent solution, and something I can use from PHP. Google is not helping (PHP's dominance as a server-side technology overwhelms the client-side related hits).

Here is my dream PHP script:

$firefox=new FirefoxInstance();
$firefox->set_url("http://dcook.org/work/");
$firefox->wait_until_fully_loaded();
$links=$firefox->get_links();
$found=false;
foreach($links as $id=>$info){
if($info['text']=="MLSN"){$firefox->click_link($id);$found=true;break;}
}
if(!$found)echo "MLSN link is missing...\n";

Or:

$form=$firefox->get_form("login");
$form->set("username","guest");
$form->set("password","guest");
$form->submit();

Et cetera. I.e. I'm talking about operating firefox the same way a user does; I know I can grab the raw HTML, parse it, etc. all from PHP, but that doesn't test a web site the same way clicking links in a browser does. Especially web pages with javascript, iframes, AJAX, etc.

(I'd heard of XPCOM but, if I've understood it correctly, it is a library to build firefox and its extensions, not something to control firefox? It also has no PHP bindings.)

BTW, going back to controlling IE from the COM interface, I don't suppose anyone has seen a detailed tutorial on how to use it to fill out and submit forms? I only ever see simple examples of how to set the URL, but I believe full control should be possible.
Dec 16th 2009 UPDATE: This came to the top of my to-do list so I read the MSDN docs on the Internet Explorer COM object, and now it is my understanding that I cannot manipulate and submit forms via the COM object. None of the example usage even hinted at doing this.

Thursday, September 24, 2009

PHP, reliability, ASP and remote desktops

I've been working in ASP on an IIS server recently. Not my environment of choice, but the scripts I need to write are relatively simple, so I decided it was easier to go with it than ask for PHP to be installed (which then requires apache). This is quite a helpful page:
http://www.design215.com/toolbox/asp.php

We'll see how it goes. In many of the systems I work on, windows or linux, I usually use commandline PHP as the glue. I'm always amazed at how rock solid it is. Especially on Windows it is always the most stable element. E.g. I've a 24/7 PHP script that deals with COM objects. The COM objects crash regularly. But I just catch the exception in PHP, delete the COM object, create another one and off we go. Needing to use 3rd party libraries only available in C are the only reason I write C++ recently, but they cause me no end of trouble (mysterious crashes deep in windows system calls for instance). Windows itself needs to be rebooted every 3 or 4 weeks or it starts to go all wobbly on us, and my 24/7 PHP scripts simply run for those 4 weeks without a single problem or restart.

Of course saying PHP is more stable than C would be stupid; PHP is itself a C app. The difference is that PHP is a well-crafted piece of code, better than the COM objects, 3rd party C libraries and Microsoft OSes I'm comparing it to.

Going back to IIS, I don't have it installed locally, so have been developing on a remote server. "rdesktop" wins this month's "application I wish I'd discovered months ago" award. Previously I would have to boot up my windows notebook just to use remote desktop. rdesktop gives me this functionality on linux, works perfectly (touch wood) and copy and paste works too.

Thursday, September 3, 2009

Windows SEH in C++

A windows app was mysteriously dying, roughly once a day; no clues in any of the various log files.
So I enabled Windows SEH:
_set_se_translator(win32_exception_handler);

(See MSDN article about _set_se_translator)

And here is my implementation of that function:

void win32_exception_handler(unsigned int code, EXCEPTION_POINTERS *ep){
throw new win32_exception(code,ep);
}

And the class (cut down to basics) is:

class win32_exception{
std::string info;
public:
win32_exception(unsigned int code,EXCEPTION_POINTERS *ep){
//Describe it in info
}
const char *what()const{return info.c_str();}
};


Then, I have this code (which was already here before I enabled SEH):

try{
e=main_loop(stuff);
catch(std::exception &e){
ErrorLog()<<"Got a std::exception thrown by main_loop:"<<e.what()<<" (will treat as fatal)\n";
return -9;
}
catch(win32_exception &e){
ErrorLog()<<"Caught win32_exception thrown by main_loop:"<<e.what()<<" (will treat as fatal)\n";
return -9;
}
catch(...){
ErrorLog()<<"Got an unexpected exception thrown by main_loop (will treat as fatal)\n";
return -9;
}


Now, what I don't get is today the program died with this message:
Got an unexpected exception thrown by main_loop (will treat as fatal)

I'm staring and staring at the code and don't get why the win32_exception code didn't catch and instead some other exception type got caught. Enabling SEH was the only change, all such exceptions should go through my function, and that only throws win32_exception instances.

The other mystery to me is what is the type is of this "unexpected" exception.

(I'm hoping to come back and add to this blog entry when I work out what is going on!)