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注入攻击,改变密码