Joanna About this site

About

How this site is organized and what it's for

Weblog start page

The start page contains the most recent 15 articles.

Home page
The main home page of my website, not my weblog. Currently not used.
------------------
Articles by month
Click here to get all the articles for a particular month.
This month's articles (if any)
Current month
Today's articles (if any)
Articles dated 2008/09/07 only

------------------
Subtopics
Excel :: Hacking :: PHP :: Perl :: Shell

------------------
My email address
Site map
Search my weblog
Search for text on this site
You may have to use search
if I move files around!
Listing of all articles by date
Moving man
Flavours
There's more than one way to view this weblog; these links display the current page in other formats.
External links
These are a few of my favourite sites.
T E S T
Slashdot yesterday

Copyright © 2003-2007 Alternate Worlds Publishing, Boston MA USA


powered by blosxom -- www.blosxom.com
Wenhua dageming de zhongyao jiaoxun shi bixu fandui geren mixin
If I have been able to see further, it is because I am surrounded by midgets.
Never ascribe to stupidity that which can adequately be explained by malice.
"Your argument's repugnant and intriguing." "That's kinda my thing."

Danny's Weblog

2008 Aug 31 [ Sun ]

Adding a new function to an Excel right-click menu

A few months ago I posted a short routine that adds a (hopefully) useful function to Excel's right-click menu when you have a range of cells selected: www.panix.com [http://www.panix.com/~dannyw/weblog/Computers/Programming/Excel/filldown01.html]

At that time I did not explain the tricks for adding that function to the right-click menu. This posting lists those tricks. They aren't rocket science, and I don't go into every detail, but I think it's a better overview than most. You should read through the whole thing before you start trying stuff out.

This information is for Excel 2003. It is probably also good for Excel 2000, but is probably rather misleading for Word, and basically irrelevant for Access. I haven't tried Excel 2007, but I understand MS redesigned the whole menu structure for Excel 2007, so it probably won't work.

The following links may also be useful:

