Saturday, November 28, 2009

Unzipping a file using PHP

The correct way is to use the unzip library but there are various problems with that approach that I won't harp on here. Another correct way is to use

exec("unzip /path/to/file.zip");

but I have found some zip files that the unix unzip command can't handle but that the mac os x built-in archive utility has no problem with. So I came up a simple, but goofy approach:

use php exec() to call an applescript which tells finder to open the file with archive utility, using a keyboard shortcut.

PHP blah.php
exec('osascript /applications/mamp/htdocs/zipfolder/asunzip.scpt');

APPLESCRIPT asunzip.scpt

tell application "Finder"
activate
end tell

tell application "System Events"
tell process "Finder"
key code 125 — down arrow
keystroke "z" using command down
end tell
end tell

KEYBOARD SHORTCUT - application-specific (system preferences)
command z is pulling file -> open with -> archive utility out of finder toolbar

———————————Addendum———————————————————

Here is a better AppleScript that does the same thing. But instead of bringing Finder to the forefront, then using down arrows to navigate to a file, and then using a keyboard shortcut to open it, it just directly opens the file by name quietly in the background:

set filepath to POSIX path of "Macintosh HD:Applications:MAMP:htdocs:zipfolder:neworig.zip"
application
try
set command to "open " & quoted form of filepath
do shell script command
end try

Sunday, November 8, 2009

PHP mail() bug? or feature?

PHP mail bug

I use the php mail() function to create lengthy html emails. The $message is a long string, up to 5000 characters, or more, long. Well, it turns that either the mail() function or the mail server at the other end has a character limit of 990 per string. If you exceed that, something automatically inserts 0D 0A 20 into the string (CR LF Space) every 990 characters, so that now the email conforms to the "rule." No crash, but every 990 characters you see a space inserted in the middle of words, or if the space lands in a tag, you have screwed up your message format.

The fix: create a function that takes your $message string, and inserts 0D 0A 20 more frequently than every 990 characters where there normally is just a space (20). (20 is hex ascii for space - used a hex editor to debug this thing). If your message is html, html ignores CR LF in strings, so inserting this causes no problems. Then, after applying that function, use

mail( $to, $subject, $message, $headers );

on the modified $message, and it goes through without the problem!

Mac Shortcut of the Day
I really like the Safari "Bookmark Bar" across the top of the toolbar for quickly clicking to favorite sites. As if that wasn't good enough already, try holding the command key down while clicking a book mark. This gives you a new tab in your Safari window AND jumps you to your favorite site in one click.

Saturday, November 7, 2009

I am a mac person now

I made the big switch about a month ago and I have never looked back. Virtually everything I used to do using computers I can do better now that I finally have a mac. I have Snow Leopard and haven't come up with any major problems yet. I am printing wirelessly three printers ( direct via bluetooth at home, direct via Wi-Fi (router attached to printer) at work, and via smb to another networked printer at work. The latter two were trickey: direct via Wi-Fi you have to find out the printer's IP address, and to find that out you have to hold down one of the printer's buttons to make it print it's identifying information, including the IP address. For the networked printer, even trickier. You have to find out the URL of the printer on the network and translate it into a format mac understands: in my case it is smb://xxx-03.yyy.phy/HPLaserJ. (That's the networked computer name/PrinterName) I needed to download Snow Leopard drivers for the first two printers; for the third, no driver needed since it is a shared printer.

Other fun things I have learned: Snow Leopard has a built-in VNC client, which means that with the free app VNC Lite I can see and control everything on the mac desktop over the Wi-Fi network on the screen of the iphone. in fact, I just typed this sentence using VNC on the iphone. It is useful if I want to dicate into MacSpeech Dictate using my wearable wireless microphone while in a different room from the Mac. I can still watch the words pop up on the iphone via VNC. Woo.

