Thursday, July 9, 2009

How to solve SVN conflicts. Netbeans SVN plugin tools

SVN [official site] is the most powerful open source version control software at the moment.

Introduction (for who doesn't know it at all)
Basically, SVN is a server/client system. The server that contains the repository (source code of our application).The clients get the source code (CHECK OUT) or only the new files (UPDATE) from the server. The opposite operation is called COMMIT, and consists in sending new files to the server. Every commit generates a new repository revision; SVN mantains the content of the files in every revision with the aim not to lose code and the possibility to undo code changes.


[http://telin.ugent.be/~slippens/svn-intro/fig/vc-concepts.png]


How to solve conflicts
SVN works allowing clients to get files without any locks ! It means that sometimes you may commit a file, but another client has committed the same files before. This is a conflict ! SVN requests to you to manually resolve the conflict, in order not to lose the code written by the other client (correct behaviour !).

How can you solve the conflict ? There are many solutions:
  1. Delete your local changes (REVERT). your code will be overwritten by the newest file in the repository (written not by you). Do it if you are sure you want to delete your changes.
  2. Keep ur changes and commit. Do UPDATE and SVN client will be overwrite the file (with your code between "[[[[[[[[[[[ .mine" and "=======", and the code in the repository between the second marker and "]]]]]]]]]]]]] .rN"). SVN client will also create a copy of your changed file (file.ext.mine), the original you worked with (file.ext.rM) and the newest file in the repository(file.ext.rN).

    now:
    2.1 - Analyze differences and create a new file (recommended)
    analyze the differences (DIFF) between files, then modify the file.txt, set the conflict resolved (RESOLVE, after that SVN client allows to commit) and COMMIT.
    - 2.1.1 - For small files, you can edit directly file.txt (mind deleting the markers) and obtain a new file (operation called merging). Then set resolved and commit.
    - 2.1.2 - For bigger files, it's a good solution to use a tool for file comparison (DIFF), for example between file.ext.mine (your modified file) and file.ext.rN (the newest in the repository). Then save the new file as file.ext, set resolved (RESOLVE) and COMMIT.

    or

    2.2 - Overwrite the current file in the repository with your changes (be careful !). To do it, copy file.ext.mine to file.ext, set resolved(RESOLVE) and COMMIT
Netbeans SVN plugin
Netbeans [official site] (free java-based IDE for JAVA, J2SE, C/C++, Ruby and PHP) works with the collab.net SVN command line client and provides a useful tools to manage the SVN operation on the source code.
How to do the operations above with Netbeans 6.7 (a message error dialog appears in case of conflict). Filename: file.ext. All the commands are available with right click on the file.ext, then "Subversion".
  1. "Revert modification..." and "Revert Local Changes"
  2. "Update" (the file will be coloured "red", it' necessary before 2.1.1 or 2.1.2), then:

    2.1.1 (imho the best solution). Manually merge the changes and create a new content for the "red" file (mind removing markers). "Resolve Conflicts" (now the colour will be blue, and the temporary files will be deleted), then "Commit".

    2.1.2 (Netbeans solution, not the best solution imho) ."Show changes", double click on the bottom panel "Subversion" on the line with the "red" file (status=local conflict). In the main window, you will see the local file (left) and the remote (right). Netbeans will show line by line the conflicts (different code in the same line), and you can choose the line to have in the new file by clicking in "Accept" on the left or on the right. then "Commit".

    Netbeans/manual alternative to 2.1.2: Select file.ext.mine and file.ext.rN (where N is the highest), then tight click, "Tools" and "Diff". Now create a copy with the rigth code, then copy all the content in file.ext, "Resolve Conflicts" and "Commit". It Looks complicated but maybe it's the best in case of lots of conflicts.

    2.2. copy the content of the hidden file file.ext.mine to file.ext (the red one), then "Resolve Conflicts" and "Commit" (strongly not recommended !!).
How to reduce conflicts
  1. Do "Update" before start changing a file !! You will reduce the possibility of conflicts
  2. Do more "commit", for example every 30min instead of 2h (choose it in according on the number of the clients working on the same file).
  3. In case of merging you will probably have to contact other developers to be sure about merging in case your code to commit is much different. Arrange on files with other developers (you'll avoid to have lots of conflicts when committing)
  4. Other suggestions ?

post moved here: solve SVN conflicts netbeans

SVN to FTP/web on Windows with svn client+winscp

Post moved to the new blog: Svn to ftp

How to deploy a web application and to quickly deploy future updates/patches from a SVN repository into a remote web server (only with ftp access and without possibility to setup svn client) ?
Here are my suggested steps:
  1. export SVN (that is obtain the last repository without ".svn" directories)
  2. process the exported SVN (e.g. adding or deleting files before uploading)
  3. upload (1st time) or synchronize (update new files to the remote webserver)
  4. chmod folders (only 1st time or new folders)
All the 4 steps are executable from a handy shell script using:
Example of a svn to ftp batch in Windows (with subversion client and winscp, both are free):
  1. Create a profile with winscp, and set local folder "c:\temp\site1" and remote folder (e.g. "/httpdocs" ).
  2. Write a batch file svn2ftpsite1.bat
    set PATHFOLDER=c:\temp\site1
    svn export svn://1.2.3.4/trunk %PATHFOLDER% --force
    del %PATHFOLDER%\file-not-to-upload\* /q
    copy c:\other-folder\file-to-add-to-site1 %PATHFOLDER%
    c:\path-to\winscp.exe /console "open winscp-profile" "synchronize remote" "chmod 777 uploads" "close"
  3. Save. And launch when you want to update the remote site (don't forget to commit the svn before)
Read the winscp online scripting manual for further information.
Note: if the web server (Linux I think!) can access the SVN repository, has SSH server and subversion client, you can export directly the repository in the web server.
Note: if the web application works correctly, take note of the current repository version. in case of future problems you will be able to export that revision (svn client command line option) and restore the online web site.
Note: If you can install svn client in the web server and the repository is visible from the web server, you can use "check out" and "update" directly in the webserver, then use an apache rule to hide .svn directories
RewriteRule /\.svn /errorpage

Monday, July 6, 2009

Unit testing: a brief introduction to PHPUnit

Every software needs testing [wiki], starting with testing software units [wiki] (the smallest parts of a software, that are functions and classes).
Briefly, a test is a code which runs and ensure that our code behaves as expected.
Here is an example of a test to check a mail validator function:
print ( validateEmail("test@site.com") && !validateEmail("test@site") && !validateEmail("@site") && ! validateEmail("with space@site.com") && !validateEmail("test@site.commm") && validateEmail("a-b_c@sub.site.com")) ? "function looks OK":"test fail";
Obliviously, we need more testing features (first of all to understand which test fails). So, let's use an existent tool to make and to run tests effectively and easily.



PHPUnit is a free powerful easy-to-use framework to manage PHP Unit tests.
  • Installation: setup with pear (recommended) or download the source archive
  • Test writing: include the main class, extend the PHPUnit_Framework_TestCase class and write inside one method for each unit test. Each method should call an existent superclass method, such as assertEquals($a, $b), assertTrue($a), etc... [online manual]
  • Run: use a command line tool and type
    phpunit fileWithTests.php
    PHPunit will automatically run all the tests (=methods written in the class) and will show the detailed results of each one.
This is only a summary, consult the PHPunit official online manual to explore all the features.
One personal suggestion: write the tests BEFORE writing the code ! You will save time and write a better code.

Wednesday, July 1, 2009

PHP 5.3.0 released

I don't like writing posts for every new PHP release as other PHP blogs, but this time it's worth doing it !
PHP 5.3 implements important new OOP features:
  • namespaces
  • late static binding and __callStatic() !
  • anonymous functions
  • Phar extension (pratically, it's the same as JAR for java files)
Forother improvments and bug fixing, see change log


Saturday, June 27, 2009

Debugging techniques with free tools [updated 30 June]


  • Netbeans PHP 6.* + Xdebug + Firefox (with netbeans extension to server debug with javascript) !
    howto configure with
    Wamp 2.0h:
    - download
    php_xdebug-2.0.4-5.2.8.dll into the Wamp folder
    - open port 9000 in the firewall
    - edit php.ini adding

    [xdebug]
    zend_extension_ts="c:/wamp/bin/php/php5.2.9-2/ext/php_xdebug-2.0.4-5.2.8.dll"
    xdebug.remote_enable=on
    xdebug.remote_handler=dbgp
    xdebug.remote_host=localhost
    xdebug.remote_port=9000
    xdebug.remote_mode=req

    - now, let's debug the script with Netbeans choosing "Server side PHP with client side Javascript". Netbeans will install an extension for firefox which will allows to launch the script in the server (localhost). The extension will "pause" (thanks to extension and javascript) the server execution and it will be possibile to debug with netbeans when the breakpoints (put them in valid lines) will be reached.

    See the screenshot: array debug



    Note: obviously it's possible to debug the script directly in the php command line (no browsers is needed).

    Tested with Netbeans 6.7, Wamp 2.0h

    see official wiki

  • Eclipse PDT + Xdebug ! both are free. In Eclipse you can set breakpoints, then run the application; when breakpoints are reached, Eclipse will show variable values (tree explorer for multi-level arrays )
  • debug with php code
    function debugAll(var_dump($GLOBALS));
    print
    "[pre]"; debugAll(); print "[/pre]";
  • zend debugger [...]
  • [...]

Tuesday, June 23, 2009

Symfony: password hashing and login

It's a good practice not to keep the clear values of the passwords in the db, but to store only their hash values.
You can do login operations comparing the hash value of the inserted password with the stored hash value.

How to do it with Symfony 1.2, propel ORM, MD5 hashing:
  • db schema: Use a VARCHAR, length must be at least 32
  • validator:
    - require a minimum length (ex: 3 chars) or (better) regexp validation
    - use a widget Schema password
    $this->widgetSchema['password'] = new sfWidgetFormInputPassword (array(
    'always_render_empty' => false, //IMPORTANT !!
    ));
  • model: modify the method setPassword($v) assigning the md5 value:
    public function setPassword($v)
    //set md5 password if there is a new inserted password
    if (strlen($v)!=32) //if is not a md5 value, convert into it (*)
    $v = md5($v);
    return
    parent::setPassword($v); }
  • To check the login data, use the md5 value in the post action :
    $criteria->add(UsersPeer::USER,$request->getParameter('user'))
    ->
    add(UsersPeer::PASSWORD,md5($request->getParameter('passwordlogin')));
From now, only the hash value of the passwords will be stored.
The CRUD operations will work.

(*) Note: it won't work if the clear password is 32 chars length.

Monday, June 22, 2009

LAMP documentation links

PHP
SYMFONY v1.2

MYSQL
LINUX

Sunday, June 14, 2009

JSON generation with PHP and parsing with jQuery

JSON [official site][wiki] is a data interchange format (similar to XML, but simpler), often used for WEB 2.0 applications to load structured data with AJAX HTTP calls.
- PHP offers functions to encode and decode JSON from/to a PHP value.
- jQuery includes a function (getJSON) to parse HTTP resource with JSON data.

JSON pseudo grammar
#json block: comma separated couple key: value
JSON_BLOCK = { KEY1: VALUE1, KEY2: VALUE2, ..., KEY_N: VALUE_N }
#key must be a string (example: "abc123")
KEY_N = string
# value must be a native type, or array of values or json_block (recursive)
VALUE_N = string | number | true | false | null |
| [
VALUE_N,..., VALUE_N] |JSON_BLOCK

Minimal example:
//note: "less/greater than" symbols are replaced with square brackets because of blogspot limitation

/* json.php - json generation */
print json_encode( array(
"title" => "products",
"items"=> array(
array(
"id"=>"1","title"=>"1st"),
array(
"id"=>"2","title"=>"2nd")
)));
/*
result ("items" key contains an array with two values, each one is a block).
{
"title":"products",
"items": [ {"id":"1","title":"1st"}, {"id":"2","title":"2nd"} ]
}
*/


/* page.html - call JSON resource (ajax with jQuery) and write into the DOM*/
[script src="jquery-1.3.2.min.js" ][/script]
[
script]
$(
document).ready(function(){
$.
getJSON("json.php",
function(
data){
$.
each(data.items, function(i,item){
$(
"[h1]").text(item.id).appendTo("#main");
$(
"[h4]").text(item.title).appendTo("#main");
});
});
});
[/
script]
[
body]
[
div id="main" ][/div]
[/
body]

//output:
[body]
[
div id="main"
[h1]1[h1] [h4]1st[h4]
[
h1]2[h1] [h4]2nd[h4]
[/
div]
[/
body]

Wednesday, June 10, 2009

MySQL : version differences notes (draft)

Relevant features added in Mysql 4.0
  • FULLTEXT search
  • INNODB tables (and on [delete|update features]
  • UNION statement
  • TRUNCATE TABLE statement
  • multiple table delete and update
Relevant features added in Mysql 4.1
  • Subquery (nested query) supported
  • "CREATE table LIKE table 2" syntax supported
  • added storages:
    - EXAMPLE (for developers)
    - NBCLUSTER (table partitioned over many computers)
    - CSV (comma separated values storage)
    - BLACKHOLE (it doesn't store data)
  • added command "HELP"
  • API improved (multiple statement in a single call)
  • "INSERT ... ON DUPLICATE KEY UPDATE" syntax added
  • GROUP_CONCAT() added
Relevant features added in Mysql 5.0
  • BIT data type
  • Math precision improved
  • SQLSTATE error message
  • TRIGGERS (limited support)
  • VARCHAR max length increased to 2^16 byte (64 Kb)
  • "greedy" optimizer, "merge index" to improve join performance
  • Improvement of "NOT IN"
  • VARCHAR more efficient
  • INNODB less disk space usage (-20%)
  • Added storages ARCHIVE and FEDERATED
Relevant features added in Mysql 5.1
  • Partitioning (tables in different locations)
  • plugin API to load/unload components at runtime
  • event scheduler (like cronotab)
  • customizable MySQL logs (to file or tables)
  • XML and XPath functions
Relevant features added in Mysql 6.0
  • UTF8 (4 bytes), UTF16 and UTF32
  • BACKUP_DATABASE and RESTORE statements (to backup)
  • performance optimization for subqueries and joins
  • transactional locks
  • LOAD_XML statement

Monday, June 8, 2009

INNODB storage engine: notes

Advantages
  • transactions
  • row-level locking
  • foreign key constraints ! and behaviour
    ON [DELETE|UPDATE] [RESTRICT|CASCADE|SET NULL|NO ACTION|SET DEFAULT]

Disadvantages
  • INNODB does NOT support FULLTEXT index (MyISAM does)
  • not initial value for auto_increment keys

array_walk example

bool array_walk ( array &$array , callback $funcname [, mixed $userdata ] )

/* example !!
* transform array with other arrays as elements into an array with simple elements
* array trasform !
*/

$ar = array( array(1,2), array(10,20), array(100,200) );
function
sum(&$ar) //NOTE: Argument By reference
{
$ar = $ar[0]+$ar[1];
}

array_walk($ar, "sum");
print_r($ar);
/*
Array
(
[0] => 3
[1] => 30
[2] => 300
)
*/

PHP security: input validation and XSS

for lots of reasons, security included, it's very important to validate all user input and protect our application from intentional or accidental wrong inputs.

First of all, here are some advices
  • don't use register_globals ! A malicious user may change value of script variables simply modifying the query string
  • don't use $_REQUEST: possibile loss of data. Use $_GET and $_POST

Number validation
use cast operator to validate numbers. If the malicious input is "'); drop table users", the casted (int) value will be zero.

When you use casting, remember the maximum size of int to prevent overflow. you may use (float) instead of (int).

Remember: the decimal separator is the point, not the period !
A numeric value with period (,) is not numeric, and a float casting will be delete the decimal part.

String validation
First of all, the input may contain stressed letters (French and Italian languages do, for example à,è,ì,ò and ù).
Use
set_local(LC_CTYPE,"french")
The stressed characters will be converted into the corresponding non-stressed characters (à->a, è->e, etc...).

To validate string inputs, use regular expressions !
ereg($patter, $string) // or eregi: same arguments but case insensitive
example:

if (ereg("^[0-9]{5}$", $_POST['postcode'])!==false) { /*postcode valid*/ }

"^[0-9]{5}$" means: string that contain 5 characters, each must be a number
don't forget "^" and "$" , or "a12345b" will be considered valid.

Use regular expression to validate various type of input: e-mails, URLs. For further details, php.net examples and google !

File uploads
as second argument of
move_uploaded_file ( string $filename , string $destination )
use basename($_FILE["fieldName"]["name"]) to increase security
$filename must be $_FILE["fieldName"]["tmp_name"]

Don't trust $_FILE["fieldName"]["type"]
If you expect a image, use getimagesize(). If isn't an image, the return value will be FALSE

If the size of the $destination file is different form the size of the temp file ($filename), delete it !!

Do not use magic quotes !
Magic quotes doesn't escape correctly all the special characters !
it's better to use specific db functions, such as
mysql_real_escape_string()

Pay attention to the current PHP configuration, you may do a stripslashes to $_GET data if the magic quotes are enabled. Use the get_magic_quotes_gpc()

Do not allow the user to modify serialized data !
A malicious user may be change and array with 100 elements a:100:{} to an array with millions of elements (it requires lots of memory).

If you need to pass serialized data, you should use a two-way cipher algorithm with key.

XSS
Cross site scripting allows users to insert malicious code in frontend via form submit. When the result page with the user data will be displayed (examples: weblog comments or site guestbook), the code will be executed or shown.
Examples of malicious inputs:
  • [? passthru("rm -rf *"); ?]
  • [iframe src="http://mysite.com/banner.php" ... /]
Some tips:
  • Convert characters to html entities. the "less and greater than" will be converted in HTML entities preventing not-expected HTML formatting or PHP code execution
    pho function: htmlspecialchars() //converts "ampersand", "double and single quote", "less and greater than" into HTML entities
  • Pay attention to quotes or double quotes if you compose tag attributes with user's data:
    print "[a href='{$_GET['link']}']text[/a]";
    if $_GET['link'] is: #' onclick='alert('malicous js code')' title='
    the result of the link will be execute a user-defined javascript
  • If the HTML tags are not allowed, you can use strip_tags() and remove all the tags from the user data. Note: strip_tags() does not convert special chars !
  • To only remove attributes to user submitted tags, use preg_replace()
  • If the user data is a URL, remember to check that it will not start with "javascript:" to prevent javascript code, or (better), parse with eregi()
  • to obtain a IP-based accesscontrol, you should also consider the proxy. If the user uses it, the real IP is contained in the variabile HTTP_X_FORWARDED_FOR, and validate it by using ip2long(), then long2ip() and check if the IP remain the same
  • HTTP_REFERER is not reliable, some browsers don't send it

Design Pattern: Strategy

Strategy is a way to encapsulate, manage and interchange (also at runtime) algorithms.
In the following example, we have three classes (A,B and C) that implement an interface with the method f().
The class AlgoContainer must be initiated by passing the object (external instantiation) or the class name (internal instantation).


Interface StrategyInt
{
public function f();
}

class A implements StrategyInt {
public function f() { print "A:f()"; }
}

class B implements StrategyInt {
public function f() { print "B:f()"; }
}

class C implements StrategyInt {
public function f() { print "C:f()"; }
}

class AlgoContainer {
private $strategy;
private $name;
public function __construct($s){
if (is_object($s))
$this->strategy = $s;
else
$this->strategy = new $s();
}
public function doF() {
$this->strategy->f();
}
}

//Usage 1 (external instantiation):
$ac = new AlgoContainer(new A);
$ac-> doF();

//Usage 2 (internal instantiation):
$ac = new AlgoContainer("A");
$ac-> doF();

Design Pattern: Decorator

Decorator is similar to Proxy.
Basically, decorator is an extension (or wrapper) of the original class (component) and adds features.
A decorator contains a pointer to the component class (initialized by the constructor), and the methods of the component overridden.

Example:


class ImgComponent {
private $src;
private $alt;
public function __construct($name, $src) { /* assign to properties*/ };
public function getHTML() {
return "[ img src="{$this->src}\" alt=\"{$this->alt}\" /]";
}
}

Let's write a decorator:


class ImgWithCaption extends imgComponent
{
private $caption;
private $imgComponent;
public function __construct(&$img, $caption) {
$caption->imgComponent = $caption;
$this->imgComponent = &$img;
};

public function getHTML() {
return "<div><div>{parent::getHTML()}</div>
<div> $caption</div></div>";
}
}

Design Pattern: Adapter

The Adapter design pattern is basically a wrapper, that is a class which provides methods to access to another class.
It's commonly used to normalize incompatibile interfaces.
It's similar to Proxy pattern, but it's a little different. Proxy includes an object and controls accesses to it; Adapter provides an interface to the object, usually by inheritance.



class A {
public static function sort(array $ar) { ... }
}

class B {
private $ar;
public function __construct() {}
public function sortElements() { ... };
public function returnArray() { return $ar;}
}

Now we can extend B and provide the same interface as A



class BAdapter extends B {
public static function sort(array $ar) {
$b = new B($ar);
$b->sortElements();
return $b->returnArray();
}
}

now we can use A and B2 in the same way:



print_r( A::sort(array(3,2,4)) );
print_r( BAdapter ::sort(array(3,2,4)) );
 

PHP and tips|PHP