An example web application demonstrating usage of Zend_ProgressBar and jquery progressbar for monitoring progress of file uploads in Zend Framework 1.11.3.
Since file uploads are done to the folder APPLICATION_PATH/uploads, the application tries to create this folder if it does not exists. For this reason APPLICATION_PATH should be writable, or uploads folder created manually with necessary rights. The application also requires 'uploadprogress' PECL package since it uses 'uploadprogress_get_info' function for getting the information about upload progress.
The source code is at GitHub. Most action happens in indexController.php and index.phtml.
i.e. some stuff and junk about Python, Perl, Matlab, Ruby, Mac X, Linux, Solaris, ...
Showing posts with label Zend Framework. Show all posts
Showing posts with label Zend Framework. Show all posts
Tuesday, March 08, 2011
Sunday, February 27, 2011
An example of OpenID, Facebook and Twitter authentication in Zend Framework 1.11
This is an example Zend Framework 1.11.3 application that uses OpenID (Google,
Yahoo, MyOpenId, AOL, OpenId) as well as Facebook Connect and Twitter Oauth for
authentication of users.
During authentication, information about a user (e.g. an email or a country) is fetched from the authentication provider.
Zend Framework 1.11 does not have a very good support for OpenID, not mentioning Facebook Connect and Twitter Oauth. Thus, to make it all work the following elements were used:
The demo of this application is here , while the source code is at GitHub. The user authentication is performed in a loginAction in UserController.php.
Hopefully, this example application will be useful to others as it was for me.
Yahoo, MyOpenId, AOL, OpenId) as well as Facebook Connect and Twitter Oauth for
authentication of users.
During authentication, information about a user (e.g. an email or a country) is fetched from the authentication provider.
Zend Framework 1.11 does not have a very good support for OpenID, not mentioning Facebook Connect and Twitter Oauth. Thus, to make it all work the following elements were used:
- openid-selector
- My_Auth_Adapter_Facebook by Michael Krotscheck
- My_Auth_Adapter_Oauth and My_Auth_Adapter_Oauth_Twitter by Jason Austin
- My_OpenId_Extension_AttributeExchange by Chris Bisnett
- Patched Zend_OpenId_Custumer
The demo of this application is here , while the source code is at GitHub. The user authentication is performed in a loginAction in UserController.php.
Hopefully, this example application will be useful to others as it was for me.
Labels:
PHP,
Zend Framework
Sunday, December 06, 2009
Testing Basic HTTP Authentication using PHPUnit in Zend Framework
In Zend Framework, there are few ways of restricting access to the protected areas of an application. The simplest and the fastest to implement is Basic HTTP Authentication. However, it must be remembered that it is not the most secure way, as it is using base64 coding that can be easily broken.
Although Zend_Auth reference guide shows how to implement Basic HTTP Authentication, it does not show how to test it using PHPUnit. Therefore, in this post, a simple example of a Zend project, along with the associated PHPUnit test case is presented. The full source code of the project is available for download. The project's name is httpautheg.
So, lets assume that we want to restrict access to the actions called protectedAction and editAction in IndexController. We also want a simple action helper, called HTTPAuth that will do the authentication. Finally, we want a test case for IndexController that will perform the tests of incorrect and correct authentications, so that we do not have to worry that during further work on the project we will break something without noticing it.
The full code of the IndexControllerTest.php is
Failed Authentication:
Successful access to protected action:
Execution of PHPUnit
Although Zend_Auth reference guide shows how to implement Basic HTTP Authentication, it does not show how to test it using PHPUnit. Therefore, in this post, a simple example of a Zend project, along with the associated PHPUnit test case is presented. The full source code of the project is available for download. The project's name is httpautheg.
So, lets assume that we want to restrict access to the actions called protectedAction and editAction in IndexController. We also want a simple action helper, called HTTPAuth that will do the authentication. Finally, we want a test case for IndexController that will perform the tests of incorrect and correct authentications, so that we do not have to worry that during further work on the project we will break something without noticing it.
The directory tree of the httpautheg project
HTTPAuth action helper
The helper has only one function called doBasicHTTPAuth that does the authentication, and returns false or true if authentication failed or succeeded, respectively.<?php
class My_Controller_Action_Helper_HTTPAuth extends Zend_Controller_Action_Helper_Abstract {
//put your code here
/**
* Perform Basic HTTP authentication
*
* @return boolean authentication successful or not
*/
public function doBasicHTTPAuth() {
$path = APPLICATION_PATH .'/configs/passwdBasic.txt';
$resolver = new Zend_Auth_Adapter_Http_Resolver_File($path);
$config = array(
'accept_schemes' => 'basic',
'realm' => 'Admin Area',
'digest_domains' => '/index',
'nonce_timeout' => 3600,
);
$adapter = new Zend_Auth_Adapter_Http($config);
$adapter->setBasicResolver($resolver);
$request = $this->getRequest();
$response = $this->getResponse();
$adapter->setRequest($request);
$adapter->setResponse($response);
$result = $adapter->authenticate();
if (!$result->isValid()) {
// Bad userame/password, or canceled password prompt
return false;
} else {
return true;
}
}
}IndexController.php
In the preDispatch() function, public actions that do not require authentication are specified. For all other actions in the controller, basic HTTP Authentication using the above helper. For this example 'index' and 'failedauth' actions are public, while actions named 'protected' and 'edit' require authentication.<?php
class IndexController extends Zend_Controller_Action {
public function init() {
/* Initialize action controller here */
}
public function preDispatch() {
//any action not in this array will require Auth
$publicActions = array('index','failedauth');
$action = $this->getRequest()->getActionName();
if (!in_array($action, $publicActions)) {
//if requested action is non public one,
//then do authenticated
if ($this->_helper->_HTTPAuth->doBasicHTTPAuth() == false) {
$this->_forward('failedauth');
return;
}
}
}
public function indexAction() {
// public action
}
public function protectedAction() {
// protected action
}
public function editAction() {
// protected action
}
public function failedauthAction() {
//public action
}
}
PHPUnit test case IndexControllerTest.php
Testing of failed authentication is quite easy. The trick is with testing correct authentication, since we have to sent a correct HTTP header to the server. In our case, the username is 'admin' and the password is 'admin12', so before we dispatch the request for a protectedAction, we need to set a header as follows:$this->request->setHeader('Authorization','Basic YWRtaW46YWRtaW4xMg==');where “YWRtaW46YWRtaW4xMg==” is a result of base64_encode("admin:admin12") function.The full code of the IndexControllerTest.php is
<?php
class IndexControllerTest extends ControllerTestCase {
/**
* Check if we go to index controller
*/
public function testIndexController() {
$this->dispatch('/');
$this->assertController('index');
$this->assertAction('index');
}
/**
* Prived an array with protected actions
*
* @return array
*/
public function getProtectedActions() {
return array(
array('/index/protected'),
array('/index/edit'),
);
}
/**
* Going to /index/protected should result in Www-Authenticate header
* and since we do not send header with correct passwors and user
* we should be forwarded to failedauth action and see 'Failed authentification'
*
* @dataProvider getProtectedActions
*/
public function testAccessWithoutAuth($action='/index/protected') {
$this->dispatch($action);
$this->assertHeader('Www-Authenticate');
$this->assertAction('failedauth');
$this->assertQueryContentContains('h1', 'Failed Authentication');
}
/**
* Going to /index/index, but this time we send a header
* with some inccorect password:username, codded as base64_encode.
* Since username and password are inccorect we should get 'Www-Authenticate'
* header.
*
* @dataProvider getProtectedActions
*
*/
public function testAccessWithInccorectAuthCredentials($action='/index/protected') {
//send header with inccorect user and password, e.g.
//YWRtaW46d3JvbnRwYXNzd29yZA== is equal to base64_encode("admin:wrontpassword")
$this->request->setHeader('Authorization','Basic YWRtaW46d3JvbnRwYXNzd29yZA==');
$this->dispatch($action);
$this->assertHeader('Www-Authenticate');
$this->assertNotQueryContentContains('h1', 'Successful Authentication');
}
/**
* Going to /index/index, but this time we send a header
* with CORRECT password:username, codded as base64_encode.
* Since username and password are ccorect we should not get 'Www-Authenticate'
* header and be able to see protected content.
*
* @dataProvider getProtectedActions
*/
public function testAccessWithCorrectAuthCredentials($action='/index/protected') {
//send header with correct user and password i.e.
//YWRtaW46YWRtaW4xMg== is equal to base64_encode("admin:admin12")
$this->request->setHeader('Authorization','Basic YWRtaW46YWRtaW4xMg==');
$this->dispatch($action);
$this->assertNotHeader('Www-Authenticate');
$this->assertQueryContentContains('h1', 'Successful Authentication');
if ($action == '/index/protected') {
$this->assertQueryContentContains('h2', 'Protected action');
} elseif ($action == '/index/edit') {
$this->assertQueryContentContains('h2', 'Edit action');
}
}
}Some example screenshots
After clicking “Go to protected action” we are ask for credentials:Failed Authentication:
Successful access to protected action:
Execution of PHPUnit
Download the project (httpautheg.tar.bz2)
The project was done using ZendFramework-1.9.3PL1. For simplicity, the archive file contains the Zend library. Therefore, just download the archive, unpack it, change file rights if necessary and it should work. Assuming that the project directory is in your root path in the localhost, than it can be executed with url: http://localhost/httpautheg/public/. If xampp is used, it must be remembered that PHPUnit version that comes with xampp is too old and it must be upgraded to execute PHPUnit tests. To execute PHPUnits, a phpunit command must be used in a terminal - not a web browser.Testing Digest HTTP Authentication
Testing Digest HTTP Authentication can be done in a similar way. The difference would be in setting a correct header when requesting for protected action. More details on Digest HTTP Authentication header is here.
Labels:
Zend Framework
Thursday, December 03, 2009
PHP: Generation of MD5 hash for HTTP digest access authentication
HTTP Digest access authentication is one of the agreed methods a web server can use to negotiate credentials with a web user (using the HTTP protocol). Digest authentication is intended to supersede unencrypted use of the Basic access authentication, allowing user identity to be established securely without having to send a password in plaintext over the network. Digest authentication is basically an application of MD5 cryptographic hashing with usage of nonce values to prevent cryptanalysis.
For example, lets assume that we want to allow a user called "adminuser" access a realm called "Admin Realm" with a password "secretpassword". Using php command the MD5 hash for this can be generated using:
php -r 'echo MD5("adminuser:Admin Realm:secretpassword")."\n";'This gives the following MD5 hash:3228e0b5f8ae5ffb249d16125baffe63Therefore, for example when using Zend_Auth in Zend Framework, a file e.g. 'files/passwd.txt' with the username,realm and password that has to go into a resolver Zend_Auth_Adapter_Http_Resolver_File can containadminuser:Admin Realm:3228e0b5f8ae5ffb249d16125baffe63
In case of basic authentication, in 'files/passwd.txt' we would have password in a plain text
adminuser:Admin Realm:secretpassword
Labels:
PHP,
Zend Framework
Thursday, November 26, 2009
Zend Framework: Returning pdf file from an action controller
Lets assume that we have an action called getpdfAction in a Zend Controller. When we execute the action in a browser (e.g. http:://www.oursite.com/somezfcontroller/getpdf), the Zend Application by default will render view associated with the action and if necessary layout. However, when we want to have a pdf file returned or any other file from the action this behaviour is not needed. So, before we read a pdf for returning, we have to disable view script and layout rendering. This can be done as in the example getpdfAction function below:
public function getpdfAction() {
//Disable rendering of view script and layout
$this->_helper->viewRenderer->setNoRender();
$this->_helper->layout->disableLayout();
// We'll be outputting a PDF
header('Content-type: application/pdf');
// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');
// The PDF source is in original.pdf
readfile('some_pdf_file.pdf');
}
Labels:
PHP,
Zend Framework
Sunday, October 18, 2009
xampp / lampp: upgrade PHPUnit in lampp 1.7.1
The default PHPUnit that ships with lampp 1.7.1 is not suited for use with Zend Framework 1.9. The reason is that the PHPUnit version in lampp is to low. So it is necessary to upgrade it using pear. However, before it can be done, pear version that comes with lampp 1.7.1 needs to be also upgraded. The pear executable is in /opt/lampp/bin so I went to this folder.
First PHPUnit channel must be added
Then pear chanels can be updated
Then we can try to install PHPUnit:
To upgrade pear I used
Before PHPUnit can be upgraded, pear/Image_GraphViz package must be upgraded first. So
and install PHPUnit
After this, when I could use PHPUnit with Zend Framework as described in a tutorial here.
First PHPUnit channel must be added
sudo ./pear channel-discover pear.phpunit.de
Adding Channel "pear.phpunit.de" succeeded
Discovery of channel "pear.phpunit.de" succeededThen pear chanels can be updated
sudo ./pear update-channelsThen we can try to install PHPUnit:
sudo ./pear install phpunit/PHPUnit
phpunit/PHPUnit requires PEAR Installer (version >= 1.8.1), installed version is 1.7.1
phpunit/PHPUnit requires package "pear/Image_GraphViz" (version >= 1.2.1), installed version is 1.1.0
phpunit/PHPUnit can optionally use PHP extension "xdebug" (version >= 2.0.5)
No valid packages found
install failedTo upgrade pear I used
sudo ./pear upgrade PEAR To check if upgrade was successful I used ./pear -V
PEAR Version: 1.9.0
PHP Version: 5.2.9
Zend Engine Version: 2.2.0
Running on: Linux arch 2.6.31-ARCH #1 SMP PREEMPT Tue Oct 13 13:36:23 CEST 2009 i686Before PHPUnit can be upgraded, pear/Image_GraphViz package must be upgraded first. So
sudo ./pear upgrade pear/Image_GraphViz
downloading Image_GraphViz-1.2.1.tgz ...
Starting to download Image_GraphViz-1.2.1.tgz (4,872 bytes)
.....done: 4,872 bytes
upgrade ok: channel://pear.php.net/Image_GraphViz-1.2.1and install PHPUnit
./pear install -a phpunit/PHPUnit
phpunit/PHPUnit can optionally use PHP extension "xdebug" (version >= 2.0.5)
downloading PHPUnit-3.4.1.tgz ...
Starting to download PHPUnit-3.4.1.tgz (326,659 bytes)
...................................................................done: 326,659 bytes
install ok: channel://pear.phpunit.de/PHPUnit-3.4.1After this, when I could use PHPUnit with Zend Framework as described in a tutorial here.
Wednesday, October 07, 2009
Xampp: SQLSTATE[HY000] [2002] Invalid argument
I'm currently developing a web application using Zend Framework 1.9.x. For this purpose I used Xampp for linux (i.e. lampp 1.7.2). Most of the time I was using arch linux with xampp 1.7.2 and there was no problem. Then I changed my os to Ubuntu 9.04 and I installed the same xampp 1.7.2. Interestingly, when I wanted to run my application under Ubuntu I got an error
Therefore I set it to /opt/lampp/var/mysql/mysql.sock
Of course, I also had to restart Xampp
Message: SQLSTATE[HY000] [2002] Invalid argumentAfter googling I found that the reason was that in my php.ini (i.e. for xampp it is /opt/lampp/etc/php.ini) the variable pdo_mysql.default_socket was not set:
Therefore I set it to /opt/lampp/var/mysql/mysql.sock
Of course, I also had to restart Xamppsudo /opt/lampp/lampp restartIt is interesting why Xampp 1.7.2 worked under Arch Linux, but it did not work under Ubuntu 9.04?
Sunday, September 27, 2009
TOP PHP frameworks in terms of number of books published on a given framework
To begin with, I would like to say that I'm not new to PHP 4 and 5, but I would not call myself an expert. The reason is that for a few years now, PHP and web applications are things that I do only in my spare time. I also haven't used all the PHP frameworks, nor I'm the expert in any of them. I'm basically looking for a framework that is worth looking into and which would save me a time, as I don't want to spend much time on weekends coding e.g. only user authorization or registration form validation. So far, I did some small jobs using Prado, CakePHP and now I'm starting to learn Zend Framework. I also heard lots of good about CodeIgniter and Symfony. Since, I couldn't learn all of them, I just wanted to find some way of determining which of them seems to be the most popular. I decided to check how many books on a given framework are available in amazon.com?
I chose this criterion because for a person that wants to learn a framework, examples along with explanation can be valuable. Apart from official tutorials, quick start guides and reference manuals, that are available on the websites of the frameworks, books can provide good introduction along with example applications. Additionally, a number of books, also shows to some extend, how popular a given framework is. I would imaging that not many authors would write books about unpopular frameworks. Off course, there are many other possible criteria that can be used to rank or compare PHP frameworks, such as documentation, community support, performance, fast availability of updates etc., but I think that the number of books somehow translates to the the popularity of a framework.
Method of comparison
I went to amazon.com and I performed advanced searches for books on a given framework written in English and published after 2007. A year 2007 was chosen because books older than two years may contain highly outdated information. A framework name was a keyword. Than, the number of books found was counted.
En example of a search criteria used is given below:
En example of a search criteria used is given below:

Results
The results are as follows:![]() | Zend Framework - 10 books (see the books) |
![]() | Symfony - 9 books (see the books) |
![]() | CakePHP - 3 books (see the books) |
![]() | CodeIgniter - 2 book (see the books) |
![]() | Prado - 0 books (see the books) |
My personal opinion
From my perspective, the experience that I had with Prado (I used v. 3.1.4) was the worst one, although it's concept was interesting. I found it difficult to learn and use, because the documentation was sparse, there were not many tutorials, and even if I was wiling to invest some money and buy a book about it, I could not find any books about it.
After Prado I tried CakePHP (I was using v. 1.2). I found it very good, easy to learn and fast to use, as long as I adhered to all the naming conventions. Especially, I liked the ORM (Object-Relational Mapping) which was very useful and saved me a lot of time. The problem I had with it, was that it uses PHP 4, which already has been discontinued. Off course, sooner or later CakePHP will move to PHP 5, but I wanted to use a PHP 5. I think it would be better to use something in PHP 5, rather than something that is developed in a version of language that is already not supported. Off course, CakePHP runs smoothly on PHP 5. It is only CakePHP's core that does not use features of PHP 5. Additionally, I wanted to have more freedom when programming, and CakePHP does not allow for much of it due to it's "convention over configuration paradigm". But this is a price that you pay in CakePHP.
At the moment I'm learning Zend Framework v1.9 which is build using PHP 5. For now, I can say that it is definitely more difficult to learn at the beginning. The biggest issue that I had at the beginning, and still have but to a lesser extend, is a bootstrap class, which is difficult to understand. It really took me a long time to begin to understand how to use it at the simplest level. However, what I like is, that Zend Framework is less rigid than CakePHP, it uses PHP 5, and it has a vast number of tools (e.g. for working with PDF files or captcha) that CakePHP does not have.
I don't have experience with Symfony and CodeIgniter, so I cannot say anything apart from what I read in the Internet. CodeIgniter is considered to be faster than CakePHP and just like CakePHP, it is written for PHP 4, whereas Symfony is for PHP 5 only.
In conclusion, it seems that when you look only at the number of books on a given framework, Zend Framework is the winner with eight books. At the moment, I'm trying to get to know it, hopping that it will not be a waste of time. It must be remembered though, that there are many other criteria that can be used to compare PHP frameworks. However the final decision which framework to choose, if any, should be based on the specific needs of a project that we want to developed.
After Prado I tried CakePHP (I was using v. 1.2). I found it very good, easy to learn and fast to use, as long as I adhered to all the naming conventions. Especially, I liked the ORM (Object-Relational Mapping) which was very useful and saved me a lot of time. The problem I had with it, was that it uses PHP 4, which already has been discontinued. Off course, sooner or later CakePHP will move to PHP 5, but I wanted to use a PHP 5. I think it would be better to use something in PHP 5, rather than something that is developed in a version of language that is already not supported. Off course, CakePHP runs smoothly on PHP 5. It is only CakePHP's core that does not use features of PHP 5. Additionally, I wanted to have more freedom when programming, and CakePHP does not allow for much of it due to it's "convention over configuration paradigm". But this is a price that you pay in CakePHP.
At the moment I'm learning Zend Framework v1.9 which is build using PHP 5. For now, I can say that it is definitely more difficult to learn at the beginning. The biggest issue that I had at the beginning, and still have but to a lesser extend, is a bootstrap class, which is difficult to understand. It really took me a long time to begin to understand how to use it at the simplest level. However, what I like is, that Zend Framework is less rigid than CakePHP, it uses PHP 5, and it has a vast number of tools (e.g. for working with PDF files or captcha) that CakePHP does not have.
I don't have experience with Symfony and CodeIgniter, so I cannot say anything apart from what I read in the Internet. CodeIgniter is considered to be faster than CakePHP and just like CakePHP, it is written for PHP 4, whereas Symfony is for PHP 5 only.
In conclusion, it seems that when you look only at the number of books on a given framework, Zend Framework is the winner with eight books. At the moment, I'm trying to get to know it, hopping that it will not be a waste of time. It must be remembered though, that there are many other criteria that can be used to compare PHP frameworks. However the final decision which framework to choose, if any, should be based on the specific needs of a project that we want to developed.
Labels:
Arch,
CakePHP,
framework,
PHP,
Zend Framework
Subscribe to:
Posts (Atom)











