PHPCI icon indicating copy to clipboard operation
PHPCI copied to clipboard

Unserialize error

Open gnat42 opened this issue 10 years ago • 12 comments

Hello,

I had evaluated phpci in a vm awhile back. Now we have an instance in production however the first project I add to it results in the following.

Notice: unserialize(): Error at offset 0 of 2 bytes in /path/to/phpci/PHPCI/Model/Project.php line 63

This is a completely fresh install so I'm at a loss.

gnat42 avatar Sep 25 '14 22:09 gnat42

bump.. Exception: Notice: unserialize(): Error at offset 0 of 2 bytes in /path/to/phpci/PHPCI/Model/Project.php line 62 when i try integrated with GitLab env: fedora, apache,mysql

mxtechno avatar Sep 28 '14 18:09 mxtechno

So this doesn't fix anything however one thing I figured out was that I shouldn't put the .git in my project url as PHPCI adds this. Personally I think that's a bug but whatever at this point...

gnat42 avatar Sep 30 '14 22:09 gnat42

So I've dug around - there seems to be a number of bugs relating to gitlab integration. First off is the serialization issue this bug reports.

       // Handle old-format (serialized) access information first:
        if (!empty($info) && substr($info, 0, 1) != '{') {
            $data = unserialize($info);
        } else {
            $data = json_decode($info, true);
        }

somehow fails, the first test ends up being true even though $info tends to be "{"buildId": 1}".

However even if I comment all that out and use json_decode because I'm using a new system so know that nothing will have been serialize - there are still issues.

One part of the code appends a .git to the resource, and another expects there to be no .git.

All of the offending code is in commit 0e1fe3ea220c72052259b28b477919873eef23df

From: ProjectService.php

protected function processAccessInformation(Project &$project)
    {
        $matches = array();
        $reference = $project->getReference();

        if ($project->getType() == 'gitlab') {
            $info = array();

            if (preg_match('`^(.*)@(.*):([0-9]+)?/?(.*)/(.*)\.git`', $reference, $matches)) {
                $info['user'] = $matches[1];
                $info['domain'] = $matches[2];
                $info['port'] = $matches[3];

                $project->setReference($matches[4] . '/' . $matches[5]);
            }

            $project->setAccessInformation($info);
        }
    }

you can see the reference must end in .git. Meaning that when creating a gitlab project the url must be user@url:/owner/repo.git

However GitlabBuild.php has

    protected function getCloneUrl()
    {
        $key = trim($this->getProject()->getSshPrivateKey());

        if (!empty($key)) {
            $user = $this->getProject()->getAccessInformation("user");
            $domain = $this->getProject()->getAccessInformation("domain");
            $port = $this->getProject()->getAccessInformation('port');

            $url = $user . '@' . $domain . ':';

            if (!empty($port)) {
                $url .= $port . '/';
            }

            $url .= $this->getProject()->getReference() . '.git';

            return $url;
        }
    }

You can see it appends a .git, meaning if I setup a project with git@url:owner/project.git, the clone url becomes git@url:owner/project.git.git which will fail to clone.

To compound this there are validation rules for each project type - I haven't looked into why it isn't being called however ProjectController.php has:

protected function getReferenceValidator($values)
    {
        return function ($val) use ($values) {
            $type = $values['type'];

            $validators = array(
                'hg' => array(
                    'regex' => '/^(https?):\/\//',
                    'message' => 'Mercurial repository URL must be start with http:// or https://'
                ),
                'remote' => array(
                    'regex' => '/^(git|https?):\/\//',
                    'message' => 'Repository URL must be start with git://, http:// or https://'
                ),
                'gitlab' => array(
                    'regex' => '`^(.*)@(.*):(.*)/(.*)\.git`',
                    'message' => 'GitLab Repository name must be in the format "[email protected]:owner/repo.git"'
                ),
                'github' => array(
                    'regex' => '/^[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-\.]+$/',
                    'message' => 'Repository name must be in the format "owner/repo"'
                ),
                'bitbucket' => array(
                    'regex' => '/^[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-\.]+$/',
                    'message' => 'Repository name must be in the format "owner/repo"'
                ),
            );

            if (in_array($type, $validators) && !preg_match($validators[$type]['regex'], $val)) {
                throw new \Exception($validators[$type]['message']);
            } elseif ($type == 'local' && !is_dir($val)) {
                throw new \Exception('The path you specified does not exist.');
            }

            return true;
        };
    }

