Archive for the ‘source’ Category

Debug phtagr with Netbeans 7.2

September 17th, 2012 Comments off

Following instructions gives you a small HowTo for debugging phTagr code with Netbeans 7.2 and Xdebug on Ubuntu 12.04.

If you like to contribute some code to the phtagr project it is recommended to use a IDE with debugging support. Netbeans IDE is a great and free IDE with a good PHP language support. Combined with the PHP debugger and profiler Xdebug you can execute your code line by line and inspect variables which makes changes and errors easy to handle.

Requirements – Assumptions

  • You have some (php) programming skills
  • You installed and configured phtagr on your local web server like apache
  • You use phtagr source from  phtagr’s git repository

Install Netbeans and Xdebug

  • Download Netbeans 7.2 for PHP from

    $ chmod 755
    $ ./

    and follow the installation wizard (windows like). For detailed installation instruction visit netbeans.

  • Install xdebug via sudo apt-get install php5-xdebug. By default xdebug has a configuration file at /etc/php5/conf.d/xdebug.ini.

Create project

  • Start netbeans (e.g. run /home/sebastian/netbeans-7.2/bin/netbeans if you installed netbeans in /home/sebastian/netbeans-7.2).
  • Create a new project via menu File -> New Project
  • Select PHP Application with existing Source. Confirm by clicking Next
  • Enter your php git repository (e.g. /var/www/tests/phtagr), the project name. Confirm by clicking Next
  • Enter the Project URL. At my machine /var/www is Apache’s web root so http://localhost/tests/phtagr is the correct Project URL. At Index File enter webroot/index.php. Netbeans requires a real file and the main index file of phtagr is in webroot/index.php. Confirm by clicking Next
  • Ensure at Menu Tools -> Options -> PHP -> Debugging that Stop at First line is disabled.

Debug phtagr

  • Run Debug Project (shortcut Ctrl+F5). At the first page phtagr will report an error. But this is necessary to set the correct debug cookie for xdebug. Now you can use your phtagr installation and enter Project URL http://localhost/tests/phtagr.
  • Use breakpoints to intercept the execution of php script. E.g. set a break point at Controller/AppController.php to function beforeFilter function but clicking on a line number. If you reload the page in your browser by hitting F5, netbeans will stop at your breakpoint line.


  • Ctrl+F5 – Start debugger
  • F8 – Step Over
  • F7 – Step Into
  • Ctrl+F7 – Step Out
  • F5 – Continue
Categories: source Tags: , ,

Public API now available!

July 31st, 2010 Comments off

Finally, the code of the open source social web gallery phTagr has now an API page available at The API is extracted from source using the API generator plugin for CakePHP which makes the documentation pretty easy. Futher the plugin provides a nice web interface for all classes.

The phTagr API contains the API of cakePHP and the API of phTagr classes. So if you need a code documentation of a class, controller, view, component, helper, theme, etc have a look at, make use of the search function, and get things quicker done.

Categories: Related Links, source Tags: ,

phTagr 2.1.2 released!

July 11th, 2010 Comments off

2.1.1 phTagr is released! It has a simplified upload function which is enabled by default and replaces the advance file browser. Users have now an upload menu entry where uploaded files are stored in a daily upload directory. ZIP archives are extracted automatically. Uploaded and extracted files are imported and are shown immediately. Therefore, users can upload their media within three clicks and the upload form has now five upload field instead of one.

The next big improvement is the quick search which covers sub word. The quick search of ‘ice‘ returns also media with tags of ‘slice‘ or ‘rice‘.

phTagr is build on top of the MVC framework CakePHP and uses now CakePHP 1.3 instead of CakePHP 1.2. You have to upgrade your CakePHP if you use SVN trunk. See How To Migrate Phtagr for more details.

An admin user can now see the access level of other users and can change these. This feature was requested to handle private or malicious media.

phTagr supports now Dutch as new language – Thanks to Remy Wetzels. See also How To Translate.

