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