ZF-7778: getCookie doesn't utilize _matchDomain (CookieJar)

Description

When trying to retrieve a cookie using the cookieJars getCookie function it is impossible currently to match the .domain.com key associated to the cookies array. The solution I came up with was to utilize the _matchDomain , _flattenCookiesArray and _matchPath function of the cookiejar.


public function getCookie($uri, $cookie_name, $ret_as = self::COOKIE_OBJECT)
    {
        if (is_string($uri)) {
            $uri = Zend_Uri::factory($uri);
        }
        
        if (! $uri instanceof Zend_Uri_Http) {
            require_once 'Zend/Http/Exception.php';
            throw new Zend_Http_Exception('Invalid URI specified');
        }

        // Get correct cookie path
        $path = $uri->getPath();
        $path = substr($path, 0, strrpos($path, '/'));
        if (! $path) $path = '/';

        $cookies = $this->_matchDomain($uri->getHost());
        $cookies = $this->_matchPath($cookies, $path);
        $cookies = $this->_flattenCookiesArray($cookies);

        foreach ($cookies as $cookie)
        {
            if ($cookie->getName() == $cookie_name)
            {
                switch ($ret_as) {
                    case self::COOKIE_OBJECT:
                        return $cookie;
                        break;

                    case self::COOKIE_STRING_ARRAY:
                    case self::COOKIE_STRING_CONCAT:
                        return $cookie->__toString();
                        break;

                    default:
                        require_once 'Zend/Http/Exception.php';
                        throw new Zend_Http_Exception("Invalid value passed for \$ret_as: {$ret_as}");
                        break;
                }
            }
        }

        return false;
    }

Cheers,

Jay

Comments

Not fixed as of 1.9.6, makes using moneybookers session api unuseable as it doesn't recognize the cookie. Haven't checked 1.10 alpha yet.

Could you provide an example?

The appropriateness of what you have suggested depends on what the intended purpose of {{getCookie}} is. I assumed it was for retrieving specific cookies (ie: you have to specify the exact name and domain string as set in the Set-Cookie header), while {{getMatchingCookies()}} was intended for what you are trying to accomplish above. Am I wrong in that assumption?

Hey Adam,

The problem I ran into was when writing a class for processing Moneybookers.com payments, It was a couple of years ago now so I can't be absolutely positive, I believe the problem was that getHost returned moneybookers.com but the cookie was being stored as .moneybookers.com with a period at the begining.

Looking at the getMatchingCookies(), it looks like it may work for this as well.

Here is the resulting code that allows it to function properly:


public function getSessionUrl(array $data)
    {
        $client = new Zend_Http_Client(
             'https://www.moneybookers.com/app/payment.pl',
             array(
                 'maxredirects' => 0,
                 'timeout'      => 30
             )
        );

        $client->setParameterPost($data);

        $client->setCookieJar(new Nexus_Http_CookieJar());

        $response = $client->request(Zend_Http_Client::POST);

        $cookie = $client->getCookieJar()->getCookie('https://moneybookers.com','SESSION_ID');

        if (! $cookie instanceof Zend_Http_Cookie)
        {
            throw new Default_Exception_Application('Failed to get session ID from moneybookers');
        }

        $sessionId = $cookie->getValue();

        return 'https://moneybookers.com/app/payment.pl/…;
    }

Then the getCookie extension to the cookieJar:


public function getCookie($uri, $cookie_name, $ret_as = self::COOKIE_OBJECT)
    {
        if (is_string($uri)) {
            $uri = Zend_Uri::factory($uri);
        }

        if (! $uri instanceof Zend_Uri_Http) {
            require_once 'Zend/Http/Exception.php';
            throw new Zend_Http_Exception('Invalid URI specified');
        }

        // Get correct cookie path
        $path = $uri->getPath();
        $path = substr($path, 0, strrpos($path, '/'));
        if (! $path) $path = '/';

        $cookies = $this->_matchDomain($uri->getHost());
        $cookies = $this->_matchPath($cookies, $path);
        $cookies = $this->_flattenCookiesArray($cookies);

        foreach ($cookies as $cookie)
        {
            if ($cookie->getName() == $cookie_name)
            {
                switch ($ret_as) {
                    case self::COOKIE_OBJECT:
                        return $cookie;
                        break;

                    case self::COOKIE_STRING_ARRAY:
                    case self::COOKIE_STRING_CONCAT:
                        return $cookie->__toString();
                        break;

                    default:
                        require_once 'Zend/Http/Exception.php';
                        throw new Zend_Http_Exception("Invalid value passed for \$ret_as: {$ret_as}");
                        break;
                }
            }
        }

        return false;
    }

Cheers,

Jay

Jay,

Thanks for your response. I've looked at the documentation (here), but it doesn't really spell out the exact purpose of the {{getCookie}} method. I'll see if I can find out if the intent is to have it match literal URIs or to have it do a "fuzzy" URI match like {{getMatchingCookies}} does.

From your example, it looks to me like using {{getMatchingCookies}} would work for you. The only difference would be that it returns an array of matches, and so you'd just have to pop off the first one and assign that to {{$cookie}}.

Closing as Won't Fix. It's unlikely this can be changed at this late stage in ZFv1's lifecycle, and a possible workaround (getMatchingCookies) exists.