Following Tickets where closed since 2.1.1

  • #14 – Automatic media import on upload
  • #63 – Multiple inputs for HTML upload
  • #90 – Wish: search on part of a tag
  • #110 – Admin rights: Change access level of others
  • #89 – Wish: change “Welcome to phTagr” via system preferences
  • #83 – Wrong import of files with UTF-8 multi-byte characters
  • #86 – PEAR path is missing in include_path variable
  • #85 – User with 0 quota, file uploaded shows up in “My Files” even it said “Could not upload”
  • #87 – User can see root of filesystem in “My Files”
  • #91 – Search on unknown string returns “Array” as search key
  • #93 – Shorten the user authentication keys
  • #112 – Broken Unzip functionality

Resize Control PResizeControl for Google Maps

March 20th, 2010 4 comments

This Google map control adds a dynamic resize function to Google’s map API: You can enlarge or shrink the size of your google map via the resize handle in the right lower corner of the map.

The map control PResizeControl is based on map-in-a-box from Wolfgang Pichler (which bases on Dynamically Resize Google Maps With Mouse). Compared to Wolfgang Pichler’s version it is completed as standalone Google Map control. It also embeds the resize handle image and does not need an external image file (only older IE’s below version 8 could not handle embedded data (But IMHO this is a feature – not a bug!). Further you can resize only the height or widht depending on your configuration. Minimum and maximum of height and/or width is also suppored.

<script type="text/javascript" src=""></script>
<!-- Include resize control PResizeControl -->
<script type="text/javascript" src="./presizecontrol.js"></script>
function initialize() {
  if (GBrowserIsCompatible()) {
    map = new GMap2(document.getElementById("map"));
    map.setCenter(new GLatLng(52.521653, 13.41091), 14);
    // Add resize control PResizeControl with default settings.
    map.addControl(new PResizeControl());
<body onload="initialize">
<div id="map" style="width: 450px; height: 250px;"></div>

Note: The PResizeControl is used in the open-source project phTagr – a social photo gallery for its Geo coding and map display. The javascript file ./presizecontrol.js is extracted from the source of pmap.js of the photo gallery phtagr. Updates of PResizeControl will be commited to the phtagr source.

Variables of PResizeControl

Resize modes. Possible values are PResizeControl.RESIZE_BOTH, PResizeControl.RESIZE_WIDTH or PResizeControl.RESIZE_HEIGHT. Default is PResizeControl.RESIZE_BOTH
Minimal width of the map. 0 disables the minimum width. Default is 150.
Minimal height of the map. 0 disables the minimum height. Default is 150.
Maximal width of the map. 0 disables the minimum width. Default is 0 (disabled).
Maximal height of the map. 0 disables the minimum height. Default is 0 (disabled).

More PResizeControl examples

PResizeControl: Resize Width Only

var resizeControl2 = new PResizeControl();
map2.addControl(new resizeControl2);
resizeControl2.mode = PResizeControl.RESIZE_WIDTH;

PResizeControl: Resize Height Only

var resizeControl3 = new PResizeControl();
map3.addControl(new resizeControl3);
resizeControl3.mode = PResizeControl.RESIZE_HEIGHT;

PResizeControl: Minimal Size

var resizeControl4 = new PResizeControl();
resizeControl4.minWidth = 450;
resizeControl4.minHeight = 250;

PResizeControl: Maximum Size

var resizeControl5 = new PResizeControl();
resizeControl5.maxWidth = 450;
resizeControl5.maxHeight = 250;
Categories: Related Links, source, tools Tags: , , ,

Eliminated Software Requirements

January 5th, 2010 Comments off

I am happy to announce with revision r505 that the software requirements are finally reduced to a minimum! phTagr requires now only a basic LAMP:

  • Webserver (tested with Apache)
  • PHP (tested with PHP5)
  • GD or ImageMagick
  • database engine (tested with mysql)

This change improves and simplifies the initial steps to run this great gallery! Further, the installation documentation was updated and improved.

exiftool and ffmpeg are no longer required to run the basic operations. Further the dependend PEAR libraries are now included into the software. The new version could be downloaded as  ZIP archive or TAR ball – happy  testing.

Without exiftool the meta data like tags, categories or geo location are imported from photos but not be written back to them. Without ffmpeg only flash movies could be imported. If you have ffmpeg other video formats are supported and the videos are automatically converted from AVI, MPEG or MOV to the flash file format. ffmpeg also creates the a video preview. If now preview exists a default image is shown.

First plugin released: DupFinder

August 11th, 2009 Comments off

As by today the first phTagr plugin is released: The DupFinder plugin finds media duplicates and merges the copies to one master media.

This plugin is very helpful if first lower quality media are uploaded to phTagr and the original data are uploaded on a later stage.

Example Scenario: Bob is traveling and want to upload his new vacation images as quick as possible. However, the Internet connection at the NetCafe is slow and upload of all original media is time consuming. Bob selects the best images and creates preview of it, which he uploads to phTagr. While Bob continue to travel his friends can tag the image and write comments.

When Bob arrives at home he uploads the original media and merges the tags and comments of the previews to the original.

See the wiki page of DupFinder for more details.

Categories: announce, Related Links, source, tools Tags:

Merged branch phtagr-media-schema

April 25th, 2009 Comments off

The branch phtagr-media-schema was merged to the trunk successfully. The new database schema fits more the database relation between files and media and changes the model Image to the model Media.

Upgrade your phTagr instance

The database must be upgraded to the new schema. However, the new merged trunk comes with a handy shell script upgradeMediaSchema which handles the database upgrade and data migration. Update your phtagr code of trunk via svn and change to your phtagr directory and execute the shell script by ‘../cake/console/cake -app phtagr upgradeMediaSchema upgrade

phtagr$ svn up
phtagr$ ../cake/console/cake -app phtagr upgradeMediaSchema
Schema Upgrade Shell Script for Media Schema
Help screen
    Upgrade schema to media schema
phtagr$ ../cake/console/cake -app phtagr upgradeMediaSchema upgrade
Schema Upgrade Shell Script for Media Schema
Prepare upgrade...
Upgrade schema...
Migrate 132 media...
Finalizing upgrade...
All done. Enjoy!

Reasons for a new Schema

The old schema uses only one table for a image/media which includes also the file information. Since a media is not only restricted to one file, this schema does not model the reality well. E.g. a media could be a video and the video thumb file or an image with a sound memo attached to it. Since now, phTagr uses also the term media instead of image.

The new schema splits the old table images to the table media and table files while the model Media gets a HasMany relation to the model File.

Other changes

The merge comes also with an improved import functionality. phTagr has now a Filter Manger which handles the import and export of a media and/or metadata. Currently there are three different filters:

  • Image Filter (JPEG)
  • Video Filter (AVI, MOV, MPEG, THM)
  • GPS Filter (LOG)

New filters could be implemented more convenient (e.g. a Sound Filter which attaches a sound memo to a media). The Filter Manager supports a priority based import that a video thumbnail is read after the video file.

Database Schema Changed

October 30th, 2008 Comments off

By revision 386 the database schema of phtagr changed and must be changed manually! Please update your phtagr source to the latest version and rename the table ‘configs’ to ‘options’. Execute following mySQL command for your phtagr database. Please consider your table prefixes if you have it.

mysql> RENAME TABLE 'configs' TO 'options';
Categories: Related Links, source Tags: ,

Cipher Behavior

August 11th, 2008 2 comments

If your want to cipher critical data of your cakephp model like passwords or emails, the cipher behavior of phtagr handles the symmetric encryption and decryption on the fly. For the symmetric encryption the cipher BlowFish is used, but other symmetric encryption algorithms are possible. This behavior is very useful if your data should not be stored in clear text in the database (e.g. external database connections).

The behavior could be configured simple for your needs. By default the behavior ciphers the password Model property.

The Behavior

First of all the PEAR package of BlowFish must be installed. This packages comes with an PHP implementation of BlowFish and does not required the MCrypt PHP extension. If the MCrypt extension is installed, the PEAR library will use it.


As mentioned above, the behavior ciphers the password property (table column) by default.


class User extends AppModel
  var $name = 'User';

  var $actsAs = array('Cipher' => array());


Following example saves the User model. Submit your login data via a formular. The $this->data might looks like:

    [User] => Array
            [id] => 1
            [username] => admin
            [password] => MySecret

In the controller you save your submitted data:



Now every time a User is saved, the password will be ciphered. The behavior only ciphers the properties, if the values do not start with the ciphered prefix $E$.

The ciphered data looks now like:

    [User] => Array
            [id] => 1
            [username] => admin
            [password] => $E$fIOGYbF6jQMXOOa5umzgXGWBfo7roAuk

By default the behavior does not decrypt the properties and the decryption must be called explicitly:


$user = $this->User->findByUsername($this->data['User']['username']);
if ($user['User']['password'] == $this->data['User']['password']) {
// successful login


Automatic Decryption

If you want to decrpyt all data automatically (might cost some CPU cycles and slows down your requests), you can configure the cipher behavior:


class User extends AppModel
  var $name = 'User';

  var $actsAs = array('Cipher' => array('autoDecypt' => true));

Model Properties

By default, the cipher behavior encrypts and decrypts the model property (table column) password. Other fields are also possible.


class User extends AppModel
  var $name = 'User';

  var $actsAs = array('Cipher' => array('cipher' => array('password', 'email', 'creditnumber')));

Custom Key

By default, the cipher behavior uses the Security.salt as cipher key. If you require a custom key, you can set in on the configuration:


class User extends AppModel
  var $name = 'User';

  var $actsAs = array('Cipher' => array('key' => 'MySuperSecureCipherKey'));

Note: Since the Security.salt is used from your configuration config/core.php and cipher key, it is very important to change the default value of Security.salt! Otherwise the encryption is not secure!

  * A random string used in security hashing methods.
      Configure::write('Security.salt', 'NewSecureAndUnknownSecuritySaltForCake');

Salt and Padding

Before a value is encrypted it will be packed and padded. The clear text before the value is ciphered is surrounded by a salt and padded to a specific length block to $salt.$value.$padding.$salt.

The salt is used to avoid same encrypted results of same values. It is also used to discover the correct decryption. The padding is used to hide the original value lengths. By default, the salt and padding have the length of 4. This could be changed in the behavior configuration.

Note: The salt should be at least 2 characters long. Otherwise the successful decryption could not be detected well (apart of the diversity of the ciphered value).


class User extends AppModel
  var $name = 'User';

  var $actsAs = array('Cipher' => array('saltLen' => 6, 'padding' => 8));


To distinguish between ciphered value and a clear text value, the ciphered value has a prefix. The default prefix is $E$ but could be change in the configuration.


class User extends AppModel
  var $name = 'User';

  var $actsAs = array('Cipher' => array('prefix' => '$ciphered$'));


The behavior dumps log message to the standard log if something goes wrong. Please watch these entries while developing with the cipher behavior.

Changing Security.salt

If you using this behavior and some data is already ciphered but have to change the Security.salt, you need to decrypt all the data with the old Security.salt, save the clear text and encrypt all values with the new Security.salt.

Decrypt all values with the old Security.salt value:


class User extends AppModel
  var $name = 'User';

  var $actsAs = array('Cipher' => array('noEncrypt' => true, 'autoDecrypt' => true));

  function clearCipher() {
    $users = $this->findAll();
    foreach ($users as $user) {
      $this->id = $user['User']['id'];



Encrypt now all values with the new Security.salt.


class User extends AppModel
  var $name = 'User';

  var $actsAs = array('Cipher' => array());

  function cipherAll() {
    $users = $this->findAll();
    foreach ($users as $user) {
      $this->id = $user['User']['id'];




July 16th, 2008 Comments off

Screenshots of phtagr where uploaded to the demo page and can be viewed by category screenshot. You are able to see more screenshots of older versions if you login with username demo and the password demo08. Have fun watching them.