Oops, I did it again… Outlook 2010 attachment and account check

We’ve all done it – please see attached…. DOH!

And with multiple email accounts, and forwarding to your main address, it’s easy to send from your default account when you meant to use another…

But there are solutions to hand!

FAD (Forgotten Attachment Detection) from MS Office Labs solves problem 1:

http://www.officelabs.com/projects/forgottenattachmentdetector/Pages/default….

It requires Microsoft Visual Studio Tools for Microsoft Office V3 which is only 2mb:

http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=23656

I believe .NET is required too.

 

For account selection, a small registry modification will prompt you to choose the account each time – essentially removing the ‘default account’ functionality.

http://www.msoutlook.info/question/477

‘Deprecated’ error warnings – PHP 5.3

Just reviewing some sites in my portfolio, and I notice that a CubeCart installation on a shared host is broken. Oh dear…

Deprecated: Function set_magic_quotes_runtime() is deprecated in /path/to/domain/shop/ini.inc.php on line 114Warning: ini_set(): Cannot change zlib.output_compression - headers already sent in /path/to/domain/shop/ini.inc.php on line 118 Warning: Cannot modify header information - headers already sent by (output started at /path/to/domain/shop/ini.inc.php:114) in /path/to/domain/shop/index_enc_ion.php on line 31 Warning: Cannot modify header information - headers already sent by (output started at /path/to/domain/shop/ini.inc.php:114) in /path/to/domain/shop/index_enc_ion.php on line 32Deprecated: Function eregi() is deprecated in /path/to/domain/shop/includes/functions.inc.php on line 408

Ah, great. Without warning, we’ve been upgraded to PHP 5.3

Thanks for that…

Anyway, it’s easily solved.

With 5.3 a new error level has been introduced – E_DEPRECATED, so it’s easy to suppress deprecated errors:

In your scripts:
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);

In the case of CubeCart 4 this can be acheived in ini.inc.php line 101.

In php.ini:

error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED

in .htaccess:

php_value error_reporting 1

.htaccess requires the correct integer value equivalent of your chosen reporting level – these are a touch obscure, but setting it to 1 means report fatal run-time errors and unrecoverable errors, which will do the trick.

YouTube Easter Egg has Worms


A worm on YouTube, yesterday…

 This may not be news to you, but I came across a secret game of “worm” while using YouTube yesterday – while the loading icon shows, simply press any two different cursor keys and the icon zooms off and you can keep yourself entertained while waiting. Of course, should you find yourself enjoying the game and not want the video to start, you should probably be watching more interesting videos in the first place…

 

Social Engine 4: Unable to delete user [Solution]

I am new to Social Engine, but have already found a number of quite surprising issues with it. As such my analysis relies upon a certain amount of logic and assumption. Ironic really, as assumptions are what cause this particular issue… 

Symptoms:

A user trying to delete their profile from http://{domain.com}/members/settings/general gets an 500 Internal Server Error.

Administrators attempting to delete profiles from admin get delete confirmation modal popup. On clicking delete, the popup turns white and user is not deleted. Inspecting traffic in the Firebug Net panel, the ajax request is returning a 500 Internal Server Error.

Checking {domain}/statistics/logs/error_log reveals the following errors generated each time:

PHP Fatal error:  Call to a member function remove() on a non-object in /path/to/domain/application/modules/Album/Model/Photo.php on line 150PHP Fatal error:  Undefined class constant 'PRIMARY_TYPE_NUM' in /path/to/domain/application/modules/Core/Model/DbTable/Session.php on line 538

 

Cause:

I believe the cause is a user with missing images that are listed in the database. This in itself should not be an issue, but it seems the code makes fatal (!) assumptions regarding the existance of images that are listed in the database, a rookie mistake if ever there was one. When dealing with files on the file system, one must always confirm their existance, and if possible validate the file content before attempting to operate on it, else you are open to software errors and worse, security risks.

In this case the files are dealt with through objects, representing the file and the possible methods, or operations, upon it. Where a file does not exist, the object is not created, so it is the object, rather than the file whose existance needs confirmation before operating upon it.

As the source code itself notes:

    // This is dangerous, what if something throws an exception in postDelete
    // after the files are deleted?

While the author of this note is considering a different edge case, this would seem to be a worrying indicator of the standard of coding .

The ‘Undefined class constant’ error is merely a consequence of the prior fatal error.

The offending lines are

application/modules/Album/Model/Photo.php 
l.149 – 150
      $file = $this->api()->getApi('storage', 'storage')->get($this->file_id, null);      $file->remove();

You could say that it is 149 that is the cause, rather than 150. 150 tries to do a perfectly valid operation upon the presumed object, but it is 149 that has failed to return an object as expected.

