Friday, June 29

VMware Fusion

Today, I got to play with a 17" MacBook Pro. I was supposed to try out VMware Fusion. I'd used it in its early beta days, but not since they added the very cool feature, Unity. This is about the same thing as Coherence in Parallels. (I haven't used Parallels since they added Coherence either).
Unity is a really nice feature. If you haven't heard of it, it allows you to use your Windows applications on the Mac desktop instead of having to be restricted to its guest window. These little app windows even work with Expose and other mac features. Here's some screenshots...


This is how a vm normally looks. Great, I'm trapped in a box.


But now! Awesome, my windows are sitting side by side. Plus, if you'll notice, there's even an icon in the dock for each of the Windows applications running.


The coolest thing (IMHO) is that you can still do expose and stuff with these windowed Windows apps.

And just because I can, here's a YouTube video someone made:

Wednesday, June 20

"Intelligent" Custom 404 Page

This is fairly simple, but took me quite a while to find. I wanted to use a custom 404 page on my WIMP, but I wanted to be able to do SSI, php and whatever. Well setting the 404 page is easy enough.

  1. Open IIS Manager

  2. Right-click on the website and go to properties

  3. go to the tab Custom Errors

  4. scroll down to 404 and click edit
Now this is the part I couldn't find any info on. If you pick File from Message type: you can only use htm/html files. If you pick an shtml file, the page will display, but no includes will work. If you pick a php (or asp) file, when you try to access a nonexistent page, the browser will download the 404 page!

To be able to use shtml/php, you have to pick URL and give it a link from site root (e.g. /404.php). Hit OK and Apply and it's all set.

Now you can set your 404 pages to anything you want. One helpful thing is to have it take whatever they typed in and use it as a search term for the site.

Thursday, June 14

No document.write() Allowed

I have not been doing a good job of posting in here, but honestly, I haven't been doing anything interesting at all. I guess the latest thing I learned was about document.write().

It is NOT ALLOWED in XHTML 1.1 Transitional. It creates code that will not be valid by the W3C. I was unaware when I started so I had a page that used it. I was using it for a section that randomly loaded a picture and some text each time the page loaded. doing like:

document.write('<img src="'+images[randomNumber]+'" />")

etc.
What I ended up doing to make it valid was use innerHTML. I did:
function feature(){
var place = document.getElementById('featured');
place.innerHTML = '<img src="'+images[randomNumber]+'" /><p>'+words[randomNumber]+'</p>';
}

and now it comes up valid. I'm pretty sure you can use addChild in a similar manner and it would be valid as well.

Thursday, May 31

Resize Images with GD2

I found a bunch of places on the internets that help you with scripts to resize your images with gd2. These are all pretty cool because they resize your images while preserving their aspect ratio. Well I didn't want that so I had to read through the gd2 info on php.net. It's actually fairly simple, once I figured out what I was doing. I'm using a file uploaded from a form. So here's some simple resize code:

$imgrel = '../images/upload/'.basename($_FILES['pic']['name']); //gd wants relative paths
list($width,$height) = getimagesize($imgrel);
if($width<>150 || $height<>188){
$img_src = imagecreatefromjpeg($imgrel);
$img_dst = imagecreatetruecolor(150,188);
$imagecopyresampled($img_dst, $img_src, 0, 0, 0, 0, 150, 188, $width, $height);
imagejpeg($img_dst, $imgrel, 90);
}
There's the option of using imagecopyresized instead of imagecopyresampled, but I did that and it just doesn't look as good. If you don't know why, read this (I did). When I first did this, it wasn't working, but that was because I forgot the imagejpeg(). Oops. By the way, the 90 in that means 90% quality for that jpeg.

So now I suppose you want to resize your images keeping the aspect ratio. Well, I'm just going to share some code I found that seems to work for me. This one is from 9tutorials:
function resizeImage($originalImage, $toWidth, $toHeight){

list($width, $height) = getimagesize($originalImage);
$xscale = $width/$toWidth;
$yscale = $height/$toHeight;

//recalculate new size with default ratio
if($yscale>$xscale){
$new_width = round($width * (1/$yscale));
$new_height = round($height * (1/$yscale));
}else{
$new_width = round($width * (1/xscale));
$new_height = round($height * 1/xscale));
}
$imageResized = imagecreatetruecolor($new_width, $new_height);
$imageTmp = imagecreatefromjpeg($originalImage);
imagecopyresampled($imageResized, $imageTmp, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
}

There we go. Easy as that. If you don't like that one, there's a different one at Netlobo which is the same as one on Travidal

Now just remember when you're doing this that GD2 is pretty process intensive so if you're resizing lots of images or large images, it's probably better to go with something like imagemagick.

Friday, May 18

Engineers vs. IT

I work at a university for a subset of Civil Engineering: Traffic Engineering. I'm just a lowly tech person, so I make websites and maintain computers and take orders from PhD's and Engineers. In case I haven't made it clear enough, to engineers it seems anyone who isn't an engineer is lower class citizen. And pretty stupid at that. I really have a problem with this. Not because I think I'm smarter than them at traffic engineering, but because I KNOW I'm smarter than them at technical stuff.

Now traffic engineering has been stepping into the world of technology with Intelligent Transportation Systems (ITS) and these poor engineers don't really have any idea. They seem to be taking baby steps and I think it's because of their opinion toward IT people, or non-engineers. For example, I met the technical support manager for Econolite, a major manufacturer of ITS equipment. He was really excited because their new software (version 9, just released this May) has IP support. "This means you can configure the cameras from anywhere!" he excitedly tells me. Yeah! That's the point of the internet! Up until then, you actually have had to go to the camera and connect to it with a laptop and a serial cable.

Now obviously this is a great idea, but it was still implemented pretty poorly. The webapp was clunky and written in Java. (The cool thing is since he's pretty high up, he's got some powers. I asked him if they developed in house and when he said yes, I suggested AJAX. 5 minutes later he tells me he sent an email to the developers suggesting it.) So what I'm wondering is, how much sooner would they have had IP connections to their cameras if it were IT people working on this instead of engineers?

Another example: I was reading about some plans for a particular city for phasing in their cameras. They have 300-ish cameras set up and only 20 some are being used. Their problem is they are using dial up to access the cameras. They want to set up a wireless mesh network between the lights for connectivity instead. Very cool idea. The problem they're running into is the project has come in way over budget for them. Now, this university I work for has another project from a different college (not engineering, but IT) which is trying to supply wireless networks around the city. Hmm... seems like a match made in heaven doesn't it?? Well, the engineering PhD's here didn't seem to thing so and threw a royal fit when that college tried to pair up with the city.

How much farther would we be if we could all just get along? How many other groups are separated by stupid ego issues and could have advanced so much farther if they just worked together?

Tuesday, May 15

PEAR Mail for Contact Info Check

I was asked to make an email that would send out every 6 months to see if the user's contact information had changed. So I needed to send an email to everyone in our database comprised of their information. I already mentioned using scheduled tasks, but we've got to make the file for it to run first. I thought it was going to be complicated, but it turned out to be quite easy. All I had to do was put the entire email into a while loop that went through the database. This is where the PEAR mail class definitely outshines PHP mail() because you can set a persistent connection to the server until you're done sending emails.

include 'Mail.php';

$get_contact = mysql_query("SELECT * FROM contact_info");
while($row = mysql_fetch_assoc($get_contact)){
$recipients = $row['email'];

$params['host'] = 'smtp.server.com';
$params['persist'] = true;

$headers['To'] = $row['FirstName'].' '.$row['LastName'].' <'.$row['email'].'>';
$headers['From'] = 'Me <mail@mail.com>';
$headers['Subject'] = 'Please Check Contact Information';

$body = 'Dear '.$row['FirstName'].' '.$row['LastName'].',

Some stuff about you should check your contact info. Here's your contact info';

//then just list their info in the body or add more to the body with .=
//then just mail it like before

$mail_object =& Mail::factory('smtp', $params);
$mail_object->send($recipients, $headers, $body);

} //don't forget you're in a while loop

Of course, if someone's gotten a new email and hasn't updated your list, you're still screwed, but oh well! What can ya do?

PEAR Templates

I recently discovered the place I work for has made their website templates as a PEAR extension. Very cool. I've been in the process of converting my pages. It's nice to work with because, for example, the standard no content template is a whopping 105 lines long. That's really long! The PEAR templates can do the same thing in 6 lines. I've reduced some of my pages from over 300 lines to less than 100. They still look the same and there's all those lines if you view the source on the page, but it's much much easier to work with this way. There's still some bugs, but they're working on that (hopefully).

So, I know this helps no one out there, it's just opinion. I would like to say that I've found the PEAR modules I've used mostly to be helpful (once I figured out how to use them).

Monday, May 7

lols for typos

My friend just showed me this and it was so funny I just had to share.

running Debian/Ubuntu box, type:

sudo apt-get install sl

after it finishes, run sl

read the man page for it for even more silliness

!!!

When is Date() a string?

Simple example says it all:


<?php
include 'Date.php';
$date = new Date();
$d = $date->format('%Y-%m-%D');

if(is_string($date)){
echo "date is a string<br />";
}else echo "date is not a string<br />";

if(is_string($d)){
echo "d is a string<br />";
}else echo "d is not a string<br />";
?>

returns:

date is not a string
d is a string

Friday, May 4

More PEAR Mail Tidbits

Yep, still playing with it. I'm sending emails to people who've decided they want to receive updates from the organization. I did like:

$query = mysql_query("SELECT email FROM info WHERE rcv_updates = 'yes'");
while($row = mysql_fetch_assoc($query)){
$headers['bcc'] .= $row['email'].",";
$recipients .= $row['email'].",";
}
Then all the regular stuff. It was kind of a shot in the dark for me, Not quite sure if it would work. Well, it did. The cool thing was since I didn't specify a To and only bcc's, the To field in the email I got was "undisclosed-recipients:;"

neat

Wednesday, May 2

Scheduled Tasks FTW

So easy thing today. I'd never done it before so it feels like an accomplishment. I need to send automatic emails every 6mo or so... enter Scheduled Tasks. So I created my script, just a php file that would send a mail when ran. Opened scheduled tasks... made the mistake of trying to use the wizard. Bad idea. That wizard is for n00bs so I couldn't figure it out (ha). Here's my steps:

  1. Right click -> new-> task
  2. Name it
  3. Double click it
  4. in run: type -- C:\php5\php.exe "C:\php5\includes\schedtest.php"
  5. set schedule in Schedule tab
  6. set password
That was it. Seriously. That easy. I couldn't believe it, but it actually worked.

Tuesday, May 1

PEAR Date compare()

Alright. I've got this figured out. I'm not sure if this is exactly how you're supposed to do stuff, being new to PEAR as I am, but this seems to work.

The problem:
I have due dates stored in a database. On the webpage, I want to say the due date, then say how many days until the due date (or how many days have passed since the due date.

The code:

We start of creating two date objects, one from the database, one for today.

$due = new Date($row['due_date']);
$d = new Date();
so now we want to compare them. PEAR has a cute little compare function for us. It returns 0 if the dates are equal, -1 if date1 is before date2 and 1 if date1 is after date2.
$comp = Date::compare($due, $d);
So now, we'll get 0, -1 or 1 and we need to handle them. And I want to find out how many days till the project is due.
if($comp == '1'){
$x = Date_Calc::dateToDays($due->day, $due->month, $due->year) - Date_Calc::dateToDays($d->day, $d->month, $d->year);
$daysleft = $x.' days left';
}elseif($comp == -1){
$x = Date_Calc::dateToDays($d->day, $d->month, $d->year) - Date_Calc::dateToDays($due->day, $due->month, $due->year);
$daysleft = $x.' days overdue';
}else $daysleft = 'today';
So the Date_Calc::dateToDays returns a number. It's the number of days since the Date_Calc epoch. It doesn't really matter what it is, it gives us a constant to work with. Just subtracting them returns the number of days. So my page really just says:
<strong>Date Due:</strong> <?=$due->format('%A, %B %e, %Y')?> (<?=$daysleft?>)
and displays:

Date Due: Friday, June 15, 2007 (43 days left)

Wednesday, April 25

Wasting time is my expertise

I didn't really do anything today, so I have nothing interesting to post. Darn.

Make sure you're consistent with your variables. I mean, call them with the name you defined them with, or else they won't work. Duh.

Lack of focus seems to be my problem today....

Tuesday, April 24

PEAR Mail Revisited

I FINALLY got somewhere to relay my mail. (That was the biggest hassle ever. No one wanted to do it because it wasn't "right" due to departmental issues. My issue was that it's for TESTING. What's not right about it, I'll be using it for a month, maybe 2 at most. I don't need an inbox, I don't need anything but a machine to relay my email.) Anyway, I finally got it and then realized my mail function didn't have the "send" part. That's kind of important. I added that to the post about this before too.

I did my mail test function and got errors. It was missing some files. Hmm, that's weird. I got this from PEAR, why would it be missing files. Well, what they fail to inform you when you download mail (either from the website or by doing "pear install mail" from the command line) is that you need to get Net_SMTP and Net_Socket as well. Once you've got those files, it's probably just easiest to put them in the locations they want. That means the file tree will be like:

Mail -
mail.php
null.php
RFC822.php
sendmail.php
smtp.php
Net -
SMTP.php
Net -
Socket.php

Monday, April 23

using PEAR Date with MySQL

So today, my small realization cost me some work, but simplicity in the result. I discovered that if you use the PEAR function Date(), you can correspond that directly to a MySQL database. Previously, I was using Date to format the date how I wanted it, but then using a UNIX timestamp to make sure the dates appeared in order. All I really needed to do was have the field type for the MySQL database be datetime. The output for Date() is the current date and time in the format YYYY-MM-DD HH:MM:SS, which is the MySQL format for datetime. I ran into this little problem. Before sticking a date into the database, you need to convert it into a string. I was trying to do:

$date = new Date();
and just inserting that... I'd get the error Catchable fatal error: Object of class Date could not be converted to string in...

What I really needed to do was:
$d = new Date();
$date = $d->getDate();
Which converts the output to a string before putting it into the database. It worked much better. So the next really cool thing I discovered is, once that's in the database, if you want to call out anything with a date after today (say for some sort of due dates or schedule) you can use the MySQL function date(). Such as:
//get all fields from table sched where date is after now
mysql_query("SELECT * FROM sched WHERE date>now()");
That saves a lot of trouble.

Thursday, April 19

Vista Hates Windows Domain

I have a Vista box I installed a while back. I put it on the domain and everything was all fine. Well, one day, I noticed the box wasn't named what it was supposed to be and being kind of OC about that, I changed the name. After I rebooted, the box had removed itself from the domain. hmm. I put it back on. I logged on with my domain credentials and all was great. Till I rebooted again. Once again, removed. It wouldn't let me put it on again because the computer was still in the AD list, so I renamed it. Then rebooted. Then put it back on the domain. Logged in. Rebooted (to test it)... BAM! off again. I've even tried putting it on a different domain it's never been on. Still removes after reboot. Haven't found the cause yet, but I think that's really weird.
-------
Update:
I think the box isn't really removing itself from the domain. While logged on, it has all the resources and otherwise acts like it's on the domain. The real problem seems to be it doesn't allow domain users to log on. I don't get an option to switch users on the login screen (there is one local user), therefore, there is no box in which to submit my domain credentials. I thought I found people with the problem, but they were just confused because you have to now use the format domain\user or user@domain.

Wednesday, April 18

PEAR Mail

So I've been needing to set up something so I can send automated emails from a website.

So... I created a simple PEAR Mail script, just to try it out. The script resulted in success, but I never received any emails. I changed the type to mail, which is just php's mail() function to see what was up and the error I got was SMTP server response: 554 Relay rejected for policy reasons... which makes sense, since I'm off campus working on a development server. I just wonder why the smtp mail type didn't tell me the error too. It would have been nice. Just to make this post look longer than it is, here's the code:

require_once 'Mail.php';

$recipients = 'me@example.com';

$params['host'] = 'smtp.server.com';
$params['auth'] = TRUE;
$params['username'] = 'email@example.com';
$params['password'] = 'passw0rd';

$headers['From'] = 'email@eaxmple.com';
$headers['To'] = 'me@example.com';
$headers['Subject'] = 'SMTP Test';

$body = 'test message';

$mail_object =&Mail::factory('smtp', $params);
$mail = $mail_object->send($recipients, $headers, $body);
if(PEAR::isError($mail)){
echo($mail->getMessage());
}else{
echo("success");
}

Tuesday, April 17

Working ZipArchive

Ok, I finally got it and feel really dumb now. It turned out to be the bane of my existence.... permissions. What would make me thing the IUSR_SERVERNAME account would only need write permissions. To change a file, of course they would need modify permissions too! DUH!

I figured a lot of other things out along the way too. Like: ZipArchive likes relative, not absolute paths. I had to rewrite some stuff because of that. I had been using 7za.exe, but wanted to start using the php_zip.dll since I upgraded to php5.

So here's my code for pulling file names from a database and stuffing them into a zip. I turned it into a function that throws back the zip file name. These are zips of the files in a bunch of teachers' lesson plans.

function zipper($id){
include 'db.php';
$query = mysql_query("select distinct path from files where id=".$id."");
$query2 = mysql_query("select title from lessons where lesson_id=".$id."");
$row = mysql_fetch_assoc($query2);
$zipfile = str_replace(" ", "", $row['title']).".zip";
$filename = "teacherfiles/zips/$zipfile";
//create archive
$zip = new ZipArchive();
if($zip->open($filename, ZIPARCHIVE::CREATE)!=TRUE){
exit("Cannot open $filename");
}

while($result = mysql_fetch_assoc($query)){
$path = str_replace("%20"," ",str_replace("&","&",$result['path']));
$zip->addFile($path);
}
$zip->close();

return $filename;
}

What happens is I call a popup window, which calls the function, makes the zip, then uses a meta-redirect to the created file to prompt a download. After 30 seconds, the window redirects to a page that deletes the file and closes the window almost immediately. It's pretty cool.

Monday, April 16

ZipArchive

Man, I'm trying to get this to work, but I'm not having any luck at all. It's driving me nuts!!

I'll post a solution when I get it. I've got my WIMP with php 5.2.1 and zlib 1.2.3, using the sample code from php.net

It's supposed to create a file called test112.zip, but instead I'm ending up with test112.zip.a03600 and another one called test112.zip.b03600. It's time to go home now, but I'll figure this out tomorrow.

--------------------------------------------------
Well, I'm still working on this. I'm super confused because I'm still ending up with those temporary files. I moved the script to an area where I know IUSR_SERVERNAME is allowed write permissions, but that didn't help.

I tried making .gz files just in case zlib really doesn't work with .zip, but those didn't work either.

If I use AddFromString, I can rename the files ending in zip.a03600 (or whatever number it happens to be) and then I can extract it, which is saying to me a rename error. BUT, if I use AddFile instead, no files are added and the zip isn't even created.

I tried going through the list of errors and seeing which ones I get, but it ends up being most of them. I couldn't find a way to have it report which error it's getting, so I wrote a bunch of ifs. Turns out that wasn't the best option, since all but ZipArchive::ER_OK resulted in true.

I'm still workin on it, but interrupted by people who can't print.... ._.

Saturday, April 14

What a WIMP!

Oops, forgot to post something yesterday. I'll try to put up something later today, but in the mean time, a random observation.

We've all heard of a LAMP (Linux Apache MySQL PHP) server... well, I'm not sure if this term has been highly spread around, but I'm running a WIMP!!! (Windows IIS MySQL PHP)

In case anyone wonders, I did not get to choose the webserver and if I had a choice, I would never use Windows as a webserver again. I've had experience with both now, and as far as I can tell, you're better off running a LAMP than a WIMP. Even a WAMP isn't so good as Apache has no real advantages on a Windows box over IIS. Actually, it's probably worse. There are a lot less things you can do since it's not Microsoft integrated software.

Just my 2c...

Thursday, April 12

My Google Maps

If you haven't noticed, Google maps has added "My Maps" to its page. This allows you to make and save Google Maps instead of having to use some other website like mapbuilder.net. You can even export your maps in KML format for use in Google Earth. I made a map, but it's not very exciting... Still, if you like to watch cars drive by, here it is: MATC ITS Cameras - Omaha, NE.

Wednesday, April 11

First Post Ever

This will be my log of discoveries and problems in web development and systems administration. I will try to post one thing every day in the hopes that someday someone will find it helpful. Hopefully, soon I'll change this template thingy.

Happy Coding!