move filename sanitation to tools
[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             $bUpload = false;
34             if ($_FILES['files']['error'][$num]['upload'] == 0) {
35                 //valid file upload
36                 $bUpload = true;
37             } else if ($arFile['content'] == '' && $arFile['name'] == '') {
38                 //empty (new) file
39                 continue;
40             }
41
42             $orignalName = Tools::sanitizeFilename($arFile['original_name']);
43             $name        = Tools::sanitizeFilename($arFile['name']);
44
45             if ($name == '') {
46                 if ($bUpload) {
47                     $name = Tools::sanitizeFilename($_FILES['files']['name'][$num]['upload']);
48                 } else {
49                     $name = $this->getNextNumberedFile('phork')
50                         . '.' . $arFile['type'];
51                 }
52             }
53
54             $bNew = false;
55             $bDelete = false;
56             if (!isset($orignalName) || $orignalName == '') {
57                 //new file
58                 $bNew = true;
59                 if (strpos($name, '.') === false) {
60                     //automatically append file extension if none is there
61                     $name .= '.' . $arFile['type'];
62                 }
63             } else if (!$this->repo->hasFile($orignalName)) {
64                 //unknown file
65                 //FIXME: Show error message
66                 continue;
67             } else if (isset($arFile['delete']) && $arFile['delete'] == 1) {
68                 $bDelete = true;
69             } else if ($orignalName != $name) {
70                 if (strpos($name, '/') === false) {
71                     //ignore names with a slash in it, would be new directory
72                     //FIXME: what to do with overwrites?
73                     $vc->getCommand('mv')
74                         ->addArgument($orignalName)
75                         ->addArgument($name)
76                         ->execute();
77                     $bChanged = true;
78                 } else {
79                     $name = $orignalName;
80                 }
81             }
82
83             $file = $this->repo->getFileByName($name, false);
84             if ($bDelete) {
85                 $command = $vc->getCommand('rm')
86                     ->addArgument($file->getFilename())
87                     ->execute();
88                 $bChanged = true;
89             } else if ($bUpload) {
90                 move_uploaded_file(
91                     $_FILES['files']['tmp_name'][$num]['upload'], $file->getFullPath()
92                 );
93                 $command = $vc->getCommand('add')
94                     ->addArgument($file->getFilename())
95                     ->execute();
96                 $bChanged = true;
97             } else if ($bNew || (isset($arFile['content']) && $file->getContent() != $arFile['content'])) {
98                 file_put_contents($file->getFullPath(), $arFile['content']);
99                 $command = $vc->getCommand('add')
100                     ->addArgument($file->getFilename())
101                     ->execute();
102                 $bChanged = true;
103             }
104         }
105
106         if ($bChanged) {
107             $vc->getCommand('commit')
108                 ->setOption('message', '')
109                 ->setOption('allow-empty-message')
110                 ->setOption('author', 'Anonymous <anonymous@phorkie>')
111                 ->execute();
112         }
113
114         return true;
115     }
116
117     public function createRepo()
118     {
119         $rs = new Repositories();
120         $repo = $rs->createNew();
121         $vc = $repo->getVc();
122         $vc->getCommand('init')
123             //this should be setOption, but it fails with a = between name and value
124             ->addArgument('--separate-git-dir')
125             ->addArgument($GLOBALS['phorkie']['cfg']['gitdir'] . '/' . $repo->id . '.git')
126             ->addArgument($repo->workDir)
127             ->execute();
128
129         foreach (glob($repo->gitDir . '/hooks/*') as $hookfile) {
130             unlink($hookfile);
131         }
132
133         touch($repo->gitDir . '/git-daemon-export-ok');
134
135         return $repo;
136     }
137
138     public function getNextNumberedFile($prefix)
139     {
140         $num = -1;
141         do {
142             ++$num;
143             $files = glob($this->repo->workDir . '/' . $prefix . $num . '.*');
144         } while (count($files));
145
146         return $prefix . $num;
147     }
148 }
149
150 ?>