Tuesday, March 3, 2009

Symfony VS Struts in Java

Alvaro has a very nice article about symfony performance and features. I just commented over it. it is a bit long, so i leave a copy here.

This article is about Symfony in php and Struts in Java. (they are compared in the same order that Alvaro did in his article. )

compared with struts(the mvc framework in Java), i like symfony more. Because it's easier to use and faster to implement. Maybe we would give thanks to the agile nature of PHP.

But both of them have some same features more or less:

the Factories: In struts 1, it depended on the well-form nature of java. you can extend or implement classes from the framework core classes. With struts 2, it uses the famous "Spring" lib(optionally , xwork has his own also). The concept of Ioc (inverse on control) give developers a better chance to extend and replace the logic of the original framework without changing any code. actually ioc is everywhere in struts 2 from populating request parameters to actions to getting a DAO object.
If symforny could introduce Ioc, i think it will be more attractive.

Filter Chain: 5 years ago,(struts 1 for instance), we just used filter in Java. here filter is a real filter which basically pre-excute some logic before the main one. But in struts 2, it changes the name to interceptors (interceptor chain) which do the same as "Filter chain" in symfony.
But what can be improved is : symfony should have a interface-like class (maybe abstract class) who contains 2 method : preExecute() and postExecute(), then any subclass 's logic is much clear. Since i've seen some bug caused by putting post-execute-logic wrongly before $filterChain->execute(); by mistake.

Configuration Cascade: very nice feature. struts should learn more from this(to improve at least).
But now grails (something like symfony,rails in Groovy running in JVM) has this. btw rails 1.2 's performance is much better than before.

Plugin: as developer, u can make your own plugin easily for both frameworks. and the plugin repository has a lot of nice off-the-shelf plugins.
since symfony auto-load mechanism is not as robust as java's, it will loose for performance sake.

Controller adaptability: as said before, with Ioc you can easily extend it to meet your need.

View: same as Controller. in java, you can also choose which tech you would like to render the page. like freemarker, Velocity, or the traditional JSP page. very flexible, right?


why i like symfony more:
1. it has command-line utilities which speed up development and save you from the boring configurations and machine steps.
(grails has the same functionality, so i like grails as well :))

2. symfony cooperates very well with html tags and Ajax. i have bad impress of ajax support in struts and not good experience with tags. Symfony does it really good. Especially for ajax support, the built-in is for prototype, and you can easily switch to jquery using plugin.

there is a lot to say, like the model level, performance tuning, memcache......

hope we can talk more shortly.

Wednesday, February 4, 2009

301 in header doesn't work, return 200 instead

in one opensource project, at almost end of the script , it says
header("Location: $url", 0, 301);exit;
basically, it would work as expected.

but as result, the page doesn't redirect to new page. lookin deeply this response returned 200 instead of 301.

(hacking...searching.....)

in some place before the one above, there is
header('Status: 200 OK');
so this one stops later 301. But why 301 doesnt overwrite 200.... check the doc it says it will replace similar XXX. so after replacing "header("Location: $url", 0, 301);" with
header("Location: $url");
header('Status: 301 Moved Permanently');
it works fine.

///////////////////////////////

in some cases, it needs to determine if it's cgi or not
else if (SAPI_NAME == 'cgi' OR SAPI_NAME == 'cgi-fcgi')
{
header("Location: $url");
// Call the status header after Location so we are sure to wipe out the 302 header sent by PHP
header('Status: 301 Moved Permanently');
}
else
{
header("Location: $url");
header('HTTP/1.1 301 Moved Permanently');
}

cgi gives greater security, it runs under certain user's privilege, but slow (for shared server);
module is faster but runs under the same permission of web server.

Monday, February 2, 2009

symfony 1.2 propel-build-model Bus error

run 'symfony propel-build-model' ends with 'Bus error'

if it doesnt complain your libs, you can go to your scheme.yml file.

i found this is cause by one field type in db with defual value:

i have a column called 'created_at' of type: timestamp with default value 'CURRENT_TIMESTAMP'. this is on mysql level. well enough!

run 'propel-build-schema'

you will get
created_at: { type: TIMESTAMP, required: true, defaultValue: CURRENT_TIMESTAMP }
then, run 'propel-build-model', you would get 'Bus error'

propel generator might not know 'CURRENT_TIMESTAMP'. after removing this from scheme.yml, you can run that script smoothly.

good luck. everytime when you get problems, just look back. the BACK at this moment is so called 'experience'.

Friday, January 30, 2009

symfony 1.2 upload file

symfony 1.2 上传文件

after hacking on 'uploading file' using symfony 1.2, i come here to blog this experience.

compared with 1.1 , 1.2 uses sfForm , sfValidatorFile to process uploading. But from my view, i like the way in 1.1 much more. 1.1 is doing what human usually think it should be.... i mean reasonable ...

i havent got it working with form and the sfValidatorFile. i will spend more time on it when i am unplugged.......

i dont like the concept of "Form". It came with Struts(Java) 1 , but even if the Form in Struts is better than the one in symfony, the concept of "form" has been removed from Struts 2. ppl complain about the "FORM" and just dont like it. so Struts2 elegantly discards "form" by using spring + pojo.

how to acheive uplaoding in 1.2 using deprecated 1.1 methods?

1. in config/ProjectConfiguration.php

$this->enableAllPluginsExcept(array('sfDoctrinePlugin', 'sfCompat10Plugin'));
remove the sfCompat10Plugin from it to enable 1.1 methods.

2. copy and reuse these codes
if ($request->hasFiles()) {
foreach ($request->getFileNames() as $uploadedFile) {
$fileName = $request->getFileName($uploadedFile);
$fileSize = $request->getFileSize($uploadedFile);
$fileType = $request->getFileType($uploadedFile);
$fileError = $request->hasFileError($uploadedFile);
$uploadDir = sfConfig::get('sf_upload_dir');
$request->moveFile($uploadedFile, $uploadDir.'/temp/logo/commu/'.$fileName);
}
that is all. is that reasonable? :)

Wednesday, January 21, 2009

Sql injection attack , how weak is your application ....

we've been working on this new version of the big website for more than one and a half year. We all know the potential bug in out code, so we need to be careful , careful and more careful.....

Recently when i went through the code, i run into one snippet which caught my eyes:

$sql = 'UPDATE user SET password="'.$password.'" WHERE email="'.$email.'" ';
$stmt = $con->prepareStatement($sql);


this a naked sql, which just update the password for the user's email access. No wrong with it, it works fine.
But where the magic comes is when we choose a password like 6" -- " , all the user's password was changed by me.
This is so called SQL injection attack, (SQL 注入攻击) ,Let's assume we have 1 million user in our website. Now i can change all these 1 million user's password as i want. even more , i can do anything with the db operation.

the sense behind it is the '--' which would be considered as comment character in db operation. anything following '--' would be ignored, other words: anything before it would be executed....;)

so.... how to avoid it?

use this:

$sql = 'UPDATE user SET password= ? WHERE email= ? ';
$stmt = $con->prepareStatement($sql);
$stmt->setString(1, $password);
$stmt->setString(2, $email);

with this, the prepared statement and positional parameter will handle '--', and by pass this attack.

Conclusion :

never use the naked sql by yourself. use OR mapping or prepared statement with named or positional parameter instead.

sql注入攻击,改变密码