b9d9be5aa626e6af73ca4556e2debc6481f66196
[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 $arFile) {
33             if ($arFile['content'] == '' && $arFile['name'] == '') {
34                 //empty (new) file
35                 continue;
36             }
37
38             $orignalName = $this->sanitizeFilename($arFile['original_name']);
39             $name        = $this->sanitizeFilename($arFile['name']);
40
41             if ($name == '') {
42                 $name = $this->getNextNumberedFile('phork')
43                     . '.' . $arFile['type'];
44             }
45
46             $bNew = false;
47             $bDelete = false;
48             if (!isset($orignalName) || $orignalName == '') {
49                 //new file
50                 $bNew = true;
51                 if (strpos($name, '.') === false) {
52                     //automatically append file extension if none is there
53                     $name .= '.' . $arFile['type'];
54                 }
55             } else if (!$this->repo->hasFile($orignalName)) {
56                 //unknown file
57                 //FIXME: Show error message
58                 continue;
59             } else if (isset($arFile['delete']) && $arFile['delete'] == 1) {
60                 $bDelete = true;
61             } else if ($orignalName != $name) {
62                 //FIXME: what to do with overwrites?
63                 $vc->getCommand('mv')
64                     ->addArgument($orignalName)
65                     ->addArgument($name)
66                     ->execute();
67                 $bChanged = true;
68             }
69
70             $file = $this->repo->getFileByName($name, false);
71             if ($bDelete) {
72                 $command = $vc->getCommand('rm')
73                     ->addArgument($file->getFilename())
74                     ->execute();
75                 $bChanged = true;
76             } else if ($bNew || $file->getContent() != $arFile['content']) {
77                 file_put_contents($file->getPath(), $arFile['content']);
78                 $command = $vc->getCommand('add')
79                     ->addArgument($file->getFilename())
80                     ->execute();
81                 $bChanged = true;
82             }
83         }
84
85         if ($bChanged) {
86             $vc->getCommand('commit')
87                 ->setOption('message', '')
88                 ->setOption('allow-empty-message')
89                 ->setOption('author', 'Anonymous <anonymous@phorkie>')
90                 ->execute();
91         }
92
93         return true;
94     }
95
96     public function createRepo()
97     {
98         $rs = new Repositories();
99         $repo = $rs->createNew();
100         $vc = $repo->getVc();
101         $vc->initRepository();
102
103         foreach (glob($repo->repoDir . '/.git/hooks/*') as $hookfile) {
104             unlink($hookfile);
105         }
106
107         touch($repo->repoDir . '/.git/git-daemon-export-ok');
108
109         return $repo;
110     }
111
112     public function getNextNumberedFile($prefix)
113     {
114         $num = -1;
115         do {
116             ++$num;
117             $files = glob($this->repo->repoDir . '/' . $prefix . $num . '.*');
118         } while (count($files));
119
120         return $prefix . $num;
121     }
122
123     /**
124      * Removes malicious parts from a file name
125      *
126      * @param string $file File name from the user
127      *
128      * @return string Fixed and probably secure filename
129      */
130     public function sanitizeFilename($file)
131     {
132         $file = trim($file);
133         $file = str_replace(array('\\', '//'), '/', $file);
134         $file = str_replace('/../', '/', $file);
135         if (substr($file, 0, 3) == '../') {
136             $file = substr($file, 3);
137         }
138         if (substr($file, 0, 1) == '../') {
139             $file = substr($file, 1);
140         }
141
142         return $file;
143     }
144 }
145
146 ?>