login/pass: error messages below page title
[minimedit.git] / upload.inc.php
index afaa047303b3cf420872460325303056d791adf9..22db140cd27351543f12682ab41eae4b74d05348 100644 (file)
@@ -1,4 +1,10 @@
 <?php
+global $journalcol;
+$journalcol = [
+       'assign' => 'Toegewezen aan',
+       'subject' => 'Onderwerp',
+];
+
 function userupload($input, $target = NULL, $filename = NULL)
 {
        switch ($input['error']) {
@@ -27,6 +33,9 @@ function userupload($input, $target = NULL, $filename = NULL)
                $target .= $input['name'];
        }
 
+       if (file_exists($target)) {
+               throw new Exception("bestandsnaam al aanwezig op $target");
+       }
        if (!@move_uploaded_file($input['tmp_name'], $target)) {
                throw new Exception("bestand kon niet worden opgeslagen in $target");
        }
@@ -41,13 +50,146 @@ function userupload($input, $target = NULL, $filename = NULL)
 function messagehtml($input)
 {
        # convert user textarea post to formatted html
+       global $User;
        if (empty($input)) {
                return;
        }
-       $html = preg_replace(
-               ["/\r?\n/", "'(?:<br />\n?){2}'"],
-               ["<br />\n", "</p>\n\n<p>"],
-               htmlspecialchars($input)
-       );
-       return "<p>$html</p>";
+       if ($User and $User->admin and preg_match('/\A<[a-z][^>]*>/', $input)) {
+               return $input;  # allow html input as is if privileged
+       }
+       $markup = [
+               '{&lt;((?:\w+:|/).+?)&gt;}'    => '<$1>',                # unescape link entities
+               '{<(?:https?://)?([^>\s|]+)>}' => '<$1 $1>',             # unnamed link
+               '{<([^>\s|]+)[\s|]([^>]+)>}'   => '<a href="$1">$2</a>', # hyperlink
+               "/\r\n?/" => "\n",        # unix newlines
+               "/  +\n/" => "<br />",    # trailing spaces for hard line break
+               '{^(/data/.*\.jpe?g)\z}m'      => '<img src="/thumb/640x/\1" />', # image reference
+               "/^[-*] (.*)$\n?/m"            => '<li>$1</li>',         # list item
+               "/^(.+)$\n?/m"                 => "<p>$1</p>\n",         # paragraph
+               "{^<p>(<li>.*</li>)(?:</p>\n)?}m" => "<ul>$1</ul>\n",    # list container
+               '/_(?<!\w_)(.+?)_(?!\w)/'      => '<em>$1</em>',         # italic
+               '/\*(?<!\w\*)(.+?)\*(?!\w)/'   => '<strong>$1</strong>', # bold
+               '/~(?<!\w~)(.+?)~(?!\w)/'      => '<s>$1</s>',           # stricken
+               '/`(?<!\w`)(.+?)`(?!\w)/'      => '<code>$1</code>',     # monospace
+       ];
+       return preg_replace(array_keys($markup), array_values($markup), htmlspecialchars($input));
+}
+
+function createcomment($input, &$Issue = NULL)
+{
+       # insert user message as database issue/reply
+       global $User, $Db, $Page, $journalcol;
+
+       $reply = [];
+       if (isset($input['reply']) and $body = $input['reply']) {
+               $reply['raw'] = $body;
+               $reply['message'] = messagehtml($body);
+       }
+       if ($_FILES and !empty($_FILES['image'])) {
+               $target = 'data/upload';
+               if (!file_exists($target)) {
+                       throw new Exception("er is geen uploadmap aanwezig op $target");
+               }
+               $target .= '/' . $User->login;
+               if ($result = userupload($_FILES['image'], $target)) {
+                       $reply['raw'] = $reply['raw'] ?? '';
+                       $reply['raw'] .= "/$result";
+                       $reply['message'] = $reply['message'] ?? '';
+                       if (preg_match('(^image/)', $_FILES['image']['type'])) {
+                               $reply['message'] .= sprintf('<p><img src="/thumb/640x/%s" /></p>', $result);
+                       }
+                       else {
+                               $reply['message'] .= sprintf('<p>Bijgevoegd bestand: <a href="/%s" />%s</a></p>',
+                                       $result, basename($result)
+                               );
+                       }
+               }
+       }
+       if (!$reply) {
+               throw new Exception("lege inhoud");
+       }
+       if (isset($input['announce'])) {
+               $reply['announced'] = !!$input['announce'];
+       }
+       if (isset($input['page'])) {
+               $reply['page'] = $input['page'];
+       }
+
+       if (isset($input['id'])) {
+               $newcomment = $input['id'];
+               $filter = ['id = ?', $newcomment];
+               $oldcomment = $Db->query("SELECT * FROM comments WHERE $filter[0]", [$filter[1]])->fetch();
+               if (empty($oldcomment)) {
+                       throw new Exception('Antwoord niet gevonden');
+               }
+
+               $reply += [
+                       'updated' => ['now()'],
+               ];
+               $query = $Db->set('comments', $reply, $filter);
+               if (!$query->rowCount()) {
+                       throw new Exception('Fout bij aanpassen');
+               }
+
+               if ($updated = $query->fetch()) {
+                       foreach (array_keys(get_object_vars($updated)) as $col) {
+                               if ($updated->$col === $oldcomment->$col) {
+                                       continue; # unaltered
+                               }
+                               $Db->set('journal', [
+                                       'comment_id' => $newcomment,
+                                       'property'   => 'col',
+                                       'col'        => $col,
+                                       'old_value'  => $oldcomment->$col,
+                                       'value'      => $updated->$col,
+                               ]);
+                       }
+               }
+       }
+       else {
+               $reply += [
+                       'page'    => "{$Page->handler}/{$Issue->id}",
+                       'author'  => $User->login,
+               ];
+               $query = $Db->set('comments', $reply);
+               if (!$query->rowCount()) {
+                       throw new Exception('Fout bij opslaan');
+               }
+               $newcomment = $Db->dbh->lastInsertId('comments_id_seq');
+       }
+
+       if (isset($Issue)) {
+               $row = [];
+               foreach (array_keys($journalcol) as $col) {
+                       if (!isset($input[$col])) continue;
+                       $row[$col] = $input[$col] ?: NULL;
+               }
+               if (isset($input['status'])) {
+                       $reset = !empty($input['status']);
+                       if (isset($Issue->closed) !== $reset) {
+                               $row['closed'] = $reset ? ['now()'] : NULL;
+                       }
+               }
+               $derived = ['updated' => ['now()']];
+               $filter = ['id = ?', $Issue->id];
+               $subquery = $Db->set('issues', $row + $derived, $filter);
+
+               if ($updated = $subquery->fetch()) {
+                       foreach (array_keys($row) as $col) {
+                               if ($updated->$col === $Issue->$col) {
+                                       continue; # unaltered
+                               }
+                               $Db->set('journal', [
+                                       'comment_id' => $newcomment,
+                                       'property'   => 'attr',
+                                       'col'        => $col,
+                                       'old_value'  => $Issue->$col,
+                                       'value'      => $updated->$col,
+                               ]);
+                       }
+                       $Issue = $updated;
+               }
+       }
+
+       return $newcomment;
 }