Snippets

Create an account or login to be able to add, comment and rate snippets.

Navigation

Snippets by user Rob Rosenbaum Snippets by user Rob Rosenbaum

Disable Session Timeout

The problem: make the session expire when the user closes the browser window, instead of using a timed expiration. You can solve this little problem easily if you are using symfony 1.1 (currently in beta). Just set the timeout to false in settings.yml:

all:
  .settings:
    timeout:    false
 

But if you are using the stable 1.0 branch of symfony, this will do just the opposite - it will make your sessions time out immediately! To make this work, we have to override sfBasicSecurityUser's initialize() method. I will describe two ways to do this; one is a short hack, the other is longer and somewhat more proper.

Here's the short way:

class myUser extends sfBasicSecurityUser
{
  public function initialize($context, $parameters = null)
  {
    if (sfConfig::get('sf_timeout') == 0) {
      // session will expire if window is open for a day
      sfConfig::set('sf_timeout', 86400);
    }
 
    return parent::initialize($context, $parameters);
  }
}
 

This works because the sf_timeout setting is not used by any other class (at the moment), so changing it doesn't have any side effects. If you set your timeout to 0 or false, symfony will always think you have set the session timeout to 24 hours, but the session will actually expire when the user closes the browser window. If you are not comfortable with "hacks" like the above, you could copy the initialize() method from sfBasicSecurityUser, change it in the appropriate place, and skip calling the parent constructor altogether. Unfortunately, sfBasicSecurityUser calls its parent constructor, so you have to rewrite them both:

class myUser extends sfBasicSecurityUser
{
  public function initialize($context, $parameters = null)
  {
    $this->context = $context;
 
    $this->parameterHolder = new sfParameterHolder();
    $this->parameterHolder->add($parameters);
 
    $this->attributeHolder = new sfParameterHolder(self::ATTRIBUTE_NAMESPACE);
 
    // read attributes from storage
    $attributes = $context->getStorage()->read(self::ATTRIBUTE_NAMESPACE);
    if (is_array($attributes))
    {
      foreach ($attributes as $namespace => $values)
      {
        $this->attributeHolder->add($values, $namespace);
      }
    }
 
    // set the user culture to sf_culture parameter if present in the request
    // otherwise
    //  - use the culture defined in the user session
    //  - use the default culture set in i18n.yml
    if (!($culture = $context->getRequest()->getParameter('sf_culture')))
    {
      if (null === ($culture = $context->getStorage()->read(self::CULTURE_NAMESPACE)))
      {
        $culture = sfConfig::get('sf_i18n_default_culture', 'en');
      }
    }
 
    $this->setCulture($culture);
 
    // read data from storage
    $storage = $this->getContext()->getStorage();
 
    $this->authenticated = $storage->read(self::AUTH_NAMESPACE);
    $this->credentials   = $storage->read(self::CREDENTIAL_NAMESPACE);
    $this->lastRequest   = $storage->read(self::LAST_REQUEST_NAMESPACE);
 
    if ($this->authenticated == null)
    {
      $this->authenticated = false;
      $this->credentials   = array();
    }
    else
    {
      // Automatic logout logged in user if no request within [sf_timeout] setting
      if (0 != sfConfig::get('sf_timeout') && null !== $this->lastRequest && (time() - $this->lastRequest) > sfConfig::get('sf_timeout'))
      {
        if (sfConfig::get('sf_logging_enabled'))
        {
          $this->getContext()->getLogger()->info('{sfUser} automatic user logout due to timeout');
        }
        $this->setTimedOut();
        $this->setAuthenticated(false);
      }
    }
 
    $this->lastRequest = time();
 
  }
}
 
by Rob Rosenbaum on 2008-01-16, tagged sessions  timeout 

Upload Multiple Files with Flash

you can create a multi-file uploader in Flash using ActionScript's FileReference and FileReferenceList classes, but you have to jump through some hoops to make it work. The upload() method doesn't send the user's session cookie with the request, so you have to send it in the URL and set the cookie manually on the server. If you are using ufo.js, the first argument to UFO.create() should look like this:

{
  movie: '/flash/uploader.swf', 
  id: 'uploader',
  name: 'uploader',
 
  flashvars: 'cookie=' + document.cookie,
 
  // other options ...
}
 

If you are dealing with multilple cookies, you need to parse document.cookie and send only the desired cookie.

Next, add the cookie to the URL:

var list:Array = myFileRefList.fileList;
var item:FileReference;
var url:String = _root.uploadURL + '?cookie=' + _root.cookie;
 
for (var i:Number = 0; i < list.length; i++) {
  item.upload (url);
}
 

Now add the following class to your symfony project:

class mySessionStorage extends sfSessionStorage
{
  public function initialize($context, $parameters = null)
  {
    if ( /* whatever the condition is when we want to do this */ ) {
      if ($cookie = $context->getRequest()->getParameter('cookie')) {
        $name = 'symfony';
        preg_match('/^' . $name.'=(.*)$/', $cookie, $asMatch);
        $value = $asMatch[1];
 
        session_name($name);
        session_id($value);
      }
    }
 
    parent::initialize($context, $parameters);
  }
}
 

Now edit factories.yml:

all:
  ...
  storage:
    class: mySessionStorage
    param:
      session_name: symfony
 

And you're done!

My blog post on this subject seemed popular, so I made it into a snippet. Hope it helps!

by Rob Rosenbaum on 2007-09-11, tagged flash  session  upload