Archive for March, 2010
Image Resizing Functions (… again?!)
by z3n on Mar.27, 2010, under Coding, Tips & Hints
Problem:
Oh yeah i posted this before, but now that i finally got wordpress updates i can use a decent syntax highlighter.
The main function img_resizer, is able to resize gif, png, wbmp, bmp and jpgs with proportional or cropping resize, it’s also got a function to eventually FIX the format if the filename extension is not really the same of the format, like a jpg named as file.bmp. BMP function been taken off php man pages, i will not post author’s full email to avoid spam.
Solution:
function dwordize($str) {
$a = ord($str[0]);
$b = ord($str[1]);
$c = ord($str[2]);
return $c*256*256 + $b*256 + $a;
}
function byte3($n) {
return chr($n & 255) . chr(($n >> 8) & 255) . chr(($n >> 16) & 255);
}
function dword($n) {
return pack("V", $n);
}
function word($n) {
return pack("v", $n);
}
function imagebmp(&$img, $filename = false) {
$wid = imagesx($img);
$hei = imagesy($img);
$wid_pad = str_pad('', $wid % 4, "\0");
$size = 54 + ($wid + $wid_pad) * $hei;
//prepare & save header
$header['identifier'] = 'BM';
$header['file_size'] = dword($size);
$header['reserved'] = dword(0);
$header['bitmap_data'] = dword(54);
$header['header_size'] = dword(40);
$header['width'] = dword($wid);
$header['height'] = dword($hei);
$header['planes'] = word(1);
$header['bits_per_pixel'] = word(24);
$header['compression'] = dword(0);
$header['data_size'] = dword(0);
$header['h_resolution'] = dword(0);
$header['v_resolution'] = dword(0);
$header['colors'] = dword(0);
$header['important_colors'] = dword(0);
if ($filename) {
$f = fopen($filename, "wb");
foreach ($header AS $h) {
fwrite($f, $h);
}
// save pixels
for ($y=$hei-1; $y>=0; $y--) {
for ($x=0; $x<$wid; $x++) {
$rgb = imagecolorat($img, $x, $y);
fwrite($f, byte3($rgb));
}
fwrite($f, $wid_pad);
}
fclose($f);
} else {
foreach ($header AS $h)
{
echo $h;
}
//save pixels
for ($y=$hei-1; $y>=0; $y--) {
for ($x=0; $x<$wid; $x++) {
$rgb = imagecolorat($img, $x, $y);
echo byte3($rgb);
}
echo $wid_pad;
}
}
}
function _ckdir($fn) {
if (strpos($fn,"/") !== false) {
$p=substr(substr($fn,0,strrpos($fn,"/")),0,250);
if (!is_dir($p)) {
mkdir($p,755,true);
}
}
}
function imagecreatefrombmp($p_sFile) { // by alexander at http://www.php.net/manual/en/function.imagecreatefromwbmp.php
// Load the image into a string
$file = fopen($p_sFile,"rb");
$read=fread($file,10);
while(!feof($file)&&($read<>""))
$read.=fread($file,1024);
$temp=unpack("H*",$read);
$hex=$temp[1];
$header=substr($hex,0,108);
// Process the header
// Structure: http://www.fastgraph.com/help/bmp_header_format.html
if (substr($header,0,4) == "424d") {
// Cut it in parts of 2 bytes
$header_parts=str_split($header,2);
// Get the width4 bytes
$width=hexdec($header_parts[19].$header_parts[18]);
// Get the height4 bytes
$height=hexdec($header_parts[23].$header_parts[22]);
// Unset the header params
unset($header_parts);
}
// Define starting X and Y
$x=0;
$y=1;
// Create newimage
$image=imagecreatetruecolor($width,$height);
// Grab the body from the image
$body=substr($hex,108);
// Calculate if padding at the end-line is needed
// Divided by two to keep overview.
// 1 byte = 2 HEX-chars
$body_size=(strlen($body)/2);
$header_size=($width*$height);
// Use end-line padding? Only when needed
$usePadding=($body_size>($header_size*3)+4);
// Using a for-loop with index-calculation instaid of str_split to avoid large memory consumption
// Calculate the next DWORD-position in the body
for ($i=0;$i < $body_size;$i+=3) {
// Calculate line-ending and padding
if ($x >= $width) {
// If padding needed, ignore image-padding
// Shift i to the ending of the current 32-bit-block
if ($usePadding)
$i+=$width%4;
// Reset horizontal position
$x=0;
// Raise the height-position (bottom-up)
$y++;
// Reached the image-height? Break the for-loop
if ($y > $height)
break;
}
// Calculation of the RGB-pixel (defined as BGR in image-data)
// Define $i_pos as absolute position in the body
$i_pos=$i*2;
$r=hexdec($body[$i_pos+4].$body[$i_pos+5]);
$g=hexdec($body[$i_pos+2].$body[$i_pos+3]);
$b=hexdec($body[$i_pos].$body[$i_pos+1]);
// Calculate and draw the pixel
$color=imagecolorallocate($image,$r,$g,$b);
imagesetpixel($image,$x,$height-$y,$color);
// Raise the horizontal position
$x++;
}
// Unset the body / free the memory
unset($body);
// Return image-object
return $image;
}
function img_force($src,$quality,$w,$h,$saveas,$nocrop,$force) {
foreach (array("jpg","gif","png") as $x) { // will skip bmp formats
if ($x != $force) {
if (img_resizer($src,$quality,$w,$h,$saveas,$nocrop,$x)) {
return 1;
break;
}
}
}
return 0;
}
function img_resizer($src,$quality,$w,$h,$saveas,$nocrop=0,$force=0) { /* v2.72 with auto crop, no crop, automatic file type detection when avalible (requires exif library) */
if (!is_file($src)) { _o("Source is not a file.");return 0; }
if (!is_readable($src)) { _o("Can't read: ".$src);return 0; }
if ((file_exists($saveas)) && (!is_writeable($saveas))) { _o("Can't write to: ".$saveas);return 0; }
$r=1;
if (function_exists('exif_imagetype')) { // automatic filetype detection
$e=exif_imagetype($src);
if ($e == IMAGETYPE_JPEG) {
if (!$OldImage=@ImageCreateFromJpeg($src)) { $r=0; }
} elseif ($e == IMAGETYPE_GIF) {
if (!$OldImage=@ImageCreateFromGif($src)) { $r=0; }
} elseif ($e == IMAGETYPE_BMP) { // custom
if (!$OldImage=@ImageCreateFrombmp($src)) { $r=0; }
} elseif ($e == IMAGETYPE_WBMP) {
if (!$OldImage=@ImageCreateFromwbmp($src)) { $r=0; }
} elseif ($e == IMAGETYPE_PNG) {
if (!$OldImage=@ImageCreateFromPng($src)) { $r=0; }
} else {
_o("Not a Valid Image! (".$e.") -- ".$src);$r=0;
}
} else { // filename based filetype detection, might be subject to incorrect file extensions, resulting on a error, which when enabled will fall into a try and error `force` mode
$e=($force == "0") ? strtolower(substr($src,strrpos($src,".")+1)) : $force;
if (($e == "jpg") || ($e == "jpeg")) {
if (!$OldImage=@ImageCreateFromJpeg($src)) { $r=0; }
} elseif ($e == "gif") {
if (!$OldImage=@ImageCreateFromGif($src)) { $r=0; }
} elseif ($e == "bmp") { // this is NOT wbmp
if (!$OldImage=@ImageCreateFrombmp($src)) { $r=0; }
} elseif ($e == "png") {
if (!$OldImage=@ImageCreateFromPng($src)) { $r=0; }
} else {
_o("Not a Valid Image! (".$e.") -- ".$src);$r=0;
}
}
if ($r) {
list($width,$height)=getimagesize($src);
// check if ratios match
$_ratio=array($width/$height,$w/$h);
if ($_ratio[0] != $_ratio[1]) { // ratio don't match
if ($nocrop) { // since we can't crop we will need to do image on a different height/width
$hx = (100 / ($width / $w)) * .01;
$hx = @round ($height * $hx);
$wx = (100 / ($height / $h)) * .01;
$wx = @round ($width * $wx);
if ($hx < $h) {
$h = (100 / ($width / $w)) * .01;
$h = @round ($height * $h);
} else {
$w = (100 / ($height / $h)) * .01;
$w = @round ($width * $w);
}
} else { // crop image
// find the right scale to use
$_scale=min((float)($width/$w),(float)($height/$h));
// coords to crop
$cropX=(float)($width-($_scale*$w));
$cropY=(float)($height-($_scale*$h));
// cropped image size
$cropW=(float)($width-$cropX);
$cropH=(float)($height-$cropY);
$crop=ImageCreateTrueColor($cropW,$cropH);
ImageCopy($crop,$OldImage,0,0,(int)($cropX/2),(int)($cropY/2),$cropW,$cropH); // crop the middle part of the image to fit the thumbnail's proportions
}
}
// do the thumbnail
$NewThumb=ImageCreateTrueColor($w,$h);
if (isset($crop)) { // been cropped
ImageCopyResampled($NewThumb,$crop,0,0,0,0,$w,$h,$cropW,$cropH);
ImageDestroy($crop);
} else { // ratio match, regular resize
ImageCopyResampled($NewThumb,$OldImage,0,0,0,0,$w,$h,$width,$height);
}
_ckdir($saveas);
ImageJpeg($NewThumb,$saveas,$quality);
ImageDestroy($NewThumb);
ImageDestroy($OldImage);
} elseif (($force == "0") && (!function_exists('exif_imagetype'))) {
$r=img_force($src,$quality,$w,$h,$saveas,$nocrop,$e);
}
return $r;
}
See how nice it looks with the syntax highligher? :P
Updates:
100407 – Added imagebmp function to save as bmp;
Adding RAR to allowed upload types of wordpress
by z3n on Mar.26, 2010, under Tips & Hints
Problem:
I can’t upload rars to wordpress.
Solution:
Edit wp-includes/functions.php,
search for:
'exe' => 'application/x-msdownload'
add a line after it:
'rar' => 'application/x-rar-compressed',
Done!
You may want to add other filetypes you also enjoy here.
Source:
Micro mouse cursors
by z3n on Mar.26, 2010, under Tips & Hints
I made this back 2004, and still rocking.
Those are mouse cursors, about 5×3 pixels size, for all allowed windows types. I don’t like the original annoying format and this one suits me better.
They are in inverted format so should be visible in almost of the backgrounds, unless you use it on a gray like deviantart’s.
Generating an SSL certificate for apache mod_ssl
by z3n on Mar.26, 2010, under Coding, Tips & Hints
Problem:
how to generate a ssl certificate to integrate with apache’s mod_ssl?
Solution:
You will need OpenSSL.
First step – Generate a RSA Private Key.
Use random files as seed.
openssl genrsa -des3 -rand file1:file2:file3:file4:file5 -out server.key 1024
openssl will ask you for a password, don’t forget it cuz your key will be useless without it.
— Stolen Text Begins:
One unfortunate side-effect of the pass-phrased private key is that Apache will ask for the pass-phrase each time the web server is started. Obviously this is not necessarily convenient as someone will not always be around to type in the pass-phrase, such as after a reboot or crash. mod_ssl includes the ability to use an external program in place of the built-in pass-phrase dialog, however, this is not necessarily the most secure option either. It is possible to remove the Triple-DES encryption from the key, thereby no longer needing to type in a pass-phrase. If the private key is no longer encrypted, it is critical that this file only be readable by the root user! If your system is ever compromised and a third party obtains your unencrypted private key, the corresponding certificate will need to be revoked. With that being said, use the following command to remove the pass-phrase from the key:
openssl rsa -in server.key -out server.pem
— Stolen text ends.
Now you need to generate a CSR that will be sent to the Certificate Authority that will verify and i$$ue a signed certificate. Now you will need to fill lots of fields, make sure you write them down, sometimes the CA asks for the info to see if it matches.
openssl req -new -key server.key -out server.csr
Generating a Self-Signed Certificate
Now that your have your csr you may want to test it on your local server, or if you want to actually buy a signed certificate you can just send the server.csr file to your beloved CA. Note that generating self-signed certificates will show an error on client’s browser, since your’re not a trusted entity.
openssl x509 -req -days 60 -in server.csr -signkey server.key -out server.crt
This will generate a 60 days self-signed certificate.
And now…
You just need to add it to apache!
Usually apache has a ssl.conf or a httpd-ssl.conf file as examples, just copy the .crt, .csr and .key file to the folders there.
There’s also a simple example of doing a implementation of ssl on a domain:
<IfDefine SSL>
<VirtualHost _default_:443>
ServerAdmin webmaster@domain.com
DocumentRoot /usr/local/apache/share/htdocs
ServerName www.domain.com
ScriptAlias /cgi-bin/ /usr/local/apache/share/htdocs/cgi-bin/
SSLEngine on
SSLCertificateFile /usr/local/apache/etc/ssl.crt/server.crt
SSLCertificateKeyFile /usr/local/apache/etc/ssl.key/server.pem
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
CustomLog /usr/local/apache/var/log/ssl_request_log \"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" </VirtualHost>
</IfDefine>
…also stolen from the same site.
Notes:
DO NOT use OpenSSL for windows, it has sucked for me.
If you are using this on windows and when starting apache you get:
Init: SSLPassPhraseDialog builtin is not supported on Win32
Remove the password from your server.key file by:
cp server.key server.key.bak openssl rsa -in server.key.bak -out server.key
Source:
Nested Ifs using ? : notation
by z3n on Mar.25, 2010, under Coding, Tips & Hints
Problem:
I can’t tell if this is a good practice, but i don’t really care, it speeds up the process.
I’m talking about this specific IF notation:
$x=1;
// this:
if ($x == 1) {
// do something
} else {
// do something
}
// .. can be replaced with this
return ($x == 1) ? /* true */ : /* false */;
// however... this:
if ($x == 1) {
// do something
} else {
if ($x == 2) {
// do something
} else {
// do something
}
}
// can't be replaced with the ? : notation
Solution:
function foo($x) { return $x; }
return ($x == 1) ? /* x = 1 */ : foo(($x == 2) ? /* x=2 */ : /* x = other */);
Automatic Backups to gmail
by z3n on Mar.25, 2010, under Uncategorized
Problem:
Gmail is offering a considerable ammount of free space, now, it can be used to do automatic backups, specially if you run a database or something critical.
Solution:
They offer a lot of space … but you can’t get emails bigger than 20mb, so you need to do some tricks,
first a little bash script:
#!/bin/bash
s_ts() { date "+[%H:%M:%S%p]"; }
_dt=`date +%y%m%d`
echo \(c\) z3n - R1V1.06@070509 \(PiD:$$\)
cd /path/to/backup/folder
echo `s_ts` SQL Backup...
mysqldump -pMYSQL_PASSWORD --all-databases > mysql-"$_dt".sql
echo `s_ts` Compressing...
rar a -m5 -inul -s -rr3 -v19750k -df mysql-"$_dt".rar mysql-"$_dt".sql
cd ..;php ma.php mysql-"$_dt".rar
and then a ma.php to email attachments:
// (c) z3n - z3n666@gmail.com
define('from','backup@youdomain.com');
define('to','your.gmail@gmail.com');
define('subject','MySQL Backup - '.date("Y-m-d"));
define('base_path','/path/to/backup/');
set_time_limit(0);
ini_set("memory_limit","1G");
function send_attach_mail($email_from,$email_to,$email_subject,$file) {
$email_message = $file; // Message that the email has in it
$semi_rand=md5(time());
$mime_boundary="==Multipart_Boundary_x{$semi_rand}x";
$headers="From: ".$email_from."\nMIME-Version: 1.0\nContent-Type: multipart/mixed;\n boundary=\"{$mime_boundary}\"";
$email_message.="This is a multi-part message in MIME format.\n\n--{$mime_boundary}\nContent-Type:text/html; charset=\"iso-8859-1\"\nContent-Transfer-Encoding: 7bit\n\n".$email_message."\n\n";
/* First File */
$fileatt_type = "application/octet-stream"; // File Type
$fileatt_name = $file; // Filename that will be used for the file as the attachment
$rfile = fopen($file,'rb');
$data = fread($rfile,filesize($file));
fclose($rfile);
$data = chunk_split(base64_encode($data));
$email_message .= "--{$mime_boundary}\nContent-Type: {$fileatt_type};\n name=\"{$fileatt_name}\"\nContent-Transfer-Encoding: base64\n\n".$data."\n\n--{$mime_boundary}\n";
@mail($email_to, $email_subject, $email_message, $headers);
}
if (!isset($argv[1])) {
die("Usage: ".$_SERVER['PHP_SELF']." <filename>");
} else {
$argv[1]=str_replace("..","",$argv[1]);
if (!file_exists(base_path.$argv[1])) { // try to see if this is multipart file
for ($i=1;file_exists(substr(base_path.$argv[1],0,-3)."part0".$i.".rar");$i++) {
send_attach_mail(from,to,subject,substr(base_path.$argv[1],0,-3)."part0".$i.".rar");
}
} else {
send_attach_mail(from,to,subject,base_path.$argv[1]);
}
}
Done!
packable qTip
by z3n on Mar.19, 2010, under Coding, Tips & Hints
Problem:
I was looking around and found this great jQuery plugin, qTip, i added to my auto packer javascript script and then it didn’t worked at all.
Reading further on their site i found out that they have a YUI compressed version which is not what i need.
Solution:
After hunting a lot of missing ; and extra ;, i’ve got a working packable version.
json decode fails on non utf-8
by z3n on Mar.16, 2010, under Coding, Tips & Hints
Problem:
When sending a non utf-8 string as json, the decoding fails.
Solution:
PHP works as utf-8 as default, since i’m using strings with accents (áéíóú..) those are taken as iso-8859-1. Client-side script will not send as utf-8, not even if you force it, so the best solution is convert the json object’s encoding. You may also want to encode your string as plain chars (I use base64) to avoid issues with IE.
Code would look like this:
$json=json_decode(iconv(‘ISO-8859-1′,’UTF-8′,base64_decode($input)),true);
If you’re working with different charsets just change the iso-8859-1, remember that if you’re working with multibyte chars, such as japanese, chinese, etc, you will need to use the mb functions instead.
Sources:
Pablo Viquez (A solution pretty much like mine but for sending data instead)
