PHP

Cookies

Et voilà sur le même thème un petit billet en français pour les non anglophones.

Nous avons libéré sur github une petite classe qui installe un gestionnaire de session personnalisé. Sa particularité est de stocker les données de session dans un cookie chiffré.

L'intérêt est que nous n'avons plus besoin de partager les sessions entre serveurs si nous avons plusieurs frontaux.

Le chiffrement permet d'éviter toute modification par l'utilisateur du contenu du cookie. Le chiffrement par défaut utilise la paquet pear Crypt_Blowfish.

Son utilisation est très simple, on utilise toujours les fonctions habituelles de gestion de session (session_start(), session_destroy(), etc.). La seule exigence est de fermer la session en écriture juste avant la sortie HTML/whatever.

<?php
// just include session class
require_once 'session.php';
require_once 
'Crypt/Blowfish.php'// pear package, only needed when using SessionInCookie_DefaultCipher

SessionInCookie::setCipher(new SessionInCookie_DefaultCipher('mysecretkey'));

// start session normally
start_session();

// Read and write in session
$_SESSION['foo'] = 'bar';

// juste before output, call session_write_close
session_write_close();

// WARNING: now session data have been send to the client via encrypted cookie. You *CANNOT* write on $_SESSION.

echo 'Hello Word';
?>

Vous pouvez retrouver le code sur le dépot session-cookie. L'utilisation est décrite dans le README.

This must be PHP week on AF83's github, with a bunch of stuff that we hope can help someone out there. I will post about toupti and the others later, but first:

François (francois2metz) just released session-cookie that does just that. It puts your session data in the cookie.

Usually when you are doing PHP your session data is somewhere in a local store (either on the disk as a default, in your database or in some kind of DHT like memecache).

PHP lets you set quite easily the session handler for any of these methods (look at http://www.php.net/manual/en/function.session-set-save-handler.php).

Now this does pose some serious issues in terms of scalability. If you use a database or the file system this can be very hard on your disks. Opening a session is expensive, and distributing it over a large number of servers is hard complicated and may require more code then you imagined.

Sometimes all you want to have from the session is the user_id, yet when you get the session cookie you still have to pay a round trip to the database just to get it from there.

So.. one simple, cool solution, is just to send this data to the client as a cookie. Now you don't really want the user to be able to change the data (for example changing the user id and logging-in as a super duper admin). But this is not hard.. just encrypt it with your own secret, and the user will not be able either to modify or look at it.

Basic Usage
===========

<?php
// just include session class
require_once 'session.php';
require_once 
'Crypt/Blowfish.php'// pear package, only needed when using SessionInCookie_DefaultCipher

SessionInCookie::setCipher(new SessionInCookie_DefaultCipher('mysecretkey'));

// start session normally
start_session();

// Read and write in session
$_SESSION['foo'] = 'bar';

// juste before output, call session_write_close
session_write_close();

// WARNING: now session data have been send to the client via encrypted cookie. You *CANNOT* write on $_SESSION.

echo 'Hello Word';
?>

Advanced Usage
==============

<?php
Custom cipher
-------------

class MyCipher implements SessionInCookie_Cipher
{
    public function 
encrypt($data)
    {
        return 
$data;
    }

    public function decrypt($data)
    {
        return 
$data;
    }
}

SessionInCookie::setCipher(new MyCipher());

Debug
-----

You can use SessionInCookie_DummyCipher

SessionInCookie::setCipher(new SessionInCookie_DummyCipher());

?>

I do not think this solution is great when you have too much data in the session.. but that anyway is probably a very bad idea. If the data is important ... please remember : sessions die.

get the code at: http://github.com/AF83/session-cookie

Enjoy

(btw some frameworks, written by serious people take this approach as a default...)

Logo
Chaque semaine, je publie une liste de liens vers des billets de blog, des articles et des annonces qui me semblent intéressants et en rapport avec l’activité d’AF83. N’hésitez pas à proposez vos liens. Voici la sélection de cette semaine :
Campagne Microsoft

I looked for a nice clean class implementation in PHP for embedding videos from youtube and such and could not find anything that was nice enough. So here is my take on embedding videos in php.
As the embed code is reconstructed it should be safe enough put probably some more checks need to be done after extracting the id to see there is nothing hostile there.

Configuration:
This class requires the SpyC library to read the cobnfiguration file. The library is assumed to be in the SITEBASE/include/yaml/ directory.

<?php
define
('SITEBASE''/var/www/mysite'); // path to the root of the site (not forcefully public)
define('VIDEO_EMBED_CONFIG_FILE'SITEBASE.'/config/video_embed.yaml'); //path of video embed config file
define('DEBUG'true); //to activate debug mode and false for production usage. it will write to a log file when something goes wrong but should not produce exceptions in production enviroment
?>

USAGE
note: The embed code may either be embed or url

<?php
$embed
='http://www.youtube.com/watch?v=h2EUW_rgDVo';
$videoEmbed = new VideoEmbed($embed); //optional width and height may be passed to the constructor
print($videoEmbed->embed);
$videoEmbed->width 240// resize
$videoEmbed->height 120;
print(
$videoEmbed->embed); // resized video
print($videoEmbed->thumb); // get thumb url
?>

the other public properties are: ->id, ->type, ->url, ->width and ->height
note that magic getters and setters are used to make ->id, ->type, ->url read only

TODO: thumbnails should be cached locally
TODO: Create unit tests (for the moment test_VideoEmbed(); does some testing)

The video services are configured in the configuration file (video_embed.yaml), form:

---
embedTemplate: default embed template
defaultWidth: default width
defaultHeight: default height
services:
servicename:
urlPattern: pattern to distinguis between services
embedUrlTemplate: template (used with sprintf) for construvting the player url
thumbnailUrlTemplate: template to find thumnbail by video ID (used with sprintf)
thumbnailUrlExtractPattern: if present the thumbnailUrlTemplate is assumed to be a text resource, and this is a regexp to extract the thumnbail from it
extractPattern: regexp pattern to extract
apiUrl: api url (not used for the currently supported services)
defaultWidth: service default width
defaultHeight: service default height
embedTemplate: specific embed template (not used for the current supported services)

Example configuration file for google video youtube and dailymotion (if you configure it for other services please post the config)... :)