More great stuff: Mac Mail Rules and Applescript. You can define Rules for mail that act like powerful little macros and the rules can invoke Applescript scripts. Since mobile me email is "push", I can write php scripts on my MAMP server, and run the scripts remotely using the iphone, which results in pushing commands to the mac via mobile me -> via rules -> via applescript. In this manner I can print customized documents to a crisp laser printer right off of my iphone, and I can alter the content of document by entering the data on the phone via MAMP, and the php script handles the formatting (because it's html email with formatting tags). Two big helps on this: (1) Get rid of the unwanted headers (Mail->Preferences->Viewing->Show Header Details->None. (2) Rules run on the mac BEFORE the mail message that triggers the rule is delivered. So send a second mail message with the actual command in the subject line AFTER the HTML message is received (in php: sleep(1); makes the script wait just long enough to work) .

I'll mention a few more things in less detail: Finder -> Command-K is similar to Windows Key-R for connecting to servers: but instead of \\servername use smb://servername. When adding printers, remember to click the plus sign and then control-click the menu bar to get the option to customize the menu bar by adding the "Settings" icon. Built-in Automator macro app. Publishing your iCal calendar on-line for integration into your family's various calendars on their iCals (and iphones via mobile me). Time machine. Backup. The keyboard shortcuts under System Preferences -> Language and Text AND System Preferences -> Keyboard.

In short, it's a whole new world and a better one. Wow.

Sunday, August 9, 2009

Sync iPhone Calendar to Windows

The iPhone Calendar famously does not sync with most Windows Calendar applications directly. Here is the solution that I found: Set up a Google Calendar account, then go into iPhone Settings -> mail,contacts,calendars -> add account -> Microsoft Exchange. Then enter your email address in both the email and username fields, leave domain blank, enter google password and hit next. It then brings up the same fields with the addition of server, and you enter m.google.com there and hit next again. Then what I did is turn calendar sync on, and turn contacts and mail sync off in this account, because I already have functioning accouts for those. Now if I enter something on my iPhone calendar, I can see it pop up on my PC in the browser in Google Calendar.

The only sidebar is that since it is not on the physical PC, and it is the physical PC that syncronizes with the Mobile Me "Cloud", it doesn't appear in the Mobile Me Calendar. But the Google Calendar is in another "Cloud", so it is accessible from anywhere and it could function as a backup just as well.

Saturday, August 8, 2009

Gadget Consolidation

I am now entering a new phase of life with the purchase of my first iPhone, which can take over the functions of the following gadgets that I carry around:

Cell phone
Alphanumeric pager
Digital camera
MP3 player
Dictaphone
Palm Pilot: Calendar, Contacts, Memos, Tasks, ePocrates, Password vault
GPS unit
Netbook / Wireless Data Service

It's a little risky putting all those eggs in one basket, but I'll try to take good care of it, and back it up two ways always (Sync to PC via iTunes software and Sync to Cloud via MobileME).

Macro Program to Automate Complex Tasks

I found what appears to be a very good Macro Program: AutoHotKey. (For Windows XP and Vista). You run the AutoHotKey.exe program in the background and the macros are text files with the extension .ahk which you run by double clicking them. The program runs silently in the background and the scripts are run by pressing the hotkey. The examples below are self-explanatory:

;comment - WindowsKey+Z
#z::Run www.google.com

;comment - CTR+ALT+N
^!n::
IfWinExist Untitled - Notepad
WinActivate
else
Run Notepad
return

It comes with an indexed help file that explains thousands of details such as WinMaximize, MouseMove, and the various Send commands for keystrokes. And there is an online forum with a lively following. Price: Free.

Wednesday, July 22, 2009

HTTP POST Method: Finding the data on the receiving end

This is regarding FINDING the POSTed data with a PHP script. Where is it? Why do I keep coming up with NULL values when I look where it is supposed to be? Well, it depends on how the data was posted, and if some other site is posting the data you really don't know which method they will use. Here are the first three places to look:

print_r($_POST);

if(!isset($HTTP_RAW_POST_DATA)) $rawpost = file_get_contents( 'php://input' );

echo $GLOBALS['HTTP_RAW_POST_DATA'];

There are more places to hunt, but so far these three have worked for me.

PS With the second method above, when receiving XML, you end up with \" for every ", which can mess you up. Try following up with

$cleanpost = str_replace( '\"', '"', $rawpost );

Monday, July 20, 2009

My favorite PHP Class: SimpleXMLElement

1. A lot effort has been expended by countless people to convert XML into PHP arrays. There are countless forum discussions on the subject and many complex scripts to accomplish this task.

But there is something better.

$xml = simplexml_load_string($str);

One line of code converts an XML string to an object of class SimpleXMLElement. Then you can access any individual data element within the object simply by calling the surrounding tags (skipping the outermost [message] tags):

$xml->body->layer1->layer2->layer3

2. It is very useful for debugging objects to have a way of examining the object structure, datatypes, and content. The very useful function for this is var_dump($obj); which lays everything out for you (kind of like print_r($arr); for arrays).

3. Another strange discovery I have made is that instead of enclosing lenghty XML strings in quotes or double quotes, it is possible to dispense with the quotes altogether and enclose it with XML preceded by three "less-than" signs on one end and XML on the other end. I am not sure why this is so or what the ramifications are of this, but it looks like a very useful option.

Monday, July 6, 2009

PHP Shortcut of the Day

Normally in PHP you concatenate two strings like this:

$str1 = $str1.$str2;

This adds $str2 to the end of $str1. Here's a handy shortcut, which when constructing really huge XML strings is highly useful:

$str1 .= $str2;

The "dot-equals" operation is even smart and will let you concatenate to a null string at the beginning, which is a good thing when you are in loops. You can't do that in C ; you have to StrCopy and then StrCat. To me, this type of thing is what makes PHP great.

Here's another great PHP shortcut: the 'foreach' loop.

A foreach loop lets you loop through all the elements of an array and get access to either the individual keys and individual data elements. The syntax is:

foreach( $somearray as $key => $data ) { .... }

For multidimensional arrays you can nest foreach loops. It takes some getting used to this funny syntax, but it is very useful and worth knowing about.

HTML - JavaScript : Button Inputs as Links

Normally Button inputs in HTML post data to a destination link specified when the form is declared. Wouldn't it be nice to have multiple buttons that can post to other URL's on the same form? Most "solutions" in forums and books say create a different form for each button, but that's cumbersome and messes up your page layout. And you are not allowed to "nest" forms in HTML.

Enter JavaScript. The one line solution (for GET method): While declaring your button input include:

onClick="window.location.href='../folder/url'"

for POST method dynamically change the form "action" attribute with:

onClick="document.myform.action='../folder/url'; document.myform.submit();"

This last solution is my favorite because you can have a whole bunch of data in input fields automatically posted to whatever URL you want from just one form.

Tuesday, June 23, 2009

How to pass variables between HTML documents

The most common way is using the HTTP GET method, which is the default method when you just link to a page using (a href). The disadvantage is that your variables end up visible in the URL such as in www.google.com/search?oq=variable which can be messy and poses some security issues. Also it is sometimes difficult to dynamically change your established (a href) links with user input without a LOT of javascript code. Whatever you pass ends up in receiving document in the PHP $_GET[] array.

The next most common way is by using the HTTP POST method. However, this automaticaly POSTS all of the data in all of the input fields at once, without allowing you to specify priority based on client actions. Results end up in the $_POST[] array.

My preferred method is to set up a bunch of hidden input fields, like (input type="hidden" /) and then use JavaScript events such as onFocus, onBlur, or onClick to modify the contents and the priority of these fields. Then use the standard POST method and the contents of all these fields pops up in the next document in the PHP $_POST[] array. And you can easily debug by temporarily making these fields visible (type="text") and you can see how the javascript events modify your variables as you go in real time.

Monday, June 15, 2009

Assorted Useful Discoveries in No Particular Order

Here are a few helpful discoveries that took a lot of time to find but have saved me even more time in the end:

1. There is a PHP function that passes PHP arrays to javascript variable arrays: json_encode($array) It puts the PHP array elements in dble quotes, comma delimits them, surrounds the whole array with brackets, and puts sub-arrays into dot-delimited child elements. If only I had known a few weeks ago...

2. The current state of the art for printing web content wirelessly from an iTouch or iPhone is an app called "Print n Share" from EuroSmartz in New Zealand. I am testing it on an iTouch and it works extremely well.

3. The browser within Print n Share is a watered down Safari-Mini browser that Apple provides third party developers. As such, it lacks certain features, such as the ability to prompt users for their userid and password on secure sites. The workaround is: https://userid:password@www.website.com (I didn't know you could do that!! Actually, you can't do that with IE, for security reasons, unless you tweak your registry).

4. Apple does things in "obvious" ways that sometimes are so "obvious" they take me hours and hours to figure out. Some classic examples: How to eject a CD from a MAC. Where is the damn button?? Oh, there it is. There is an actual eject key on the keyboard !! Or here's another one: how to download an iTouch app? You generally don't do it on your computer!! That solves two hours of fruitless research. You use the "App Store" app right on your iTouch. Or, if you are installing an app that you bought yourself for another person's iTouch, how do you install it (there's the owner's password in the way)? You plug it into your USB port, go open iTunes, find the device, click on it, and then you are presented with an option to install/sync. And finally, my favorite: How to use the AC adaptor to charge it up? It wasn't obvious to me, but I guess it is intuitive to someone: you plug your USB cable directly into the AC adaptor, as if your wall socket was a USB port. Who knows? Isuppose there's data in there somewhere....

Tuesday, June 9, 2009

Networking Information

My router at work is set up as a wireless access point, with no physical connection to a PC. It is just hooked to the ethernet cable. It is configured with an encryptation key for security, and it connects to my work domain which I thought was inaccessible to XP home or Vista, until today.

I connected to the domain (yes, domain, not workgroup!) with XP home and with Vista (yes, not XP Pro) wirelessly with the following three simple steps:

1. Connect to the router using the encryptation key and verify internet connectivity.

2. While holding the "Windows Key" on the keyboard down, type the letter "R". This is the "shortcut to 'RUN' ".

3. Enter \\kap-02.companyname.phy (That's just the path to one of the domain computers).

This brings up the domain login which for me is companyname\myfirstinitialmylastname plus domain password. That's it. Then you can surf to the shared folder you need and view files. You can do this with multiple computers on the domain. I did it with a second computer with a shared laser printer. Surfed to the printer, opened it, connected, and selected it a my default printer just as if it was connected to my laptop.

If I find out the router settings I will post that. I did see that one can right click on my computer to bring up "map network drive" to assign say drive Z: to \\mydomaincomputerpath.

Sunday, June 7, 2009

iRotate from EnTech in Taiwan

Fantastic discovery! A simple application that rotates the display of any XP/Vista computer, including light-weight netbooks, to tablet-style orientation. Combine this with a Targus 2.4 GHz wireless optical mouse, and you can view documents in portrait orientation and navigate around very intuitively. You can hold the netbook sideways, like an open book, with the keyboard on the left and the screen on the right. The smaller netbooks are very light-weight and can be held very comfortably in one hand while open in this sideways orientation, like an open pamphlet. But unlike a tablet PC, you still have use of a full size real keyboard with no obstruction of the view of the document. If needed, the wireless optical mouse can be used to navigate and click even if still in your coat pocket with your free hand; or, you can take the mouse out of your pocket and move it on a desk.

So far I have just tested this with XP. The default settings work great. You end -up with hotkeys CTRL-ALT-leftarrow for rotation and CTRL_ALT-uparrow to restore, and on the MSI netbook the three keys are located conveniently together on the bottom right side of the keyboard. You can also toggle from the DOS command line as follow:

c:\Program Files\iRotate>irotate.exe /rotate=90

which got me out of a jam. (At first I had combined this application with the MSI netbook toggle for an external monitor (FN-F3) and my netbook was stuck in portrait mode). The documentation says you can control multiple moniters by editing the irotate.ini file and you can also assign the hotkeys to alternatives.
Documentation: c:\Program Files\iRotate\irotate.htm
Forum: http://forums.entechtaiwan.com

The cost: FREE.

Sunday, May 24, 2009

Built-in DOS Command-Line FTP client and DOS scripts

Did you know that there are two ways that you can use the FTP client (ftp.exe in the c:\windows\system32 directory) that comes packaged with Windows? (Yes, Vista included) This dates back to XP, Win98, and even Win95. From the DOS prompt you can type ftp to get the ftp> prompt, and from that environment you can sequentially type in the ftp commands, OR you can write a batch file to automate the FTP of multiple files using the single DOS command:

c:\>ftp -s:script.txt ftp.your_url.com

The batch file can WRITE the ftp> commands to a text file script.txt, invoke the commands in the file and erase the file to clean up, and can be run from the c:\> prompt by just calling the batch file name (without the trailing .bat). A couple of different syntaxes below gets the job done:

echo userid> script.txt
echo password>> script.txt
echo binary>> script.txt
echo put filetoupload.pdf>> script.txt
echo close>> script.txt
echo bye>> script.txt
ftp -s:script.txt ftp.insertyoururl.com
del script.txt

or

set /p FTPADDRESS=Enter URL or IP Address:
set /p SITEBACKUPFILE=Enter File to Download:
set /p FTPUSERNAME=Enter FTP User Name:
set /p FTPPASSWORD=Enter FTP Password:
>script.ftp ECHO %FTPUSERNAME%
>>script.ftp ECHO %FTPPASSWORD%
>>script.ftp ECHO binary
>>script.ftp ECHO get %SITEBACKUPFILE%
>>script.ftp ECHO close
>>script.ftp ECHO bye
FTP -s:script.ftp %FTPADDRESS%
TYPE NUL >script.ftp
DEL script.ftp

And now for the BUG that took me pretty much an entire day to solve. It is so stupid that no one else has ever done this, therefore I could not find it on the internet. I found that both typing ftp at the dos prompt or running the batch files from the dos prompt caused dos to "hang". As in, the cursor blinks on a new line but nothing happens and no keys allow escape. The final answer was I had inadvertently named my batch file ftp.bat -- HUGE mistake because that name overrides the path to ftp.exe in the windows system directory and essentially causes the cmd utility to crash. Oh boy.

Monday, May 11, 2009

Avoiding Microscopic Web Text on iPhone

You need a meta tag inside your html head tag as follows:

[head][meta name="viewport" content="width=240; user-scalable=false" /][/head]

The tradeoff is: with this meta tag you lose the "pinch" zoom function, but you can control the size of the text really easily with the width parameter. And you can still scroll with your finger.

Embedding JavaScript within PHP Script

Actually the title of this post should be "Embedding PHP variables within JavaScript which is embedded within echoed HTML within PHP."

Consider this block of code:

echo '[tag]body background="../files/backgroundfade1.jpg"
onLoad="document.getElementById(\'search\').focus();
document.getElementById(\'search\').value=\' '.$_POST[search].'\';"
[tag]';

This little block of code solves a really difficult problem, which is how to have a PHP-generated page of code automatically put the cursor (focus) into the search field at the END of the text in the field (not the beginning). Notice that the echoed HTML within PHP has to be enclosed in single quotes, and the JavaScript embedded in the HTML has to be enclosed in double-quotes, and within that JavaScript one needs additional embedded single quotes to enclose names and data. But if I just use the single quotes I inadvertently escape out of my original HTML statement. THE SECRET IS TO USE BACK_SLASHES BEFORE THE EMBEDDED SINGLE QUOTES to preserve JavaScript environment, then you can immediatedly use another single quote to embed a PHP variable surounded by dots, hence the \' '. $PHP_VARIABLE .'\'

It's really obvious once you look at it this way. It took me weeks to find this solution, and it does not seem to be anywhere on the internet, as far as I know.

Here is another crazy JavaScript Gem:

onKeyup="var t=setTimeout(\'document.list.submit()\',0);"

[Again, note the back slashes because this is embedded within HTML embedded within PHP again, I just left all that out this time.] The setTimeout() to zero milliseconds before running the submit() method gets around a BUG in iPhone Safari Browsers which submits POST requests with the submit() method without capturing the contents of the text field. With the timeout function it somehow forces the BUGGY iPhone browser to submit the data in field with the POST.

Saturday, April 25, 2009

Extended Virtual Keyboard for the TX

Two .prc files are needed: mySkin-Installer from Pruss and Velo-Grayhide Extd Kbd from Velo. That's all. Install them both, run the mySkin program and it will give you the option to select the Velo keyboard.

It appears the "Fitaly" program is unnecessary, although it is supposed to have a feature to remove the rogue DIA files that sometimes get accidently transfered from T3 to TX and crash the DIA. Not sure if it is any good, I found the Fitaly "keyboard" to be buggy and unusable.

The Pruss documentation seems to indicate the ability to "fix" T3 skins, like my own DIA Ultima skins, but I haven't tried it and one would really need the registered version of the Pruss software to take advantage. Maybe I'll try it on a rainy day....

Saturday, April 11, 2009

Palm TX Simulator Crashes on Startup

A thank you and credit goes out to Doug Gordon from the palm-del-forum for this solution, which I quote here:

Sat, 14 Jan 2006

Luc Le Blanc wrote:


On a XP machine where I successfully run various POSE and Simulator
versions, the TX Simulator I downloaded today crashes soon after I
select the shipped "Devon" (?) ROM, and before anything gets displayed
on its screen.

I also had this problem with the Debug version and have not gone back to it, but I since learned this: Look for a directory on your PC named C:\Palm and see if there is a file there named "SimSlotDriverVolume". Delete that and try the Simulator again. In general, I think that you have to delete this file any time that you switch from one Simulator to another. Its contents are different from the "snapshot" file that you save in the Simulator's directory. This makes it more difficult to switch among several Simulator types quickly, but it does seem to fix the problem of it crashing or hanging on startup.

Saturday, April 4, 2009

Invalid Chunk Pointer when Exiting Application

This is a dreaded error message, because if it occurs only when exiting the application all the variables can look fine up to and including the last line of code, and then it crashes. Supposedly it signifies that the application is trying to free up a handle that is already free, such as a a field on a form that is already closed. Alternatively it is supposed to indicate that the application allocated too much memory for global variables. What I find is that if I allocate even local memory for a large, two dimensional char array or a structure consisting of chars, it the application crashes after AppStop on exiting. So my advice is isolate the function that reproduces the "exit crash" and rem out any large char array or char structure declarations, and the crash goes away. Then rewrite the code using more compact char arrays, such as smaller arrays or single-dimensional arrrays, recycling the same memory allocation in loops instead of spreading all the data out into large structures.

On a related note, I also get horrible crashes when editing text fields in my app. I find that usually that means I have screwed up the resizing of the memory when saving the data to the palm's memory. So look at the resizing code or the resizing functions reallly closely when that happens.

Another landmark to report today, besides figuring out the exit crashes and the edit field crashes: I now have the ability to line-by-line debug a Palm OS 5 app while it retreives data from the internet. The trick is to 1. Use the TX Simulator, 2. In Debugger Preferences import the "poser" file, 3. Right click on the Simulator, go into Settings->Communication and select "redirect NetLib calls to host TCP/IP". Now the TX Simulator is connected to the internet, even while using the debugger.

Wednesday, March 11, 2009

Demystified the internet connection at work

The big news of the day was successful internet browsing at work from my palm. Here is the scoop:

click wifi icon on taskbar -> scan/setup -> edit -> add
SSID = [company's three intials]
Security = WEP
Key = 104 bit hex, 26 hex digits (uncheck 'four keys')
Details = Access point (infrastructure)
Advanced = IP automatic, DNS automatic, 'use short preamble' unchecked

The part that had me confused was NOT seeing the SSID after the initial scan. It's invisible until you ADD the SSID under edit. Then you will see it.

Continuing the laptop installation sequence, installed: PODS, Par, hexedit, Core FTP Lite, setup Outlook Express, PDB converter.

Didn't have to install XP SP2 or SP3 because the laptop came with SP3 right out of the box.

Still have to deal with OpenOfficeOrg, Firefox, Skype, Coffeecup, Spybot, Adaware, printer drivers.

Tuesday, March 3, 2009

Starting from Scratch

Just got an MSI U100 Wind Netbook. Very, very cheap ($300) and very portable. I am a Vista refugee so finding XP again is a huge relief. [Vista has serious problems with palm software including desktop, hotsync, epocrates, PODS] So I thought I would tlog my progress because I am tired of reinventing the same wheel over and over.

1. Initial boot caused MSI to do an apparent 'system recovery' to factory state. Resulted in an OS_Install C: drive (30GB of 39GB free) and a Local Disk D: drive (105GB, empty). There is also a shortcut called MSI BurnRecovery which I will need to come back to.
2. Installed Palm TX which created Palm folder and hotsynced to the TX with username EHR2. [Since there is no CD drive, used a 4GB thumb drive, with files copied including hidden files.]
3. Linked to the wireless network after discovering that Fn-F11 toggles on the wireless card. At least that's what I think happened.
4. Did a few Restore Points along the way just for good luck.
5. Went into start->run->msconfig->startup and disabled all except hotsyncshortcutname and bluetooth manager.
6. Right clicked hotsync in tray->custom-> disabled versamail, addit, docstogo, etc. Had to to into docstogo to disable it from hotsync.
7. Installed epocrates from web site.