632f321c0ca3a187e3fe7a4256544c48d6fd9bf0
[phorkie.git] / src / Phorkie / Repository / Post.php
1 <?php
2 namespace Phorkie;
3
4 class Repository_Post
5 {
6     public $repo;
7
8     public function __construct(Repository $repo = null)
9     {
10         $this->repo = $repo;
11     }
12
13     /**
14      * Processes the POST data, changes description and files
15      *
16      * @return boolean True if the post was successful
17      */
18     public function process($postData)
19     {
20         if (!isset($postData['files'])) {
21             return false;
22         }
23
24         if (!$this->repo) {
25             $this->repo = $this->createRepo();
26         }
27
28         $vc = $this->repo->getVc();
29         $this->repo->setDescription($postData['description']);
30
31         $bChanged = false;
32         foreach ($postData['files'] as $num => $arFile) {
33             $orignalName = $this->sanitizeFilename($arFile['original_name']);
34             $name        = $this->sanitizeFilename($arFile['name']);
35
36             if ($name == '') {
37                 $name = $this->getNextNumberedFile('phork')
38                     . '.' . $arFile['type'];
39             }
40
41             $bNew = false;
42             if (!isset($orignalName) || $orignalName == '') {
43                 //new file
44                 $bNew = true;
45             } else if (!$this->repo->hasFile($orignalName)) {
46                 //unknown file
47                 //FIXME: Show error message
48                 continue;
49             } else if ($orignalName != $name) {
50                 //FIXME: what to do with overwrites?
51                 $vc->getCommand('mv')
52                     ->addArgument($orignalName)
53                     ->addArgument($name)
54                     ->execute();
55                 $bChanged = true;
56             }
57
58             $file = $this->repo->getFileByName($name, false);
59             if ($bNew || $file->getContent() != $arFile['content']) {
60                 file_put_contents($file->getPath(), $arFile['content']);
61                 $command = $vc->getCommand('add')
62                     ->addArgument($file->getFilename())
63                     ->execute();
64                 $bChanged = true;
65             }
66         }
67
68         if ($bChanged) {
69             $vc->getCommand('commit')
70                 ->setOption('message', '')
71                 ->setOption('allow-empty-message')
72                 ->setOption('author', 'Anonymous <anonymous@phorkie>')
73                 ->execute();
74         }
75
76         return true;
77     }
78
79     public function createRepo()
80     {
81         $rs = new Repositories();
82         $repo = $rs->createNew();
83         $vc = $repo->getVc();
84         $vc->initRepository();
85         foreach (glob($repo->repoDir . '/.git/hooks/*') as $hookfile) {
86             unlink($hookfile);
87         }
88         return $repo;
89     }
90
91     public function getNextNumberedFile($prefix)
92     {
93         $num = -1;
94         do {
95             ++$num;
96             $files = glob($this->repo->repoDir . '/' . $prefix . $num . '.*');
97         } while (count($files));
98
99         return $prefix . $num;
100     }
101
102     /**
103      * Removes malicious parts from a file name
104      *
105      * @param string $file File name from the user
106      *
107      * @return string Fixed and probably secure filename
108      */
109     public function sanitizeFilename($file)
110     {
111         $file = trim($file);
112         $file = str_replace(array('\\', '//'), '/', $file);
113         $file = str_replace('/../', '/', $file);
114         if (substr($file, 0, 3) == '../') {
115             $file = substr($file, 3);
116         }
117         if (substr($file, 0, 1) == '../') {
118             $file = substr($file, 1);
119         }
120
121         return $file;
122     }
123 }
124
125 ?>