By that token however the cause lies in the storage API, in that it fails to return an object in the first place.

Note that exactly the same careless approach is taken immediately after this operation for thumbnails, and then again (although commented out) for cropped versions.

 

Solution:

Hack:

Add an if(is_object($object)) check before the operation:

Unix Diff:

application/modules/Album/Model/Photo.php 
150c150,152 <       $file->remove(); --- >       if(is_object($file)){ >         $file->remove(); >       } 152c154,156 <       $file->remove(); --- >       if(is_object($file)){ >         $file->remove(); >       }

For clarity, we are replacing:

l.149-152:
      $file = $this->api()->getApi('storage', 'storage')->get($this->file_id, null);       $file->remove();       $file = $this->api()->getApi('storage', 'storage')->get($this->file_id, 'thumb.normal');       $file->remove();

with

l.149-156:
      $file = $this->api()->getApi('storage', 'storage')->get($this->file_id, null);       if(is_object($file)){         $file->remove();       }       $file = $this->api()->getApi('storage', 'storage')->get($this->file_id, 'thumb.normal');       if(is_object($file)){         $file->remove();       }

I am unsure as to just what the failed operation on 149 had returned – if it was anything equating to FALSE, then an alternative and more succinct solution might be:

      if($file = $this->api()->getApi('storage', 'storage')->get($this->file_id, null)){         $file->remove();       }

As this is little more than a dirty hack, I haven’t taken the time to look into this further. I don’t want to be creating users and deleting them just to test out a hunch. 

Proposed system solution:

The storage API should still return an object when a file is not found. This object should contain a ‘not found’ flag, and should not contain a remove() method, or the remove() method of said object could simply log the non existance of the file when the ‘not found’ flag is set.

The object could also reference a ‘not found’ image for use in the front end of the site in the case of images.

The advantage of this approach is that only the object definitions would need to be changed.

Alternatively, every instance of a file operation needs to have a check coded into it as per the hack above.

Further remedial action:

Having corrected this error, the system still failed to delete the user, this time throwing the following error

PHP Fatal error:  Call to a member function getNextCollectible() on a non-object in /path/to/domain/application/modules/Core/Model/Item/Collectible.php on line 54PHP Fatal error:  Undefined class constant 'PRIMARY_TYPE_NUM' in /path/to/domain/application/modules/Core/Model/DbTable/Session.php on line 538

While I am not familiar enough with Social Engine to know exactly what collectible items are (Humbold figurines? Pokémon? I dunno…), it is the same error and can be fixed with a similar approach:

application/modules/Core/Model/Item/Collectible.php
54c54,56<     return $this->getCollection()->getNextCollectible($this); --- >     if(is_object($this->getCollection())){ >       return $this->getCollection()->getNextCollectible($this); >     }

At this point the user could finally be deleted. 

Let them eat Pi! A truesim…

Another word for a trueism is a tautology. I thought I was quite clever for thinking of this in the context of the following article, but of course, the author had gotten there first.

Anyway, what follows is a fascinating and intelligent assasination of  π (Pi), and proposal for its replacement with τ (Tau).

http://tauday.com/

In the words of Smashing Pumpkins, “Tauday is the greatest day I’ve ever known”…

The Shapes of CSS

http://css-tricks.com/examples/ShapesOfCSS/

The Shapes of CSS

All of the below use only a single HTML element. Any kind of CSS goes, as long as it’s supported in at least one browser.

Square

#square { width: 100px; height: 100px; background: red; }

Rectangle

#rectangle { width: 200px; height: 100px; background: red; }

Circle

#circle { width: 100px; height: 100px; background: red; -moz-border-radius: 50px; -webkit-border-radius: 50px; border-radius: 50px; }

Oval

#oval { width: 200px; height: 100px; background: red; -moz-border-radius: 100px / 50px; -webkit-border-radius: 100px / 50px; border-radius: 100px / 50px; }

Triangle Up

#triangle-up { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-bottom: 100px solid red; }

Triangle Down

#triangle-down { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-top: 100px solid red; }

Triangle Left

#triangle-left { width: 0; height: 0; border-top: 50px solid transparent; border-right: 100px solid red; border-bottom: 50px solid transparent; }

Triangle Right

#triangle-right { width: 0; height: 0; border-top: 50px solid transparent; border-left: 100px solid red; border-bottom: 50px solid transparent; }

Triangle Top Left

#triangle-topleft { width: 0; height: 0; border-top: 100px solid red; border-right: 100px solid transparent; }

Triangle Top Right

#triangle-topright { width: 0; height: 0; border-top: 100px solid red; border-left: 100px solid transparent; }

Triangle Bottom Left

#triangle-bottomleft { width: 0; height: 0; border-bottom: 100px solid red; border-right: 100px solid transparent; }