---
embedTemplate: <object width="%2$s" height="%3$s" ><param name="movie" value="%1$s"></param><param name="wmode" value="transparent"></param><embed src="%1$s" type="application/x-shockwave-flash" wmode="transparent" width="%2$s" height="%3$s"></embed></object>
defaultWidth: 425
defaultHeight: 350
services:
youtube:
urlPattern: youtube.com
embedUrlTemplate: http://www.youtube.com/v/%1$s&rel=1
thumbnailUrlTemplate: http://i.ytimg.com/vi/%1$s/default.jpg
extractPattern: /youtube\.com\/(v\/|watch\?v=)([\w\-]+)/
apiUrl: http://www.youtube.com/api2_rest
defaultWidth: 425
defaultHeight: 350
google:
urlPattern: video.google
extractPattern: /docid=([^&]*)/i
embedUrlTemplate: http://video.google.com/googleplayer.swf?docId=%1$s
thumbnailUrlTemplate: http://video.google.com/videofeed?docid=%s
thumbnailUrlExtractPattern: '/

And here is the code :Complete class code with readme and configuration file

The code referes to a debug function, you can use:

<?php
function debug_log($msg$file "debug")
{
    
$dbg "";
    if (
SITE != '[PROD]') {
        
$bts debug_backtrace();
        foreach(
$bts as $bt) {
            
$path str_replace(SITEBASE''$bt ['file']);
            
$dbg .= $path " line " $bt['line'] . " (function " $bt['function'] . ")\n";
        }
        
$handle fopen(SITEBASE "/../log/{$file}.log""a");
        
fwrite($handlestrftime("%Y-%m-%d %H:%M:%S  ") . $dbg $msg "\n------------------\n");
        
fclose($handle);
    }
}
?>