Adding menu items via VBA: www.fontstuff.com [http://www.fontstuff.com/vba/vbatut07.htm]

Creating an Excel addin: www.fontstuff.com [http://www.fontstuff.com/vba/vbatut03.htm]

If you are not very familiar with VBA, note that when you switch to the VBA window many of the top menu items do not work the same way. In particular, you can only get VBA help while you are in the VBA editor, not when you are in normal mode (and vice versa). Also, you cannot do "save as" (including "save as addin") while you are inside the VBA window.

1. The standard term in Windows for what I'm calling "right-click menus" is actually "context menus". However, neither term is relevant to VBA. VBA considers such menus to be simply a type of "commandbar", just like the main menu. In both Word and Excel you can assign a macro to a *non-context* menu via the GUI, but you can only assign a new function to a *context* menu via the GUI in Word; in Excel you need to use VBA, because the GUI doesn't let you (funnily enough).

The term "shortcut menu" usually means a menu accessed by a keystroke combination like ctrl-G.

2. For the sake of trying all this out, here's a very simple function: it makes the text in the currently selected cell (or cells) bold. Starting from a new empty workbook, open the VBA editor with Alt-F11, select Insert Module (to create Module1) and enter the following code in Module1:

Sub MakeBold()
selection.Font.Bold = "True"
End Sub

(When you test this later, remember that the right-click menu while you are actually editing a cell is a different menu from the one which comes up while you have the cell selected; the MakeBold routine will only work in the latter case.)

3. Then the basic code for creating a new right-click menu item to call that routine is like this:

Private Sub Workbook_Open()
Set NewControl = Application.CommandBars("Cell").Controls.Add
With NewControl
  .Caption = "Make bold"
  .OnAction = "Module1.MakeBold"
End With
End Sub

You need to put this in the "ThisWorkbook" module. You can do that by opening the VB editor (if it's not already open) with Alt-F11, double-clicking on "ThisWorkbook" (under "Microsoft Excel Objects" under "VBAProject" in the Project window) to open the "ThisWorkbook (Code)" window, and selecting "Workbook" on the left-hand dropdown menu (which initially said "General").

Then the effect is: when the workbook is (next) opened, the "make bold" function gets added to the context menu for each cell (or range of cells). And that feature will *still be there* after you close the workbook, on any other workbook, even after you close and re-open Excel! (Excel has stored the link from the menu to the workbook with the actual code, and will reopen the workbook as soon as you try to execute the menu item.)

4. Now there are two snags. One is that in some cases the above code can add the menu item *every time* the workbook is opened, accumulating more and more copies... and it can happen that they never get removed. The other snag is that it's a pain having to add utility code like this to each workbook where you need it.

5. There are several ways to get around the first problem.

Whatever you do, you need to do two things: don't add a menu item which already exists; and don't forget to remove the item when you exit. But it turns out that the best way to do those two things depends on what you do about the second problem above.

6. Your decision on how to install code like this (any kind of VBA code, not just context menus) depends on whether you want to distribute the code. The big problem is macro security. Excel by default (at least in Excel 2003) refuses to load macros, giving a scary error message and a misleading prompt about how to enable macros which just creates confusion. Unless your users are very used to receiving workbooks containing macros (which allows you to use the signing mechanism – Google search for selfcert.exe), it seems to me to be impractical to distribute macros inside a regular workbook.

7. Additionally, even if the macros are for your own use, it is very tedious to have to reinstall multiple functions and features in each new workbook, and especially to update an existing workbook with new or improved code. (And you have to re-run the signing mechanism for each change, however small.)

8. For these reasons, I think the only practical way to deploy Excel macros is by using the "Add-in" feature. An add-in is just a regular workbook which you put in a special directory for special handling; under 2003 the location is c:\Documents and Settings\dannyw\Application Data\Microsoft\Addins. This is the default location which Excel automatically switches to when you do "save as" "Microsoft Excel Add-in (.xla)".

Instead of manually copying the file to the addin folder, you can use the Tools - Addins - dialog, which allows you to "browse" for another location. Once you select an addin in another location, it will ask you if you want to copy the addin to the standard addins. Even if you don't, Excel will remember to load the addin from the nonstandard location the next time it starts up.

To be any use, an add-in has to contain VBA code. Also, there's no point including regular worksheet data in an add-in, unless it's used by the VBA code – for example, boilerplate text with copyright information which macros might add to every saved workbook.

Once the user has trustingly installed the addin, the macro code will always be available: for instance, the function names are all global, so workbooks can use the functions without needing to specify a module name. And without causing intrusive prompts about enabling macros. (Which makes me wonder about what happens if you just haplessly click on an .xla file link inside a browser.)

However, the function names for some reason don't appear in the list when you insert a function via the GUI; you have to know the name already.

Because the function names are global, you can rename the addin if desired: for instance, if you are a system administrator, you can check that everyone has now installed the latest version of an addin by checking that the filename is "utils-23.xla", and if anyone still has "utils-19.xla" you can grumble at them.

Also, you only need to update a function in one place, and then the updated function is automatically available in every workbook.

9. MS suggests using the "Personal Macro Workbook" for this kind of purpose. But there's only *one* of those per user. If you have multiple users, one or two of them will be already using theirs, and they won't be happy if you overwrite it. Even if the macros are only ever going to be used by you, you may want to keep different sets of macros in different files.

10. Your users will inevitably be exchanging workbooks all the time. If they include macros, every user will need to trust every other user, and/or spend time checking that any macros are safe. If all the workbooks use macros from a single addin, users need to trust only one source.

Additionally, Excel includes an optional weak encryption feature to prevent users opening an addin to view/edit it. This may be cool if you are *selling* the addin, but of course it prevents the educated user from checking that your macros are safe.

11. Because an addin is loaded once at startup, and the functions it provides are intended to stay in memory until Excel closes, the risk of adding menu items more than once is lessened. However, it is still worth putting in defensive code (especially while you are figuring all this out). Also, I felt I should provide some code in case you do *not* deploy the code as an addin.

12. You can check whether a menu item already exists with code like this:

Function Check_MakeBold()
Check_MakeBold = False
For Each Myitem In Commandbars("Cell").Controls
    If (Myitem.Caption = "Make bold") 
        Check_MakeBold = True
    End If
End For
End Function

If you open the Immediate window, you can run the routine like this:

debug.Print(check_makebold())

The equality test is case-sensitive, although the function name is not.

13. If necessary, you can delete the context menu item when a regular workbook closes like so:

Private Sub Workbook_BeforeClose(Cancel as Boolean)
	On Error Resume Next
	Application.Commandbars("Cell").Controls("Make Bold").Delete
End Sub

By including the "on error" you don't need to check whether the "Make Bold" item exists before attempting to delete it.

The above routine needs to be entered in the "ThisWorkbook" module, using a similar approach as for the code running on workbook load (see above).

Another approach is to reset the entire r-click menu to its default state, ie (search Excel Help for "reset method") all the original items and no new ones:

Application.CommandBars("Cell").Reset

This is good if all of your menu additions are created by a single module, but if you have multiple menu items from different modules you will probably want to handle them individually.

Another approach – the one I hinted at in the previous posting – is to include the "temporary" parameter when you add the menu item:

Set newControl = Application.CommandBars("Cell").Controls.Add(, , , , temporary)

14. Once you have the addin installed and running, how do you debug it? It turns out that even the creator of the addin can't open it directly to edit it while it's running as an addin. But if you load it as a normal workbook instead, the functions aren't globally accessible from any workbook.

There is an interesting workaround that I haven't seen described elsewhere: you simply load the file both as an addin at startup, and then as a regular workbook. It seems like that would cause some sort of namespace conflict, but I haven't run into that. I haven't figured out the details of why.

15. If you try all this stuff out, you will accumulate a bunch of functions and want to implement the install procedure by looping through them. I leave that as an exercise for the reader.

2008 Aug 10 [ Sun ]

CPAN install didn't work too well

Although I was able to make CPAN work to the extent of downloading new modules which Perl would *attempt* to run, there were *thousands* of error messages during the install which I could not evaluate. (I have *more than a megabyte* of log files from the various install steps.)

And indeed, the module I really wanted – DBD::sqlite, as I am too cheap to pay for MySQL at Panix – crashes as soon as I try to do anything more with it than load it.

It is not easy to find information on how to handle such problems. I found the following page: sial.org [http://sial.org/howto/perl/life-with-cpan/debug/] which gives the impression the writer has been through the process, but is not very useful to the newcomer (unless you like finding "vendor-supplied packages" and compiling them from source).

Fortunately, an alternative showed up shortly after I posted the previous article: www.panix.com [http://www.panix.com/~dannyw/weblog/Computers/Programming/Perl/cpan01.html] Panix happened to upgrade Apache to PHP5 along with Sqlite (perhaps related to me figuring out a way I could make PHP5 run even though PHP4 was installed in Apache), so I can do a lot of the things I thought I needed DBD::sqlite for. Heigh ho, suck air.

2008 Jun 16 [ Mon ]

Setting up CPAN on panix with only user privileges

One of the reasons the perl programming language is so great is that there is a huge variety of modules avilable that you can use to add functionality. The CPAN site (http://search.cpan.org) has thousands. But installing them manually can be so clumsy and error-prone that I've found it easier to write my own code.

I had been aware for *years* that the best way to install modules was by using the CPAN module itself. But each time I tried to set it up at previous hosts or panix, I failed. (It works much easier when you are root, eg on my own Linux boxes.)

This time I seem to have succeeded. ("Danny, 1995 called and wants its issues back.")

Apparently the CPAN module *itself* was installed at panix, so I didn't have to do the whole "make install" thing on CPAN itself. However, the first time I tried running CPAN with something like
perl -MCPAN -e 'install Archie'
it apparently recognized that I didn't have any configuration defined and started asking me a bunch of questions that I didn't really know how to answer. But I knew that the *defaults* for CPAN would be to install to *system-wide* directories which I didn't have write access to. I tried using the "PREFIX" switch for the directories, but it didn't quite work. It looked like the ftp get was failing to bring in the source file, perhaps because of an error reported about "MD5 security checks". (Later I realized that impression was false – that message always appears.)

Incidentally, it's good to use a module like Archie as a test when you're setting up CPAN, because you don't want to mess up the links to a module you actually *need*. You can check whether a module is already installed (assuming your general perl setup has not been screwed up in the meantime!) like this:
perl -MArchie -e 1
which will silently succeed or produce an error message if Archie is not available.

Another irritating issue was that the CPAN setup script presents you with a ginormous list of possible mirrors, and the way to navigate and select them is not obvious. Apparently the list is fed to you via the "more" utility. Here are the tricks: when you get to the list, just press space to get another screenful, and repeat enough times to get to the end. Then you can enter one of the mirror addresses. I'm not sure how to add more than one – I wouldn't bother at this point.

Having licked my wounds overnight, I tried again this morning.

The following webpage would probably be a good guide for most people: www.dcc.fc.up.pt [http://www.dcc.fc.up.pt/~pbrandao/aulas/0203/AR/modules_inst_cpan.html]

However, actually what I did was manually edit the ~/.cpan/CPAN/MyConfig.pm setup file that had been produced yesterday. This is what I ended up with:

> cat .cpan/CPAN/MyConfig.pm 
$CPAN::Config = {
  'build_cache' => q[10],
  'build_dir' => q[/home/1/dannyw/.cpan/build],
  'cpan_home' => q[/home/1/dannyw/.cpan],
  'ftp' => q[/usr/bin/ftp],
  'ftp_proxy' => q[],
  'getcwd' => q[cwd],
  'gzip' => q[/usr/bin/gzip],
  'http_proxy' => q[],
  'inactivity_timeout' => q[0],
  'index_expire' => q[1],
  'inhibit_startup_message' => q[0],
  'keep_source_where' => q[/home/1/dannyw/.cpan/sources],
  'lynx' => q[/usr/local/bin/lynx],
  'make' => q[/usr/bin/make],
  'make_arg' => q[],
  'make_install_arg' => q[/home/1/dannyw/myperllib],
  'makepl_arg' => q[PREFIX=~/perl5lib/ \_
    LIB=~/perl5lib/lib INSTALLMAN1DIR=~/perl5lib/man1 \_
    INSTALLMAN3DIR=~/perl5lib/man3],
  'ncftp' => q[/usr/local/bin/ncftp],
  'no_proxy' => q[],
  'pager' => q[/usr/bin/less],
  'shell' => q[/usr/local/bin/tcsh],
  'tar' => q[/usr/bin/tar],
  'unzip' => q[/usr/local/bin/unzip],
  'urllist' => [q[ftp://mirror.nyi.net/CPAN/],  \_
    q[ftp://ftp.wayne.edu/cpan/]],
  'wait_list' => [q[wait://ls6.informatik.uni-dortmund.de:1404]],
};
1;
__END__
Note the following:

1. Info on the web suggested that the "~" should work in this file, and I did use it for the "make5pl_arg", but in general, I used a fully qualified path for the home directory.

2. Web info suggested creating the .cpan etc folders manually first, but I guess running the initial CPAN setup script had done that for me

3. The install script probably also guessed the correct locations for the executables like 'pager' for me. I did verify every one manually (with eg "whereis less").

4. It wasn't obvious what syntax to use to allow multiple urls in the urllist, but I guessed right the first time.

5. The INSTALLMAN1DIR value looks like it would break something, but apparently didn't. Maybe it's not essential, because I don't know how it could work.

Now I could run "perl -MCPAN -e 'install Archie' and it seemed to be OK. But I had not fixed the path for modules in my shell, so trying "perl -MArchie -e 1" failed.

The web info provides the following examples for the bash shell:
export PERL5LIB=${PERL5LIB}:~/perl5lib
export MANPATH=~/perl5lib

I am running tcsh, so I knew I had to make some changes to that. But this is the output of the "setenv" command that works:
PERL5LIB=~/perl5lib/lib
having used eg "setenv PERL5LIB perl5lib/lib". This is what I needed in the .tcshrc file:
setenv PERL5LIB ~dannyw/perl5lib/lib
Remember that you can use "source .tcshrc" to run the commands in that file again without having to log out and back in – although some commands may have unwanted results, for example if you append a directory to a path repeatedly.

Note that my version has an extra "/lib" on the end. It didn't work without it. I don't know why the web example apparently did work for them without it.

Incidentally, the default perl at panix is indeed perl5:
This is perl, version 5.005_02 built for i386-netbsd
I don't know what to do if you're running perl4 or 6 (is anybody?)

I'm not sure why the web example tried to bring in an existing value for PERL5LIB. There wasn't one when I checked (perhaps too late) and running eg "perl -MCGI -e 1" still works. – Later: according to this website:
www.perl.com [http://www.perl.com/doc/manual/html/pod/perlrun.html] the PERL5LIB variable is

A colon-separated list of directories in which to look for Perl library files before looking in the standard library and the current directory.
so it seems to be a *user-defined* variable, so it is normally empty and it doesn't smash any existing definition if I just set it directly as above. Maybe the bash shell doesn't complain like tcsh if the variable is empty when you try to append to it. – Confirmed.

The MANPATH thing just doesn't work for me at all. Doing "perldoc Archie" works fine without it. Trying to append to MANPATH causes an error message. And if I set MANPATH without appending to the existing value, it makes "man bash" (or anything else) fail.

Some webpages say you need to do this: setenv MANPATH $HOME/perl5lib:${MANPATH} but that failed too. The really funny thing is that $MANPATH doesn't seem to be set to anything in the set or setenv lists, but setting it to something seems to screw up "man". I guess setting $MANPATH *completely overrides* the path set up in man.conf.

When I checked, the default search path for man set in /etc/man.conf seems to be really long and complicated. I couldn't see an easy way to get the current value for it into the environment variable. However it turns out that there's a "-m" switch to man which *adds* a search path to the existing (invisible) path, so I put the following line in .tcshrc:
alias man "man -m ~/perl5lib"
and it worked fine, ie both "man Archie" and "man bash" worked.

Now I have to actually try it with a module I need! Maybe I'll write that up later. If you have been following along and want to try it yourself, remember that cgi programs don't get your path from your user environment, so they will need something like
push(@INC, "/usr/lib/bliv/");
as I discuss in an old posting:
www.panix.com [http://www.panix.com/~dannyw/weblog/Computers/Programming/Perl/perltip01.html]

2008 Mar 16 [ Sun ]

Useful subroutine in Excel: "filldown"

This is not the most complex stuff I've done in Excel but it is all my own code and does something which I think is generally useful, so I thought I'd list it.

It's intended to be linked to a right-click; I leave that out as an exercise for the reader... especially as I now realize that I wrote the code for that part incredibly badly, although it does work. Hint: there is a parameter for this: application.CommandBars("Cell").Controls.add which prevents an option being added multiple times. See one of the books (I forget which) in my post: www.panix.com [http://www.panix.com/~dannyw/weblog/Computers/Programming/Excel/books01.html]

It's intended to make it easier to enter data in a typical Excel table where the same values recur multiple times. For instance, if you are entering vehicle expenses in a company garage, you probably need to enter the expenses for each car multiple times with the same info so that you can easily sort the data with a pivot table. With this sub, you can just leave a blank for repeating fields, and when you're ready you can just right-click on the table and select the sub, and a value will fill down into all the empty cells below it for each record and field. In many cases it will halve the entry time and cut out a lot of errors as well (ie ensure that each repeated value is identical).

Sub filldown()
' dW 2007-12-20 Loops through a range
' if a cell is blank, copy from previous row
' (we hope)
Dim cellnum, cellrow, cellcolumn, rowcount, columncount As Long
If TypeName(Selection) <> "Range" Then
  Beep
  MsgBox "This command requires a cell/range to be selected."
  Exit Sub
End If
If Selection.Areas.Count > 1 Then
  Beep
  MsgBox "This command only works on a single range."
  Exit Sub
End If
rowcount = Selection.Rows.Count
' You can't fill down if less than 2 rows
If rowcount < 2 Then
  Exit Sub
End If
'
columncount = Selection.Columns.Count
' MsgBox ("Rows = " & rowcount & " Columns= " & columncount)
'
cellnum = 0
For Each cell In Selection
  cellnum = cellnum + 1
  ' The \ operator does integer division
  ' First row is row 0
  cellrow = (cellnum - 1) \ columncount
  ' Don't do anything on first row
  If cellrow > 0 Then
    cellcolumn = (cellnum - 1) Mod columncount
    ' MsgBox ("Cell: " & cellnum & "Row: " & cellrow & " Col: " & cellcolumn)
    ' I seem to have defined cell locations starting at 0,
    ' but Excel has cell x,y starting at 1,1.
    ' Need to handle cells with formulas separately
    If cell.Value = "" Then
        If Selection.Cells(cellrow, cellcolumn + 1).HasFormula Then
            cell.Formula = Selection.Cells(cellrow, cellcolumn + 1).Formula
        Else
            cell.Value = Selection.Cells(cellrow, cellcolumn + 1).Value
        End If
    End If
  End If
Next cell
End Sub

When you play with this, remember that Excel resets the undo stack every time you run a macro. If someone wants to fix this code so that it implements its own undo feature, that would be cool.

Some basic setup info for PHP

I haven't looked at PHP for years and needed to read through Sams' "Teach yourself PHP in 24 hours" recently.

Here are some basic tips for setting things up:

1. Assuming your Apache server allows you to use .htaccess files, you can set a bunch of useful stuff here, eg:

AddType application/x-httpd-php .php

For instance, if most of your site is real .html files but you want to put .php files in a certain folder, you can put an .htaccess file in that folder that tells Apache to run the php interpreter on .html files in that folder:

AddType application/x-httpd-php .html

(You don't want to do that in your root folder because it would waste time running the php interpreter on all the ordinary html files.)

2. The phpinfo() command inside php of course produces a nicely-formatted html file with all the setup information for php, and you need to look at it. In particular, you want to check which php version you have and what modules are loaded (irritatingly Panix has a rather old version with few modules compiled in).

Also, it's good to check the "config-file-path". This (assuming you have shell access) allows you to find the actual php.ini file to check any items not shown by the phpinfo() command.

3. If you don't control the server, you can still set php setup variables inside .htaccess. You use the "php_flag" directive to set a php variable and the php_value directive to set a php.ini variable to a value, eg:

php_flag short_open_tag On

php_value include_path ".:/home/corrdev"

4. Even if you can't use .htaccess files, as of php 4.0.5 you can set some .ini values within php pre itself, eg:

ini_set( "include_path", ".:/home/corrdev" );

5. Don't forget the main php website, eg:

www.php.net [http://www.php.net/manual]

6. Here's the entire contents of a file you can save as test.php:

<?php
phpinfo();
?>

(I know putting that here makes me look like not the greatest programmer in the world, but every time I start looking at php again I find myself having to work out the basics of the syntax all over again.)

7. Here's some code which looks simple – ok, it is simple – but I find myself wondering whether it will work every time I start playing with php again (this is basically from the book's Listing 5.14 Returning to HTML Mode within a pre block):

<?php
$display_prices= true;
if ( $display_prices ) {
?>
<p>Interesting stuff to show in this case</p>
<?php
}
?>

I don't know about you, but if I had to figure out that syntax from scratch it would take a while.

2008 Feb 02 [ Sat ]

The benefits of learning Excel VBA

The following link explains in amusing detail just how unexceptional the Societe Generale trader M. Kerviel is in his skills, or indeed modus operandi: www.theregister.co.uk [http://www.theregister.co.uk/2008/01/31/kerviel/]

From what little I know about the situation in such companies, the article is not misleading.

2008 Jan 29 [ Tue ]

Some books I've used for Excel VBA programming

Recently I've had to use Excel quite a lot. I used to be quite snooty about it (although I recognized that – after SQL Server – it was Microsoft's most respectable product). Now, having gotten into VBA programming, I have to admit you get a rather solid development environment.

Anyhow, I wanted to put in links to a couple of books I can recommend:

1. Excel 2007 VBA Programmming for Dummies - John Walkenbach

I actually read his version for Excel 2000 first. The two books are much the same. I had a feeling that he caught some errors in the new version, or maybe I just understood stuff more the second time through (I was unable to compare them except by memory).

I don't think Walkenbach ever did a version of this book for 2003. I don't think there was much difference between Excel 2000 and 2003, but there are a lot of changes in 2007 for the new menu ("commandbar") structure. And the 2007 book *only* documents the 2007 code - people expecting the book to be backwards-compatible with 2003 are going to be very disappointed.

But in general, I found the book quite ueseful.

Walkenbach recommends this "blog": www.dailydoesofexcel.com [http://www.dailydoesofexcel.com/]

He also recommends reading Microsoft's own newsgroups via Google. Search Google Groups for microsoft.public.excel.programming, as well as several others under microsoft.public.excel.

2. The Absolute Beginner's Guide to VBA

The advantage of this book is it explains how to run multiple Office apps using VBA: for instance, to read your Outlook mailbox (or at least the header fields and a smidgen of the text) into Excel.

Also, it does show various useful examples in non-Excel apps, and I may need to take a shot at Word VBA sometime.

Incidentally, I rather wish the titles of these books weren't so embarrassing. Don't bring them to your client site! I've actually done some fairly complex stuff with Excel, and if clients ever see this blog they'll get the wrong idea. Hmm, then again if they see some of my other posts my goose is cooked anyhow!

2007 Jan 10 [ Wed ]

Debugging CGI programs

In trying to add new features to this site recently I have had to figure out, or dredge out of my fading memory, the following tricks for debugging CGI programs.

1. Of course you can run perl from the command line, like so:

perl ~dannyw/htdocs/bin/blosxom.cgi

With older versions of perl, this will automatically prompt you for CGI variables. You can enter these one after another like this:

startdate=200610

listqty=20

and finish with a ctrl-D. Except ctrl-D didn't work for me! It turns out my shell was set up to accept a ctrl-D at the shell prompt to log out, but when *not* at the shell prompt the shell just silently discarded it – not I think what the docs claimed. I turned off the logout feature and then my shell passed ctrl-D to perl as advertised.

2. You can also put the parameters in right on the command line:

perl ~dannyw/htdocs/bin/blosxom.cgi startdate=200610 listqty=20

but for some reason I could not make that work to set the "Extra path information", ie the parameter PATH_INFO which Apache passes to cgi programs in the environment and which Blosxom expects to contain the folder path eg "/Reviews/Movies".

What I had to do instead was set that parameter in my shell environment:

setenv PATH_INFO /Reviews/Movies/

which of course does not interfere with the value set by Apache if you're running from the command line – duh (it took me a long time to realize that). (The "setenv" built-in function works for my shell but probably not for yours.)

3. However, now I discovered that my suspect code did *not* bomb from the command line, so I still couldn't see the error message! So I had to put a call to the Carp module in Blosxom.cgi:

use CGI::Carp qw(fatalsToBrowser);

which told me the file I was trying to write to was "no such file". That's weird, I thought: it's there, when I check from the command line.

Then I noticed that another filespec in the same section of code – one which worked – used a different path. Aargh! In Apache's environment it doesn't understand the same filespecs that I can use in my shell – including when I run a .cgi program from the shell. I changed the filespec to match the other file's path and all was well.

It's really strange: I could have sworn that the bad filespec *did* work a few times... oh well.

2005 Nov 06 [ Sun ]

How to repeat a long filespec in a command line

I have been looking for how to do this for *years*. You often have to change the name of a file in another directory. That's easy in Windows, but in Unix you have to key in the whole blasted filespec again (and hope you don't make a typo): mv /home/d/dannyw/blosxom/data/images/phnompenhtrip/crossing1.jpg... aaagh, I can't go on.

In a Linux journal article on the *bash* shell, I found this:

www.linuxjournal.com [http://www.linuxjournal.com/article/7385]

echo {one,two,three}fish
 onefish twofish threefish
echo /etc/httpd/conf/httpd.conf{,.bak}
 /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.bak

Those are *wiggly* brackets, and they create *multiple* parameters to your command line, so you can do something like:

mv /etc/httpd/conf/httpd.conf{,.bak}
mv /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.bak

I tried it under tcsh, and it still worked.

Perfecto! If only I can remember it!

2005 Sep 03 [ Sat ]

WinFS -- analogy to user interface design for apps

Apparently WinFS, although it will not actually be included in Longhorn, does indeed provide a "database-like" interface to files. Instead of allowing only one tree structure, a file can be accessed by multiple paths, assuming they are all relevant.

This issue even affects me on this site. If for instance I find a Perl program which automagically finds word breaks in Cambodian, do I put it under Perl or under Khmer-language? It should really be accessible either way.

Last week I realized that there is an analogous issue in user interface design for apps. Specifically, it took me ages to find certain functions – not I think especially arcane ones either.

For instance, I wanted to figure out how to set Excel to always display the row and column with the record and field labels. I started off trying to do something like "column lock", but that means "do not edit this column", not "lock this column's position on the screen". Eventually I found it under "Window – split" (if I remember rightly – I make no claims to be an Excel guru, so stop laughing).

I had similar experiences with Corel Draw and Mozilla.

I don't say it's clear to me how a user interface which would allow what I want should look like. Evidently you don't want the user interface to be even more cluttered than it is now. Also, there would be some risk of confusion between slightly different options when reached by different paths.

Perhaps it would be a separate, sort of "search" interface. It has just occurred to me it would look a little bit like the blasted "Clippy" interface, but if it was just for looking for nodes in the user interface maybe it would be a little more successful. Anyhow, it would allow a search term like "lock", which happens to have a specific meaning inside Excel, to also act as an entry point for *all* its common meanings, eg including "lock in place".

2005 Jul 07 [ Thu ]

The Phrack guide to hacking VMS

www.phrack.org [http://www.phrack.org/phrack/27/P27-06]

it's hardly comprehensive but gives you a few ideas.

I was struck by the revelation that (according to Phrack) groups are handled in VMS by *giving everyone who needs to use the group the password for the group*. Incredible. If Microsoft tried to do something like that they would be ridiculed (even more than now).

2005 Mar 23 [ Wed ]

Nifty app helps you experiment with regexes

A regex is the feature of many programming languages that makes it relatively easy to set up an expression to search/replace strings of characters.

Unless you a regexp guru, you will need to try out many test cases to be sure your new regexp is really working. There's a very interesting free app for Windows and Linux which makes this testing much easier: www.weitz.de [http://www.weitz.de/regex-coach/]

2 MB download.

There are different versions of regex syntax for different languages. This app follows PCRE, ie "Perl-compatible regular expressions", provided for several other languages, not just Perl.

2005 Mar 14 [ Mon ]

Storing XML in databases

Many years ago I was doing a project involving XML and the prof urged me to consider a native-XML database product which he was connected with.

As it happens I was also doing SQL courses and I told him rather snootily that I couldn't see the point of storing data in XML because it would make retrieving the data far less efficient, or even impossible if XML features were used which did not map well to the relational model. (I think my actual words included some four letters long.) He sighed. I was a fool: at the time XML was a hot buzzword and if I had combined it with "database" I could have gotten a guru-level job. (I now realize that a lot of the people in the computer biz who were selling snake oil at that time *knew* it was snake oil – but I was a trusting, naive type at that time.) I liked the professor; I probably should have told him what my judgement was and just asked him if he needed me to work on it for the sake of the database product anyway... oh well.

Slashdot has an article on native-XML database issue: developers.slashdot.org [http://developers.slashdot.org/developers/05/03/10/2043202.shtml]

People talk about "the overhead of wrapping and unwrapping the data" because your app may well be taking XML-formatted data from the client and sending XML-formatted data back, but I think the overhead of that scales much better than the overhead of running a query on the database in the middle.

2005 Feb 22 [ Tue ]

Handy piece of Javascript sample code

In the course of a Slashdot discussion on a new trick for creating popunders which is not detected by existing blockers, someone provided a listing of the actual Javascript code used which shows off many JS features which are generally useful:

Re:How it mostly works (Score:4, Interesting) by querencia (625880) on Sunday February 20, @10:27PM (#11732775) slashdot.org [http://slashdot.org/comments.pl?sid=140115&cid=11732775]

Here's another one: note how they split the string in the "write" call up so that the browser can't detect the javascript just by examining the original script:

<! –  FASTCLICK. COM POP-UNDER CODE v1.8 for spacedaily.com (12 hour)  – >
<script language="javascript"><! – 
var dc=document; var date_ob=new Date();
dc.cookie='h2=o; path=/;';var bust=date_ob.getSeconds();
if(dc.cookie.indexOf(' e=llo') <= 0 && dc.cookie.indexOf('2=o') > 0){
dc.write('<scr'+'ipt language="javascript" src="xttp://media.fastclick.net');
dc.write('/w/p op.cgi?sid=8288&m=2&tp=2&v=1.8&c='+bust+'"></scr'+ 'ipt>');
date_ob.setTime(date_ob.getTime()+432000 00);
dc.cookie='he=llo; path=/; expires='+ date_ob.toGMTString();} //  – >
</script>
<! –  FASTCLICK. COM POP-UNDER CODE v1.8 for spacedaily.com  – >  

I changed "http" to "xttp" to prevent the url being rendered as a link on my page.

Right after the above posting is one from a Proxomitron user who provides a regex which can be added to your Proxomitron setup to catch this problem among others: slashdot.org [http://slashdot.org/comments.pl?sid=140115&cid=11734433]

Proxomitron is no longer being worked on, but is still available on the net. Because it is regex-based, it is easily extensible to catch new problems without needing updated versions. I installed it on a few internet-cafe machines, but was never able to explain why it was useful to the Cambodian staff. I think they let me do it because I was a good customer, but I think they would have let me install a keylogger too.

2004 Nov 25 [ Thu ]

How many hours of work per week is too much?

When I was a lad I naively expected that weekly hours worked would continue to fall, as it had been doing for a hundred years. Instead, it started to rise, along with a cultural imperative that said you had to *look* like you were driving yourself beyond human limits just to avoid getting fired.

Somebody on Slashdot probably agrees that this is a bad thing:

Re:Well, it can be done. But can it be done well? (Score:5, Informative) by Wavicle (181176) on Wednesday November 24, @08:25PM (#10914805) ask.slashdot.org [http://ask.slashdot.org/comments.pl?sid=130722&cid=10914805]

An interesting footnote on this whole "hours of time coding" issue...

The world's largest privately held software company is a company called SAS in North Carolina. Their software is basically an environment for doing statistical analysis. Regression, multiple regression, correlation, wilcoxon rank tests, and a slew of other things I haven't got to yet. But the important part is, if you were going to do a study to figure out the "optimal" amount of time to work, and consider not just productivity from the programmer, but all sorts of correlated variables (will someone work 80 hours/week for 10 years? How much will it cost to recruit and train a newbie when someone burns out?) then you would probably use a program like SAS to analyze the data. This is a company that has plenty of computer science and statistics Ph.D. 's on staff.

Their conclusion? 35 hours per week. Keeps the productivity high, the turn over low, and the company growing at double digit rates nearly every year (or maybe it has been every year).

Something to think about during your next interview cycle.

On the other hand, it reminds me of the ingenious way the creators of Unix hid the secret to the password encryption algorithm inside the C compiler. Maybe the overworked drones at SAS built in code to detect queries about SAS employee working hours!

2004 Oct 07 [ Thu ]

Link to PHP manual

I have downloaded a PHP manual in HTML form, but when I saw a link to PHP docs I thought I should add a link to my site.

www.php.net [http://www.php.net/download-docs.php]

Note that this version presumably provides you with docs for the *current* (latest) version. Many people are still working with some rev of v4 (as this is what is provided by hosting sites, and is the version for which most sample code is available) and I don't see how to find docs for that.

2004 Sep 09 [ Thu ]

Trial versions of database servers available for free download

A Slashdot discussion of the recwent announcement that Sybase is now available as a free download: linux.slashdot.org [http://linux.slashdot.org/linux/04/09/09/0556229.shtml] included various links to free downloads of other database products which I would like to include here:

Sybase: www.sybase.com [http://www.sybase.com/linuxpromo]

MSDE (Microsoft SQL Developer's Edition, 70 MB): www.asp.net [http://www.asp.net/msde/default.aspx?tabindex=0&tabid=1]

Another page with a different version of MS SQL? (SQL Server Express 2005 Beta) lab.msdn.microsoft.com [http://lab.msdn.microsoft.com/express/sql/Features/default.aspx]

Linux, Windows, Solaris, Mac versions of Oracle 10g: www.oracle.com [http://www.oracle.com/technology/software/products/database/oracle10g/index.html]

(Hmm, the Oracle links did not seem to work for me. Maybe they need Active X enabled in the browser or something.)

I did not make the effort to analyze the legal restrictions. Various posters, for various products, talked about "5 GB", "1 instance", "1 CPU", "1 GB RAM" . These may be significant for your eventual application, but they sound like they should be no problem for programmers and sysadmins who just want to get experience installing and using them.

2004 Sep 03 [ Fri ]

Using Microsoft Access to handle data on a MySQL server

Several years ago I set up a Red Hat server – I think 7.1 – so that a Windows client running Access 97 could use the data. I used the MyODBC software, in conjunction with Microsoft's built-in ODBC support (actually, it's built in now, but I had to download it for Windows 98 before, if I remember rightly).

Anyhow, I don't remember any large problems with it. As it was the first time I'd ever used ODBC, there were some general misunderstandings about what was really going on, but I don't remember actual bugs or glitches. In fact, I felt pretty amazed. The only worry I had was security: I'm still not sure how to handle user accounts (eg if you disable a Windows user maybe their credentials still work on the MySQL box).

Still, I was interested to read the following article about getting ODBC installed under Linux so that it can be accessed from Open Office; he sure had to struggle: www.linuxworld.com [http://www.linuxworld.com/story/32629.htm]

2004 Aug 17 [ Tue ]

A couple of hints on perl

While reading a Slashdot discussion I came across this snippet:

perl -MMP3::Splitter -e 'mp3_split($_,{},[ rand(64800), 30 ], ...) for @ARGV' filename.mp3

The slightly arcane use for this is to snip up a lengthy MP3 file into multiple short sections, for a researcher.

This may make me sound extremely lame, but I have to admit that I do not use perl often enough to keep all these nifty shortcuts in mind. However I certainly wish I could; at any rate I want to note how the above line actually works.

1. The -M switch means "load the module of this name". There is no space after this switch. It is just a confusing coincidence that the name of this particular module also starts with "M" . You can use a standard "use" statement of course, but that means your program has more than one line, which probably screws up the nifty automated command-line features of perl that you wanted to use.

2. The syntax around "mp3_split" is set by that particular module and thus not generally relevant.

3. The "for @ARGV" is great. It's a neat way of simultaneously grabbing filenames from the command line and feeding their contents to the function.

Here's a simpler demo, although even less useful. It assumes you have several files in the current directory named like slash1.txt, slash2.txt, and prints out "A file" for each one:

perl -e 'print "A file\n" for @ARGV' slash*

2004 Jul 30 [ Fri ]

Link to teach-yourself-sh guide on the web

I feel embarrassed to admit this but when I need to do a shell script I often realize that I have forgotten some essential trick. Because the shell tends to use very short and/or common keywords, it's very difficult to search for terms like "if" or "return" to check syntax/usage. (I get mixed up between sh, csh and bash, also perl of course; sometimes I try syntax which *appears* to work but is actually doing something quite different from what I intended...)

So the most efective thing is probably to check out general beginner-level guides now and then. Criminy, I've done most of this stuff n times before, honestly – but I learn something new every time.

steve-parker.org [http://steve-parker.org/sh/sh.shtml] Nicely-formatted, and with clear useful examples. I noticed bigwebmaster.com and librenix.com both linked to it.

2004 May 02 [ Sun ]

How to find what Perl modules are installed on your system

A lot of the Perl docs seem to assume you are the admin of your box, but that sure isn't the case for me at panix.

For instance, how do you list what Perl modules are installed already, so you can go beat up on the sysadmin? I keep forgetting the trick for doing this, so this time I went and found it by doing "perldoc perlmodlib", from which the following is quoted:

To find out all the modules installed on your system, including those without documentation or outside the standard release, do this:

 % find `perl -e 'print "@INC"'` -name '*.pm' -print 

They should all have their own documentation installed and accessible via your system man(1) command. If that fails, try the perldoc program.

Of course, if I was a *real* Perl programmer, the above would be *obvious*. Btw, if you don't cut-and-paste this, be careful to distinguish backticks from quotes; the first three such symbols on the line are backtick, single quote and double quote. Also, if you're a real beginner: this line will only work in Unix, not in Windows. (ActiveState Perl for Windows comes with excellent documentation for the standard installed modules, but I don't know how to list the currently installed modules in ActiveState.)

Incidentally, this lists a *huge* number of .pm files, in no particular order. I would suggest you pipe into "less", thus:

 % find `perl -e 'print "@INC"'` -name '*.pm' -print | less

2004 Apr 26 [ Mon ]

Tips on using the Unix command line -- syntax for "locate" utility

The "locate" utility uses a prebuilt database to rapidly find filenames anywhere on the system. Clearly it depends on a recent database. Also, the database frequently is generated without following symbolic links (which might well be circular, or otherwise result in gigantic numbers of files0; and the many security issues mean it is often disabled for non-root users.

Oh well. If you *can* use it, you may run into this syntax issue.

I'd often tried to use commands of the form

locate stuff.*
but they didn't seem to work.

Commands of this form work:

locate stuff
and return stuff.c, stuff/some.txt, /home/danny/stuff.001/some.txt etc, but don't give much control to reject the stuff you don't need.

Of course the * needs to be hidden from the shell:

locate "stuff.*"
but that does not work either, because when a wildcard is used the non-wildcard characters have to match *exactly* – so in this case it will not even find "stuff.c" in the current directory (because "locate" stores all its locations in absolute form, and does not compare relative to the current directory).

Instead what you have to do is:

locate "*stuff.*"

Tips on using the Unix command line -- Fixing a broken shell

Whenever I get an account on a new Unix system it usually turns out that the action of the backspace key is messed up. The reason for this is that Emacs has a default configuration which is both terrible and impossible to understand, and the original installer spends weeks finding one issue after another, whether inside Emacs or at the shell level; when he winds up with a configuration that works for him, he never wants to mess with it, even if it's screwed up for everyone else.

The result is that I have to dink around with various shell config changes till I get it right, and sometimes I wind up with a hosed shell. This is something that worked for me using bash, when I found a "magical" snippet of code in the default shell config. I tried editing .bashrc: I added "stty ek" to run after the funny code which seemed to cause the problem: it resets erase and kill key handling to default, and seemed to do what I want for vi, at least.

Tips on using the Unix command line -- Acting on a list of files

I wanted to listen to a bunch of sound files, all of which were quite short. Eventually I used "find" to put a list of NL-separated sound filenames in audio.dat); the trick for converting filenames into *arguments* is one that took some head-scratching. It's the "$()" below:

cat $(cat audio.dat) > /dev/audio

This is actually an overcomplex example. I only needed to use "find" because there were sound files in multiple subdirs, and I wanted to pick up the full pathnames. Likewise, if you don't know how the linux /dev/audio device works, just catting a binary sound file to it will look a little confusing.

Here's a simpler example, though less useful. Suppose you wanted to concatenate a bunch of files whose filenames were in a file called orange.txt. You could do:

cat $(cat orange.txt) > compendium.txt

This example, it occurs to me, is probably also a little confusing. The "cat" program is being used in two different ways: just to copy orange.txt to standard output; and then to truly concatenate the files defined in orange.txt. Oh well; I suppose most people who can see the usefulness of this tip at all already grok cat.

(It also occurs to me I could have done a find -exec, but that's always so clumsy; this seems better. Also, because it works with a pre-generated file listing, it avoids long pauses in the sound output if "find" takes a while to find the next file.)

When I checked, csh did not like the "$()" syntax, but it worked in sh and bash.

2004 Apr 20 [ Tue ]

Perl tip: using modules on a server where you are not root

A lot of the documentation for Perl modules assumes that you're the administrator for the box you're installing the module on. But very often (like me) you want to run your site on a hosted system, so you can't install the module into the place it expects.

This is a compilation of notes on this process that I've picked up in various places. Some of it was already in my jumbled "links" folder, but the formatting was not good. On the other hand, I lost track of who was quoting who, so some of the attributions are missing or unclear.

General notes on using Perl modules

1. Perl -e "print qq(@INC);" shows where perl searches for modules

You may be lucky: your admin may already have set up some sort of link to your home directory. However, remember that the webserver does not get a copy of your environment, so your cgi may still not work!

2. Perl Makefile.PL PREFIX=~/perl to install a user library in /home/poindexter/perl (then do the usual "make; make test; make install"). Also see perldoc ExtUtils::MakeMaker

3. This is not really about *installing* modules, but I just wanted to remind *myself* that the docs are there. In particular, note that you need to specify CSV as a subsection of the module.

Perldoc DBI;

perldoc DBD::CSV

4. push(@INC, "/usr/lib/bliv/");

This can be used inside your program to cause it to search some additional directory for modules. Note again that if this gets run by the webserver, it won't grok your *user* environment variables (well, maybe it will, but don't trust it).

5. Adding module directories at the perl command line (useful for debugging):

Use -I switch to add one dir to library search path (repeat for more than one):

-I /usr/danny -I /usr/local/test1

Info on installing modules from CPAN

search.cpan.org [http://search.cpan.org/src/SPOON/WWW-Shorten-1.5.7/INSTALL]

The readme for this perl module includes advice for installing modules as non-root which seems to be quite general, so I'm going to note it here:

The 'make install' (done later) will install the modules and scripts on your system. You may need administrator privileges to perform this task. Alternately you can can install the module to a local directory (see ExtUtils::MakeMaker for full details), e.g.

% perl Makefile.PL PREFIX=/home/abw/

Don't forget to update your PERL5LIB environment variable if you do this, or add a line to your script to tell Perl where to find the files, e.g.

use lib qw( /home/abw/lib/perl5/site_perl/5.6.0 );

If you're not after a custom location, just do:

% perl Makefile.PL

To install this module into a specific directory (if, for example, you are a non-root user) instead do:

% perl Makefile.PL PREFIX=/name/of/the/directory

Another take on installing modules

world.std.com [http://world.std.com/~swmcd/steven/perl/module_mechanics.html#TOC24.5]

On many systems, /usr/local/lib/perl5/site_perl is owned by root with 0755 permissions. This means that you must su to root in order to install a module there. If you lack root on your system, you can ask your system administrator to install the module for you install the module somewhere else

Here's how to install a Perl module in a non-standard place.

First, create a directory to hold the module. It doesn't strictly matter where the directory is located, but it must be somewhere that you have write access that won't go away.

Your home directory is probably a good choice; /usr/tmp is probably not. We'll write /home/uid/ for your home directory. It doesn't matter what you call the directory. I would suggest /home/uid/lib/perl. Then go back to the development directory and type

./development>perl Makefile.PL LIB=/home/uid/lib/perl

./development>make install

This will build the module and install it in your private directory.

PERLLIB

Perl doesn't know to look for modules in your private directory; you have to tell it. There are several ways to do this. Perhaps the most appropriate in this context is to set the PERLLIB environment variable.

From the perlrun POD:

PERLLIB A colon-separated list of directories in which to look for Perl library files before looking in the standard library and the current directory.

Testing a module from a Perl program

Sometimes, you want to test a module by running a program that actually uses it. If the module is installed, this is easy enough, but what if the module isn't installed? Somehow, you have to get the program to find the .pm file in the development directory.

This used to require playing complicated games with @INC or use lib, but as of Perl 5.004, there's a much simpler way: use blib. blib is (what else?) a Perl module. From the perldelta.pod:

use blib 'dir'

Looks for MakeMaker-like 'blib' directory structure starting in dir (or current directory) and working back up to five levels of parent directories.

Intended for use on command line with -M option as a way of testing arbitrary scripts against an uninstalled version of a package.

The following is from the same site, and looks like it has a lot of uses . I think I'd like to do something like this for a lot of editing purposes, eg updating filedates etc:

Web Pages

The build procedure for a Perl module does not create a .html version of the POD. It's easy enough to do by hand, but, again, you get tired of all the typing. I put the following in my .bashrc file:

WEB_ROOT='/usr/www/html' PERL_LIB='Perl/Lib' 
pmweb () { if [ -z $1 ] then 
echo No destination; 
return; 
fi; 
pod2html *.pm; 
chmod 444 *.html; 
mv -f *.html $WEB_ROOT/$PERL_LIB/$1/ } 

With these defines, I can type

pmweb Foo

in the build directory, and bar.html will be created and moved to the appropriate directory.

2004 Jan 27 [ Tue ]

Perlmonks.org -- good free site for perl info

I particularly like their tutorials, eg several on HTML::template, such as this: www.perlmonks.org [http://www.perlmonks.org/index.pl?node_id=65642]

2004 Jan 01 [ Thu ]

Good references for Unix/Windows shell programming

A Slashdot discussion on a book about Unix shell programming wound up with a lot of good links to general Unix and Windows shell programming.

The Slashdot discussion: books.slashdot.org [http://books.slashdot.org/books/03/12/31/1653210.shtml]

Advanced Bash-scripting Guide: www.tldp.org [http://www.tldp.org/LDP/abs/html/]

Differences between Unix shells eg bash, csh, tcsh etc: www.faqs.org [http://www.faqs.org/faqs/unix-faq/shell/shell-differences/]

Gnu utilities compiled to run under Windows: unxutils.sourceforge.net [http://unxutils.sourceforge.net/] (note: this is not Cygwin, which provides a special Unix-like shell under Windows for running its utilities)

2003 Dec 26 [ Fri ]

Cute list of MySQL "gotchas"

I've used MySQL and it's impressive, but one particular application that was written to work with MySQL or Oracle seemed to have a lot of nagging integrity issues with MySQL that didn't happen with Oracle.

Here's a list of "gotchas" – not exactly bugs: sql-info.de [http://sql-info.de/mysql/gotchas.html]

2003 Oct 04 [ Sat ]

Programming Perl/Tk

I created a "hello world" program – well, created is a little boastful considering I copied it out of a book – about 8 years ago, using Perl/Tk. I dinked with it for a while longer – I wanted to make a GUI interface to some file utilities, because I had always forgotten how to use them when I needed to use them again; I got it more or less connected up to the original code but there was some important detail I never figured out.

Oh well. The following page is a good intro to Perl/Tk: www-106.ibm.com [http://www-106.ibm.com/developerworks/linux/library/l-datavis/?ca=dgr-lnxw10UsingPerl/Tk]

[Single-story view] [/Computers/Programming/Perl] [permanent link]
Responses: 1
Name/Blog: Smurf The Lesser
URL:
Title: Test 6
Comment/Excerpt: Lovely stuff and nonsense [View/add responses]
2003 Sep 29 [ Mon ]

Sample code for use on an internal webpage

Most web servers are used for the public and therefore the system does not have an "authenticated user" name which can be accessed by scripts.

The following posting on Slashdot illustrates what can be done on an internal Windows server, where IIS is aware of the Windows logon name of the user. Here, it's just used for a prank: a certain user gets a joke image, and all other users get an innocuous image.

ask.slashdot.org [http://ask.slashdot.org/comments.pl?sid=80131&cid=7071926]

He gives two versions, one with basic code and the other with php. It works as a redirect – I'm not sure why (something to do with his original plan to add the image to the victim's Outlook signature).

<%
embarrassing_image = "embarrassing_image.png"
fake_image = "white_one_pixel_square.png"
userfull = Request.ServerVariables("LOGON_USER")
look = inStr (1, userfull, "user_to_goof",1)
If 1 > look Then _
Response.Redirect (embarrassing_image) _
else _
Response.Redirect (fake_image) _
end if
%>

<?php $embarrassing_image = "embarrassing_image.png"; $fake_image = "white_one_pixel_square.png"; $userfull = $_SERVER["LOGON_USER"]; if (eregi ("user_to_goof", $userfull)) { header ("Location: " . $embarrassing_image); } else { header ("Location: " . $fake_image); } ?>

2003 Sep 24 [ Wed ]

Various Perl stuff taken mostly from my jumbled "Links" folder

The Perl Object Environment (POE) module for perl

www.perl.com [http://www.perl.com/pub/a/2001/01/poe.html]

Interesting approach to setting up persistent services. Basically you just set up a nunch of handlers and then POE provides the main loop which waits for events.

search.cpan.org [http://search.cpan.org/src/SPOON/WWW-Shorten-1.5.7/INSTALL]

The readme for this perl module includes advice for installing modules as non-root which seems to be quite general, so I'm going to note it here:

The 'make install' (done later) will install the modules and scripts on your system. You may need administrator privileges to perform this task. Alternately you can can install the module to a local directory (see ExtUtils::MakeMaker for full details), e.g.

% perl Makefile.PL PREFIX=/home/abw/

Don't forget to update your PERL5LIB environment variable if you do this, or add a line to your script to tell Perl where to find the files, e.g.

use lib qw( /home/abw/lib/perl5/site_perl/5.6.0 );

If you're not after a custom location, just do:

% perl Makefile.PL

To install this module into a specific directory (if, for example, you are a non-root user) instead do:

% perl Makefile.PL PREFIX=/name/of/the/directory

Perl compiler for Windows

www.indigostar.com [http://www.indigostar.com/perl2exe.htm]

It's funny, I had been looking for this utility in a desultory fashion for a long time. It wasn't till I stumbled across it that I could check it out. Maybe that means it's not very good – if it has no “buzz”? Of course real perlers use a Unix server.

Perl2Exe Lite for Win32 $49 US per copy Generates executables for Windows This is a package that supports the following Win32 versions of Perl: IndigoPerl, ActivePerl, Standard Perl, and ActiveState Perl Perl2Exe Pro for Win32 $149 US per copy Generates executables for Windows This is a package that supports the following Win32 versions of Perl: IndigoPerl, ActivePerl, Standard Perl, and ActiveState Perl Support for the -smal & -tiny options for creating smaller exe's Support for the -gui option for creating no-console applications Priority technical support

It's not clear to me if the cheapo $49 version can produce a GUI executable at all; I suspect not. You presumably have to spring for the $149 version.

They have umpteen other packages available, eg executable in Solaris, etc.

Here's another take on installing Perl in a non-standard place (ie because you're a non-root user).

world.std.com/~swmcd/steven/perl/module_mechanics.html#TOC24.5

Installing in non-standard places On many systems, /usr/local/lib/perl5/site_perl is owned by root with 0755 permissions. This means that you must su to root in order to install a module there. If you lack root on your system, you can ask your system administrator to install the module for you install the module somewhere else

Here's how to install a Perl module in a non-standard place.

First, create a directory to hold the module. It doesn't strictly matter where the directory is located, but it must be somewhere that you have write access won't go away

Your home directory is probably a good choice; /usr/tmp is probably not. We'll write /home/uid/ for your home directory. It doesn't matter what you call the directory. I would suggest /home/uid/lib/perl Then go back to the development directory and type

…/development>perl Makefile.PL LIB=/home/uid/lib/perl …/development>make install

This will build the module and install it in your private directory.

PERLLIB Perl doesn't know to look for modules in your private directory; you have to tell it. There are several ways to do this. Perhaps the most appropriate in this context is to set the PERLLIB environment variable. From the perlrun POD:

PERLLIB A colon-separated list of directories in which to look for Perl library files before looking in the standard library and the current directory.

Testing a module from a Perl program

Sometimes, you want to test a module by running a program that actually uses it. If the module is installed, this is easy enough, but what if the module isn't installed? Somehow, you have to get the program to find the .pm file in the development directory.

This used to require playing complicated games with @INC or use lib, but as of Perl 5.004, there's a much simpler way: use blib. blib is (what else?) a Perl module. From the perldelta.pod:

use blib use blib 'dir' Looks for MakeMaker-like 'blib' directory structure starting in dir (or current directory) and working back up to five levels of parent directories.

Intended for use on command line with -M option as a way of testing arbitrary scripts against an uninstalled version of a package.

The following is from the same site, and looks like it has a lot of uses – I think I'd like to do something like this for a lot of editing purposes, eg updating filedates etc:

Web Pages The build procedure for a Perl module does not create a .html version of the POD. It's easy enough to do by hand, but, again, you get tired of all the typing. I put the following in my .bashrc file:

WEB_ROOT='/usr/www/html' PERL_LIB='Perl/Lib'

pmweb () { if [ -z $1 ] then echo No destination; return; fi; pod2html *.pm; chmod 444 *.html; mv -f *.html $WEB_ROOT/$PERL_LIB/$1/ }

With these defines, I can type

pmweb Foo

in the build directory, and bar.html will be created and moved to the appropriate directory



I hope this information was useful. There may be a great deal more information on this site that is relevant to what you need. Take a look at the "site map" display at left; you can click on a topic to see many recent items on that topic.

Debug: hittotal: 28 startban: 0 dancookie: endbandate: banned: 0 tempdate: tert: jse: jsno jsh: 28