Triangle Bottom Right

#triangle-bottomright { width: 0; height: 0; border-bottom: 100px solid red; border-left: 100px solid transparent; }

Parallelogram

#parallelogram { width: 150px; height: 100px; -webkit-transform: skew(20deg); -moz-transform: skew(20deg); -o-transform: skew(20deg); background: red; }

Trapezoid

#trapezoid { border-bottom: 100px solid red; border-left: 50px solid transparent; border-right: 50px solid transparent; height: 0; width: 100px; }

Star (6-points)

#star-six { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-bottom: 100px solid red; position: relative; } #star-six:after { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-top: 100px solid red; position: absolute; content: “”; top: 30px; left: -50px; }

Star (5-points) via Kit MacAllister

#star-five { margin: 50px 0; position: relative; display: block; color: red; width: 0px; height: 0px; border-right: 100px solid transparent; border-bottom: 70px solid red; border-left: 100px solid transparent; -moz-transform: rotate(35deg); -webkit-transform: rotate(35deg); -ms-transform: rotate(35deg); -o-transform: rotate(35deg); } #star-five:before { border-bottom: 80px solid red; border-left: 30px solid transparent; border-right: 30px solid transparent; position: absolute; height: 0; width: 0; top: -45px; left: -65px; display: block; content: ”; -webkit-transform: rotate(-35deg); -moz-transform: rotate(-35deg); -ms-transform: rotate(-35deg); -o-transform: rotate(-35deg); } #star-five:after { position: absolute; display: block; color: red; top: 3px; left: -105px; width: 0px; height: 0px; border-right: 100px solid transparent; border-bottom: 70px solid red; border-left: 100px solid transparent; -webkit-transform: rotate(-70deg); -moz-transform: rotate(-70deg); -ms-transform: rotate(-70deg); -o-transform: rotate(-70deg); content: ”; }

Pentagon

#pentagon { position: relative; width: 54px; border-width: 50px 18px 0; border-style: solid; border-color: red transparent; } #pentagon:before { content: “”; position: absolute; height: 0; width: 0; top: -85px; left: -18px; border-width: 0 45px 35px; border-style: solid; border-color: transparent transparent red; }

Hexagon

#hexagon { width: 100px; height: 55px; background: red; position: relative; } #hexagon:before { content: “”; position: absolute; top: -25px; left: 0; width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-bottom: 25px solid red; } #hexagon:after { content: “”; position: absolute; bottom: -25px; left: 0; width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-top: 25px solid red; }

Octagon

#octagon { width: 100px; height: 100px; background: red; position: relative; } #octagon:before { content: “”; position: absolute; top: 0; left: 0; border-bottom: 29px solid red; border-left: 29px solid #eee; border-right: 29px solid #eee; width: 42px; height: 0; } #octagon:after { content: “”; position: absolute; bottom: 0; left: 0; border-top: 29px solid red; border-left: 29px solid #eee; border-right: 29px solid #eee; width: 42px; height: 0; }

Heart via Nicolas Gallagher

#heart { position: relative; width: 100px; height: 90px; } #heart:before, #heart:after { position: absolute; content: “”; left: 50px; top: 0; width: 50px; height: 80px; background: red; -moz-border-radius: 50px 50px 0 0; border-radius: 50px 50px 0 0; -webkit-transform: rotate(-45deg); -moz-transform: rotate(-45deg); -ms-transform: rotate(-45deg); -o-transform: rotate(-45deg); transform: rotate(-45deg); -webkit-transform-origin: 0 100%; -moz-transform-origin: 0 100%; -ms-transform-origin: 0 100%; -o-transform-origin: 0 100%; transform-origin: 0 100%; } #heart:after { left: 0; -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -ms-transform: rotate(45deg); -o-transform: rotate(45deg); transform: rotate(45deg); -webkit-transform-origin: 100% 100%; -moz-transform-origin: 100% 100%; -ms-transform-origin: 100% 100%; -o-transform-origin: 100% 100%; transform-origin :100% 100%; }

#infinity { position: relative; width: 212px; height: 100px; } #infinity:before, #infinity:after { content: “”; position: absolute; top: 0; left: 0; width: 60px; height: 60px; border: 20px solid red; -moz-border-radius: 50px 50px 0 50px; border-radius: 50px 50px 0 50px; -webkit-transform: rotate(-45deg); -moz-transform: rotate(-45deg); -ms-transform: rotate(-45deg); -o-transform: rotate(-45deg); transform: rotate(-45deg); } #infinity:after { left: auto; right: 0; -moz-border-radius: 50px 50px 50px 0; border-radius: 50px 50px 50px 0; -webkit-transform:rotate(45deg); -moz-transform:rotate(45deg); -ms-transform:rotate(45deg); -o-transform:rotate(45deg); transform:rotate(45deg); }

