Browse Source

Add file uploads 6/...

Visman 2 năm trước cách đây
mục cha
commit
49acb82f78

+ 2 - 0
.gitignore

@@ -11,3 +11,5 @@
 /public/.htaccess
 /public/index.php
 !.gitkeep
+/public/upload/**/*
+!/public/upload/index.html

+ 2 - 21
app/Core/File.php

@@ -74,25 +74,6 @@ class File
         return $this->error;
     }
 
-    /**
-     * Фильрует и переводит в латиницу(?) имя файла
-     */
-    protected function filterName(string $name): string
-    {
-        $name = \transliterator_transliterate(
-            "Any-Latin; NFD; [:Nonspacing Mark:] Remove; NFC; [:Punctuation:] Remove; Lower();",
-            $name
-        );
-
-        $name = \trim(\preg_replace('%[^\w.-]+%', '-', $name), '-');
-
-        if (! isset($name[0])) {
-            $name = (string) \time();
-        }
-
-        return $name;
-    }
-
     /**
      * Возвращает информацию о пути к сохраняемому файлу с учетом подстановок
      */
@@ -105,7 +86,7 @@ class File
         }
 
         if ('*' === $matches[2]) {
-            $matches[2] = $this->filterName($this->name);
+            $matches[2] = $this->files->filterName($this->name);
         }
 
         if ('*' === $matches[3]) {
@@ -154,7 +135,7 @@ class File
     protected function dirProc(string $dirname): bool
     {
         if (! \is_dir($dirname)) {
-            if (! \mkdir($dirname, 0755)) {
+            if (! \mkdir($dirname, 0755, true)) {
                 $this->error = 'Can not create directory';
 
                 return false;

+ 19 - 0
app/Core/Files.php

@@ -960,6 +960,25 @@ class Files
         return 0 + $value;
     }
 
+    /**
+     * Фильрует и переводит в латиницу(?) имя файла
+     */
+    public function filterName(string $name): string
+    {
+        $name = \transliterator_transliterate(
+            "Any-Latin; NFD; [:Nonspacing Mark:] Remove; NFC; Lower();",
+            $name
+        );
+
+        $name = \trim(\preg_replace(['%[^\w-]+%', '%_+%'], ['-', '_'], $name), '-_');
+
+        if (! isset($name[0])) {
+            $name = (string) \time();
+        }
+
+        return $name;
+    }
+
     /**
      * Возвращает текст ошибки
      */

+ 80 - 0
app/Models/Attachment/Attachments.php

@@ -10,15 +10,95 @@ declare(strict_types=1);
 
 namespace ForkBB\Models\Attachment;
 
+use ForkBB\Core\File;
+use ForkBB\Core\Image;
 use ForkBB\Models\Manager;
 use ForkBB\Models\User\User;
 use RuntimeException;
 
 class Attachments extends Manager
 {
+    const HTML_CONT = '<!DOCTYPE html><html lang="en"><head><title>.</title></head><body>.</body></html>';
+    const BAD_EXTS  = '%^(?:php.*|phar|phtml?|s?html?|jsp?|htaccess|htpasswd|f?cgi|)$%i';
+    const FOLDER    = '/upload/';
+
     /**
      * Ключ модели для контейнера
      */
     protected string $cKey = 'Attachments';
 
+    /**
+     * Сохраняет файл
+     */
+    public function addFile(File $file): ?array
+    {
+        $ext  = $file->ext();
+
+        if (\preg_match(self::BAD_EXTS, $ext)) {
+            return null;
+        }
+
+        $uid  = $this->c->user->id;
+        $now  = \time();
+        $name = $this->c->Files->filterName($file->name());
+
+        $vars = [
+            'uid'     => $uid,
+            'created' => $now,
+        ];
+        $query = 'INSERT INTO ::attachments (uid, created) VALUES (?i:uid, ?i:created)';
+
+        $this->c->DB->exec($query, $vars);
+
+        $id = (int) $this->c->DB->lastInsertId();
+
+        $p1 = \date('ym');
+        $p2 = (int) ($id / 1000);
+        $p3 = \substr($name, 0, 235 - \strlen($ext)) . '_' . \sprintf("%03d", $id - $p2);
+
+        $path     = "{$p1}/{$p2}/{$p3}.{$ext}";
+        $location = $this->c->DIR_PUBLIC . self::FOLDER . $path;
+
+        $result = $file
+            ->rename(false)
+            ->rewrite(false)
+            ->setQuality($this->c->config->i_upload_img_quality ?? 75)
+            //->resize($this->c->config->i_avatars_width, $this->c->config->i_avatars_height)
+            ->toFile($location);
+
+        if (true !== $result) {
+            $this->c->Log->warning("Attachments Failed processing {$path}", [
+                'user'    => $this->user->fLog(),
+                'error'   => $file->error(),
+            ]);
+
+            $vars = [
+                ':id' => $id,
+            ];
+            $query = "DELETE FROM ::attachments WHERE id=?i:id";
+
+            $this->c->DB->exec($query, $vars);
+
+            return null;
+        }
+
+        $size = $this->c->Files->size(\filesize($location), 'K');
+        $vars = [
+            ':id'      => $id,
+            ':path'    => $path,
+            ':size_kb' => $size,
+        ];
+        $query = 'UPDATE ::attachments SET size_kb=?i:size_kb, path=?s:path WHERE id=?i:id';
+
+        $this->c->DB->exec($query, $vars);
+
+        return [
+            'id'       => $id,
+            'uid'      => $uid,
+            'created'  => $now,
+            'size_kb'  => $size,
+            'path'     => $path,
+            'location' => $location,
+        ];
+    }
 }

+ 2 - 2
app/Models/Pages/PostFormTrait.php

@@ -327,7 +327,7 @@ trait PostFormTrait
                     $cur['data'] = [
                         'SCEditorConfig' => $scConfig,
                         'smiliesEnabled' => $smiliesEnabled,
-                        'linkEnabled'    => $this->c->user->g_post_links,
+                        'linkEnabled'    => $this->user->g_post_links,
                     ];
 
                     $this->pageHeader('sceditor', 'script', 9600, [
@@ -354,7 +354,7 @@ trait PostFormTrait
                         'href' => $this->publicLink("/style/sc/themes/default.css"),
                     ]);
 
-                    if ($this->c->user->g_post_links) {
+                    if ($this->user->g_post_links) {
                         $this->pageHeader('imgbb', 'script', 0, [
                             'src' => $this->publicLink('/js/imgbb.js'),
                         ]);

+ 7 - 4
app/Models/Pages/PostValidatorTrait.php

@@ -312,11 +312,14 @@ trait PostValidatorTrait
             return null;
         }
 
-        $attachments = $v->attachments;
-
         $result = "\n";
-        foreach ($attachments as $a) {
-            $result .= ' ' . $a->name() . '.' . $a->ext();
+
+        foreach ($v->attachments as $file) {
+            $data = $this->c->attachments->addFile($file);
+
+            if (\is_array($data)) {
+                $result .= ' ' . $data['path'];
+            }
         }
 
         return $result;