Tag Archives: PHP

Login through Google+ and OAuth API

One of the common scenarios is to login through an external account like Google+, Twitter or Facebook.
In this code snippet I will show how to login using Google+ API

First you need to register your api at https://code.google.com/apis/console/, register the Google+ API Service and create a new application; in the “Redirect URI” you need to pass the path of the script and add the following: “googleplus.php?op=redirect” I will comment why is this later, after you see the code, you can fragment code into other more elegant paths/scripts.

From the generated application you will need the Redirection URI and the Client ID

Google OAuth works in the following way:

  1. Generate an URL using params of services you want to access (scope) and your Client ID and Redirection URI
  2. You need to redirect user to this URL
  3. After user has approved the use, you will be redirected with a hash params, so your server won’t see it, you can pass to your server through ajax or in this case through a GET request

In the code the “?op=redirect” will show just a white page with a javascript redirection to convert the hash location into a normal GET request; this will enable in the server to grab the access_token which you can use to verify through Google+ site if is valid.
This code part does it:

<?php
        $access_token = $_GET['access_token'];

	//do something with the token, first check is real
	$data = @file_get_contents("https://www.googleapis.com/plus/v1/people/me?access_token={$access_token}");
	if ($data) {
		print $data;
	} else {
		print "Token not valid!";
	}

The code is not prepared to handle error (will show as a $_GET['error'] after have redirected) so you need to handle that for your scenario.

Links:

 

Share

Using php for analyzing apache logs

Apache has a nice feature that is to send the log output through a pipe. This avoid to configure syslog or create a listening server in php for syslog forwarding logs.

The changes in apache are really simple, you just need to write something like:

LogFormat "%v %A %D \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" mylog
CustomLog "|/usr/bin/php5 [PATH_TO_SCRIPT]/apache-stdin.php log" mylog
ErrorLog "|/usr/bin/php5 [PATH_TO_SCRIPT]/apache-stdin.php error"

In apache-stdin.php the flow is very simple, you just need to do:

<?php
$fp = fopen('php://stdin', 'r');
do {
	//read a line from apache, if not, will block until have it
	$data = fgets($fp);
	$data = trim($data); //remove line end

	if (empty($data)) {
		break; //no more data so finish it
	}

	//process the data
} while(true);

fclose($fp);

As you can see it’s basically reading a line and processing.

I’ve built a helper script around this at:
https://github.com/danguer/blog-examples/blob/master/php/syslog/apache-stdin.php

Where you can pass an additional param to specify it’s a normal log, or the error log; like in the apache configuration I’ve posted.

You can also configure the log format you are using in apache to get you a simple description like:

<?php
$format = '%v %A %D \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"';

With this, it will give you an array like:

array(
'hostname' => 'danguer.com',
'local_ip' => 127.0.0.1,
'time_ms' => 0.0002,
'first_line_request' => 'GET / HTTP/1.1',
'status_last' => 200,
'bytes_sent' => 2048
);

From there you can use for storing in a file (it’s the common behavior of this script), insert into a db, use simpledb, etc.

Share

Installing php-fpm and apache2

I’ve readed a lot of tutorials of using nginx and php-fpm.
I’m still using apache2 much more due the .htaccess easiness that allow with rewriting and password protect (despite using other modules like mod_svn, etc)

Even I haven’t found a 100% transparent solution like ngninx, here is what I’m using to work with php-fpm and apache2. Here are the steps in debian:

  • echo "deb http://packages.dotdeb.org stable all" >> /etc/apt/sources.list
  • apt-get update
  • apt-get install libapache2-mod-fastcgi apache2-mpm-worker php5-fpm php5-common php5-cli
  • do all the apt-get of all php5-* modules you want
  • Add the following to a new file: /etc/apache2/mods-enabled/fpm.load
    AddType application/x-httpd-fastphp5 .php .phtml
    Action application/x-httpd-fastphp5 /fast-cgi-fake-handler
  • in /etc/php5/fpm/pool.d/www.conf change:
    listen = 127.0.0.1:9000

    for:

    ; listen = 127.0.0.1:9000
     listen = /var/run/php-fpm.socket

    This will enable the unix socket which should be faster

  • /etc/init.d/php-fpm restart
  • /etc/init.d/apache2 restart

 

With this you will be able to use php-fpm through a /fast-cgi-fake-handler so for example in your /etc/apache2/sites-enabled/000-default your file will look like:

FastCGIExternalServer /var/www/fast-cgi-fake-handler -socket /var/run/php-fpm.socket
DocumentRoot /var/www

The system will rewrite /index.php path into: /fast-cgi-fake-handler/index.php which will be passed to the fastcgi