<blockquote id=”one’>
   <div class=”arrow”></div>
</blockquote>
Speech bubble bottom
</span></span>blockquote#one {   width: 250px;  background: #e3e3e3;  padding: 25px;  position: relative;  }    #one .arrow {   width: 0;   height: 0;   line-height: 0;   border-top: 30px solid #e3e3e3;   border-left: 60px solid white;   border-right: 10px solid white;   position: absolute;   bottombottom: -30px;   rightright: 30px;  }<span>
speech bubble top
blockquote#two { width: 250px;background: #e3e3e3;padding: 25px;position: relative;}blockquote#two .arrow { width: 0;height: 0;line-height: 0;border-top: 40px solid #e3e3e3;border-left: none;border-right: 30px solid white;position: absolute;bottom: 60%;right: -30px;}
Speech bubble right
blockquote#three { width: 450px; background: #e3e3e3; padding: 25px; position: relative;}#three .arrow { width: 0; height: 0; line-height: 0; border-bottom: 25px solid #e3e3e3; border-right: 50px solid white; position: absolute; top: -24px; left: 20px;}

cgi_wrapper: Per-domain php.ini under php-fastcgi (Plesk 9.5.2 + CentOS 5)

I recently discussed per-directory php directives utilising htscanner, allowing setting values with php_flag and php_value in .htaccess files.

While this is an enormous step forward in term of granular control for the webmaster, it doesn’t allow complete control as some things don’t work when set in .htaccess as I discovered when trying to set apc config values.

The problem stems from being unable to use vhosts.conf to specify php_admin_value as you would running PHP as an Apache module, and having to resort to other methods. I did attempt http://kb.parallels.com/9059, but it was a complete failure, because Paralells neglect to mention that you must be running Plesk 9.5.2+ in order to utilise cgi_wrapper as directed.

I had been avoiding updating Plesk, as last time I’d done so it had mangled quite a few things, but I bit the bullet, and this time the process seems to have been entirely successful.

From http://kb.parallels.com/9059

The hotfix is as follows:

It is possible to use custom php.ini for domains if php as FastCGI mode is used on it. 
It is necessary to apply hotfix. Fix is compatible with Parallels Plesk Panel versions 9.x.

Use the following instruction for applying hotfix.

1. Download hotfix from the attachment

# wget http://kb.parallels.com/Attachments/13985/Attachments/cgi_wrapper

2. Locate file cgi_wrapper

# cat /etc/psa/psa.conf |grep CGI_PHP CGI_PHP_BIN /var/www/cgi-bin/cgi_wrapper/cgi_wrapper

3. Create a backup of this file

# cp /var/www/cgi-bin/cgi_wrapper/cgi_wrapper /var/www/cgi-bin/cgi_wrapper/cgi_wrapper_orig

4. Replace cgi_wrapper with the downloaded one

# cp cgi_wrapper /var/www/cgi-bin/cgi_wrapper/cgi_wrapper

5. Copy php.ini to the configuration directory of domain

# cp php.ini /var/www/vhosts/domain.tld/conf/

6. Change permissions on the configuration directory of the domain

# chmod 0755 /var/www/vhosts/domain.tld/conf

7. Restart apache

# /etc/init.d/httpd restart
Should the download become unavailable, I have included the contents of the updated cgi_wrapper here for convenience:
#!/bin/shdomain=fgrep -m 1 "$UID" /etc/passwd| awk -F: '{print $6}' |awk -F"/" '{print $5}'PHPRC=/var/www/vhosts/$domain/conf/php.ini[ -f ${PHPRC} ] || PHPRC="/etc/php.ini"export PHPRCexec /usr/bin/php-cgi -c "$PHPRC"

PHP File Upload Progress Bar

A pure PHP based (I.E. not Flash or Java based) method of monitoring file upload progress used to be something of a holy grail for web designers for some time, especially for people creating CMS or otherwise handling user provided content. I remember seeing mention of it being on the horizon many, many moons ago, but hadn’t looked into it for a long time. Implementations in the CMS I have used is still very rare – where there is any it is still often Flash.

Installing APC recently, I noted the apc.rfc1867 configuration directive which states:

RFC1867 File Upload Progress hook handler is only available if APC was compiled against PHP 5.2.0 or later.

Aha, so that’s the key is it? Time to investigate again methinks.

I shall at some point be taking a look at

http://www.johnboy.com/blog/a-useful-php-file-upload-progress-meter

and

http://www.johnboy.com/php-upload-progress-bar/

The second is his more recent implementation. At first glance it appears to use an iFrame – well, this is the ajax age, so I hardly think that should be an issue to bring bang up to date.

I shalll be returning to this!