aboutsummaryrefslogtreecommitdiff
path: root/src/Phorkie/Repository/Post.php
blob: 632f321c0ca3a187e3fe7a4256544c48d6fd9bf0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
namespace Phorkie;

class Repository_Post
{
    public $repo;

    public function __construct(Repository $repo = null)
    {
        $this->repo = $repo;
    }

    /**
     * Processes the POST data, changes description and files
     *
     * @return boolean True if the post was successful
     */
    public function process($postData)
    {
        if (!isset($postData['files'])) {
            return false;
        }

        if (!$this->repo) {
            $this->repo = $this->createRepo();
        }

        $vc = $this->repo->getVc();
        $this->repo->setDescription($postData['description']);

        $bChanged = false;
        foreach ($postData['files'] as $num => $arFile) {
            $orignalName = $this->sanitizeFilename($arFile['original_name']);
            $name        = $this->sanitizeFilename($arFile['name']);

            if ($name == '') {
                $name = $this->getNextNumberedFile('phork')
                    . '.' . $arFile['type'];
            }

            $bNew = false;
            if (!isset($orignalName) || $orignalName == '') {
                //new file
                $bNew = true;
            } else if (!$this->repo->hasFile($orignalName)) {
                //unknown file
                //FIXME: Show error message
                continue;
            } else if ($orignalName != $name) {
                //FIXME: what to do with overwrites?
                $vc->getCommand('mv')
                    ->addArgument($orignalName)
                    ->addArgument($name)
                    ->execute();
                $bChanged = true;
            }

            $file = $this->repo->getFileByName($name, false);
            if ($bNew || $file->getContent() != $arFile['content']) {
                file_put_contents($file->getPath(), $arFile['content']);
                $command = $vc->getCommand('add')
                    ->addArgument($file->getFilename())
                    ->execute();
                $bChanged = true;
            }
        }

        if ($bChanged) {
            $vc->getCommand('commit')
                ->setOption('message', '')
                ->setOption('allow-empty-message')
                ->setOption('author', 'Anonymous <anonymous@phorkie>')
                ->execute();
        }

        return true;
    }

    public function createRepo()
    {
        $rs = new Repositories();
        $repo = $rs->createNew();
        $vc = $repo->getVc();
        $vc->initRepository();
        foreach (glob($repo->repoDir . '/.git/hooks/*') as $hookfile) {
            unlink($hookfile);
        }
        return $repo;
    }

    public function getNextNumberedFile($prefix)
    {
        $num = -1;
        do {
            ++$num;
            $files = glob($this->repo->repoDir . '/' . $prefix . $num . '.*');
        } while (count($files));

        return $prefix . $num;
    }

    /**
     * Removes malicious parts from a file name
     *
     * @param string $file File name from the user
     *
     * @return string Fixed and probably secure filename
     */
    public function sanitizeFilename($file)
    {
        $file = trim($file);
        $file = str_replace(array('\\', '//'), '/', $file);
        $file = str_replace('/../', '/', $file);
        if (substr($file, 0, 3) == '../') {
            $file = substr($file, 3);
        }
        if (substr($file, 0, 1) == '../') {
            $file = substr($file, 1);
        }

        return $file;
    }
}

?>