This have two problems:

  1. You need to set the FastCGIExternalServer like ${DOCUMENT_ROOT}/fast-cgi-fake-handler in all your virtual hosts to make it work
  2. Zend framework and other which use the consume all url’s pattern to pass through index.php will not work as will generate an endless loop, there is an easy solution, in your .htaccess use after RewriteEngine On:
    RewriteRule ^fast-cgi-fake-handler/ - [L,NC]

    this will skip processing all urls which contain “fast-cgi-fake-handler” at start; or of course use a RewriteCond to avoid this.

Share

Recipes for using SVN library in PHP

The SVN library in PHP allows to work with SVN through a working copy or directly to the SVN repository files: http://us.php.net/manual/en/ref.svn.php

The problem is there is really few documentation for the direct access functions to repository (svn_repos_* and svn_fs_*) the code is almost the same to working in C the libsvn, but also there are few documentation, most of the svn command.

The good is that is really easy to work with SVN, basically you only need to:

  1. call to svn_repos_open($path) for getting a $repo handler
  2. call to svn_repos_fs($repo) to get a $repo_fs handler
  3. get the latest revision through:  svn_fs_youngest_rev($repo_fs);
  4. Get a $transaction through svn_repos_fs_begin_txn_for_commit($repo, $latest_revision, $commiter, $log_message);
  5. Get a $repo_root resource with svn_fs_txn_root($repo_txn);
    With $repo_root will be the most of operations and the $repo_txn will just work for do a commit or abort
  6. do all the operations (create a file/dir, remove, set contents)
  7. Call to svn_repos_fs_commit_txn($repo_txn); if you want to commit, or svn_fs_abort_txn ( $repo_txn ); if you want to abort the transaction

If you read the part of API for SVN: http://svnbook.red-bean.com/en/1.5/svn.developer.usingapi.html you will see an example for creating a new dir; this code can be easily changed to PHP since the calls are almost the same (replace  svn_repos_fs_begin_txn_for_commit2 for svn_repos_fs_begin_txn_for_commit) I will show you a script for init the repository creating the common paths (branches, tags, trunk) into an empty repository:

<?php
//the path to your repository
$svn_path = "/var/lib/svn/repos/testrepo";

//open the repo
$svn_repo = svn_repos_open($svn_path);

//get a fs handler
$repo_fs = svn_repos_fs($svn_repo);

//get latest revision
$latest_revision = svn_fs_youngest_rev($repo_fs);

//generate a transaction, with user and log message
$repo_txn = svn_repos_fs_begin_txn_for_commit($svn_repo, $latest_revision, 'user-repo-label', 'Creating paths');

//get the root respource to this transaction
$repo_root = svn_fs_txn_root($repo_txn);

//create the dirs
svn_fs_make_dir($repo_root, "trunk");
svn_fs_make_dir($repo_root, "tags");
svn_fs_make_dir($repo_root, "branches");

//finally commit the transaction
svn_repos_fs_commit_txn($repo_txn);

This script is called: create-repository-paths.php

You will see at end the list of scripts, the order to use is: (with svn commands in the console to check if worked):

#create SVN repository
danguer@rukia:~$ svnadmin create /var/lib/svn/repos/testrepo
#checking is empty
danguer@rukia:~$ svn ls file:///var/lib/svn/repos/testrepo

#create paths
danguer@rukia:~$ php create-repository-paths.php
danguer@rukia:~$ svn ls file:///var/lib/svn/repos/testrepo
branches/
tags/
trunk/

#creating dirs
danguer@rukia:~$ php create-dirs-recursive.php
danguer@rukia:~$ svn ls file:///var/lib/svn/repos/testrepo/test
subdir1/
danguer@rukia:~$ svn ls file:///var/lib/svn/repos/testrepo/test/subdir1
subdir2/
danguer@rukia:~$ svn ls file:///var/lib/svn/repos/testrepo/test/subdir1/subdir2
subdir3/
danguer@rukia:~$ svn ls file:///var/lib/svn/repos/testrepo/test/subdir1/subdir2/subdir3

#create a new file
danguer@rukia:~$ php write-contents.php
danguer@rukia:~$ svn ls file:///var/lib/svn/repos/testrepo/test/myfile.txt
myfile.txt
danguer@rukia:~$ svn cat file:///var/lib/svn/repos/testrepo/test/myfile.txt
Lorem Ipsum, file generated with svn

#remove file
danguer@rukia:~$ php remove-object.php
danguer@rukia:~$ svn cat file:///var/lib/svn/repos/testrepo/test/myfile.txt
svn: File not found: revision 4, path '/test/myfile.txt'

Scripts:

Share