which should apply validation to the repository reference value. Either the regexp is wrong or the form isn't being properly validated.

All this to say that there are two issues. The first being a general issue about project deserialization vs json decoding.

The second is specific to gitlab and how the url/repository path should be validated and used internally. Personally I don't think phpci should be modifying the reference at all. Most of the time the .git is optional from a repository point of view.

Thoughts?

gnat42 avatar Oct 01 '14 05:10 gnat42

This is still an issue because I get the same on a fresh installation when using Gitlab repositories.

subdee avatar Mar 23 '15 14:03 subdee

Update: It seems the problem occurs only if you install by downloading manually. Installation via composer doesn't have this problem.

subdee avatar Mar 27 '15 10:03 subdee

@subdee you mean if you install phpci via composer this bug doesn't exist? But if you download a tarball it does have the bug?

gnat42 avatar Mar 30 '15 18:03 gnat42

Yes, first I followed the instructions given https://www.phptesting.org/wiki/Installing-PHPCI and I had this issue. Then I followed the instructions given https://www.phptesting.org/install-phpci and it worked fine.

The instructions should actually be consistent, but that's a different issue.

subdee avatar Mar 30 '15 19:03 subdee

I downloaded phpci archive manually, ran composer install and the bug persists.

EDIT: using composer create-project the bug exists anyway.

briedis avatar Apr 17 '15 13:04 briedis

The issue persist, i also follow the instructions and ran into this issue

Baachi avatar May 16 '15 20:05 Baachi

Strange, i recreated the project and the issue doesn't persist anymore

Baachi avatar May 16 '15 20:05 Baachi

This problem occurs even in current versions. I try to connect my GitLab server with 1.6.5 and the current 1.7.0-beta2 The protocol is https and the address ends with .git All I get is

Sorry, there was a problem
Notice: unserialize(): Error at offset 0 of 2 bytes in /var/www/virtual/username/phpci/PHPCI/Model/Project.php line 100

jlntrt avatar Nov 14 '15 16:11 jlntrt

I think the problem could be here:

protected function processAccessInformation(Project &$project)
{
    $matches = array();
    $reference = $project->getReference();

    if ($project->getType() == 'gitlab') {
        $info = array();

        if (preg_match('`^(.+)@(.+):([0-9]*)\/?(.+)\.git`', $reference, $matches)) {
            $info['user'] = $matches[1];
            $info['domain'] = $matches[2];
            $info['port'] = $matches[3];

            $project->setReference($matches[4]);
        }

        $project->setAccessInformation($info);
    }
}

A viable solution from end-user point of view is that you should not use the https url to the repository, but the ssh one. So this: [email protected]:owner/project.git Instead of this: https://gitlab.com/owner/project.git

This because if you use the last one (https://gitlab.com/user/project.git), $info will be an empty array, that will create a problem in the following function (since $info will be = '[]', returning true to substr($info, 0, 1) != '{'):

public function getAccessInformation($key = null)
{
    $info = $this->data['access_information'];

    // Handle old-format (serialized) access information first:

    if (!empty($info) && substr($info, 0, 1) != '{') {
        $data = unserialize($info);
    } else {
        $data = json_decode($info, true);
    }

    if (is_null($key)) {
        $rtn = $data;
    } elseif (isset($data[$key])) {
        $rtn = $data[$key];
    } else {
        $rtn = null;
    }

    return $rtn;
}

I hope this will help.

WitTrue avatar Dec 16 '15 17:12 WitTrue