/**
  * Creates a new FileAttachment for a post using a hash.
  *
  * @param  Post  $post
  * @param  string  $filename
  * @param  boolean  $spoiler
  * @return FileAttachment
  */
 public function createAttachmentWithThis(Post $post, $filename, $spoiler = false, $autosave = true)
 {
     $fileName = pathinfo($filename, PATHINFO_FILENAME);
     $fileExt = $this->guessExtension();
     $attachment = new FileAttachment();
     $attachment->post_id = $post->post_id;
     $attachment->file_id = $this->file_id;
     $attachment->filename = urlencode("{$fileName}.{$fileExt}");
     $attachment->is_spoiler = !!$spoiler;
     if ($autosave) {
         $attachment->save();
         $this->upload_count++;
         $this->save();
     }
     return $attachment;
 }
Example #2
0
 /**
  * Creates a new FileAttachment for a post.
  *
  * @param  UploadedFile  $file
  * @param  Post  $post
  * @return FileAttachment
  */
 public static function createAttachment(UploadedFile $file, Post $post)
 {
     $storage = static::storeUpload($file);
     $uploadName = urlencode($file->getClientOriginalName());
     $uploadExt = pathinfo($uploadName, PATHINFO_EXTENSION);
     $fileName = basename($uploadName, "." . $uploadExt);
     $fileExt = $storage->guessExtension();
     $attachment = new FileAttachment();
     $attachment->post_id = $post->post_id;
     $attachment->file_id = $storage->file_id;
     $attachment->filename = urlencode("{$fileName}.{$fileExt}");
     $attachment->save();
     return $attachment;
 }
Example #3
0
 public function importInfinityPostAttachments(Post $model, Board &$board, $post)
 {
     $post_id = $model->post_id;
     if (!$post_id) {
         return 0;
     }
     $attachments = @json_decode($post->files, true);
     if (!is_array($attachments)) {
         return 0;
     }
     $aModels = [];
     foreach ($attachments as $aIndex => $attachment) {
         if (isset($attachment['error']) && $attachment['error']) {
             continue;
         }
         if (!isset($attachment['file_path']) || !isset($attachment['thumb_path'])) {
             continue;
         }
         $storage = null;
         $path = "{$this->targetLocation}/{$attachment['file_path']}";
         $thumb = "{$this->targetLocation}/{$attachment['thumb_path']}";
         if (file_exists($path)) {
             if (!isset($attachment['type'])) {
                 continue;
             }
             if (!isset($attachment['hash'])) {
                 $attachment['hash'] = md5(file_get_contents($path));
             }
             $storage = FileStorage::getHash($attachment['hash']);
             if (!$storage || (!file_exists($storage->getFullPath()) || !file_exists($storage->getFullPathThumb()))) {
                 $height = null;
                 $width = null;
                 if (isset($attachment['width']) && isset($attachment['height'])) {
                     $height = $attachment['height'];
                     $width = $attachment['width'];
                 }
                 if (!$storage) {
                     $storage = new FileStorage(['hash' => $attachment['hash'], 'banned' => false, 'filesize' => $attachment['size'], 'file_width' => $width, 'file_height' => $height, 'mime' => $attachment['type'], 'meta' => null, 'first_uploaded_at' => Carbon::now(), 'last_uploaded_at' => Carbon::now(), 'upload_count' => 1]);
                 }
                 Storage::makeDirectory($storage->getDirectory());
                 if (!file_exists($storage->getFullPath())) {
                     if (is_link($storage->getFullPath())) {
                         unlink($storage->getFullPath());
                     }
                     symlink($path, $storage->getFullPath());
                 }
                 if ($attachment['thumbwidth'] && file_exists($thumb)) {
                     $storage->has_thumbnail = true;
                     $storage->thumbnail_width = $attachment['thumbwidth'];
                     $storage->thumbnail_height = $attachment['thumbheight'];
                     Storage::makeDirectory($storage->getDirectoryThumb());
                     if (!file_exists($storage->getFullPathThumb())) {
                         if (is_link($storage->getFullPathThumb())) {
                             unlink($storage->getFullPathThumb());
                         }
                         symlink($thumb, $storage->getFullPathThumb());
                     }
                 }
                 $storage->save();
             }
             if ($storage && $storage->exists) {
                 $aModel = ['post_id' => $post_id, 'file_id' => $storage->file_id, 'filename' => $attachment['filename'], 'is_spoiler' => false, 'is_deleted' => false, 'position' => $aIndex];
                 $aModels[] = $aModel;
             } else {
                 ++$skips;
             }
         }
     }
     FileAttachment::insert($aModels);
     return count($aModels);
 }
Example #4
0
 /**
  * Delete a post's attachment.
  *
  * @param  \App\FileAttachment  $attachment
  * @return Response
  */
 public function postSpoilerAttachment(Board $board, FileAttachment $attachment)
 {
     if (!$attachment->exists) {
         return abort(404);
     }
     $input = Input::all();
     $validator = Validator::make($input, ['scope' => "required|string|in:other,self", 'confirm' => "boolean|required_if:scope,other", 'password' => "string|required_if:scope,self"]);
     if (!$validator->passes()) {
         return redirect()->back()->withInput($input)->withErrors($validator->errors());
     }
     if ($input['scope'] == "other") {
         if ($this->user->canDeleteGlobally() || $this->user->canDeleteLocally($board)) {
             $this->log(!$attachment->is_spoiler ? 'log.attachment.spoiler' : 'log.attachment.unspoiler', $attachment->post, ["board_uri" => $attachment->post->board_uri, "board_id" => $attachment->post->board_id, "post_id" => $attachment->post->post_id, "file" => $attachment->storage->hash]);
         } else {
             abort(403);
         }
     } else {
         if ($input['scope'] == "self") {
             if ($this->user->canDeletePostWithPassword($board)) {
                 if (!$attachment->post->checkPassword($input['password'])) {
                     return redirect()->back()->withInput($input)->withErrors(['password' => \Lang::trans('validation.password', ['attribute' => "password"])]);
                 }
             }
         }
     }
     $attachment->is_spoiler = !$attachment->is_spoiler;
     $attachment->save();
     Event::fire(new AttachmentWasModified($attachment));
     return redirect($attachment->post->getURL());
 }
Example #5
0
 /**
  * Pushes the post to the specified board, as a new thread or as a reply.
  * This autoatically handles concurrency issues. Creating a new reply without
  * using this method is forbidden by the `creating` event in ::boot.
  *
  *
  * @param  App\Board  &$board
  * @param  App\Post   &$thread
  * @return void
  */
 public function submitTo(Board &$board, &$thread = null)
 {
     $this->board_uri = $board->board_uri;
     $this->author_ip = Request::getClientIp();
     $this->reply_last = $this->freshTimestamp();
     $this->bumped_last = $this->reply_last;
     $this->setCreatedAt($this->reply_last);
     $this->setUpdatedAt($this->reply_last);
     if (!is_null($thread) && !$thread instanceof Post) {
         $thread = $board->getLocalThread($thread);
         $this->reply_to = $thread->post_id;
         $this->reply_to_board_id = $thread->board_id;
     }
     // Store attachments
     $uploads = [];
     if (is_array($files = Input::file('files'))) {
         $uploads = array_filter($files);
     }
     // Store the post in the database.
     DB::transaction(function () use($thread) {
         // The objective of this transaction is to prevent concurrency issues in the database
         // on the unique joint index [`board_uri`,`board_id`] which is generated procedurally
         // alongside the primary autoincrement column `post_id`.
         // First instruction is to add +1 to posts_total.
         DB::table('boards')->where('board_uri', $this->board_uri)->increment('posts_total');
         // Second, we record this value and lock the table.
         $boards = DB::table('boards')->where('board_uri', $this->board_uri)->lockForUpdate()->select('posts_total')->get();
         $posts_total = $boards[0]->posts_total;
         // Optionally, the OP of this thread needs a +1 to reply count.
         if ($thread instanceof Post) {
             if (!$this->isBumpless() && !$thread->isBumplocked()) {
                 $thread->bumped_last = $this->created_at;
             }
             $thread->reply_last = $this->created_at;
             $thread->reply_count += 1;
             $thread->save();
         }
         // Finally, we set our board_id and save.
         $this->board_id = $posts_total;
         $this->save();
         // Queries and locks are handled automatically after this closure ends.
     });
     // Process uploads.
     if (count($uploads) > 0) {
         foreach ($uploads as $uploadIndex => $upload) {
             if (file_exists($upload->getPathname())) {
                 $uploadName = urlencode($upload->getClientOriginalName());
                 $uploadExt = pathinfo($uploadName, PATHINFO_EXTENSION);
                 $fileName = basename($uploadName, "." . $uploadExt);
                 $fileExt = $upload->guessExtension();
                 $storage = FileStorage::storeUpload($upload);
                 $attachment = new FileAttachment();
                 $attachment->post_id = $this->post_id;
                 $attachment->file_id = $storage->file_id;
                 $attachment->filename = urlencode("{$fileName}.{$fileExt}");
                 $attachment->save();
             }
         }
     }
     // Finally fire event on OP, if it exists.
     if ($thread instanceof Post) {
         Event::fire(new ThreadNewReply($thread));
     }
 }
 /**
  * Define your route model bindings, pattern filters, etc.
  *
  * @param  \Illuminate\Routing\Router  $router
  * @return void
  */
 public function boot(Router $router)
 {
     // Sets up our routing tokens.
     $router->pattern('attachment', '[0-9]\\d*');
     $router->pattern('board', Board::URI_PATTERN);
     $router->pattern('id', '[0-9]\\d*');
     $router->model('attachment', '\\App\\FileAttachment');
     $router->model('ban', '\\App\\Ban');
     $router->model('board', '\\App\\Board');
     $router->model('post', '\\App\\Post');
     $router->model('report', '\\App\\Report');
     $router->model('role', '\\App\\Role');
     $router->bind('user', function ($value, $route) {
         if (is_numeric($value)) {
             return \App\User::find($value);
         } else {
             if (preg_match('/^[a-z0-9]{1,64}\\.(?P<id>\\d+)$/i', $value, $matches)) {
                 return \App\User::find($matches['id']);
             }
         }
     });
     $router->bind('board', function ($value, $route) {
         $board = Board::getBoardForRouter($this->app, $value);
         if ($board) {
             $board->applicationSingleton = true;
             return $board;
         }
         return abort(404);
     });
     $router->bind('attachment', function ($value, $route) {
         return \App\FileAttachment::where('is_deleted', false)->with('storage')->find($value);
     });
     $router->bind('role', function ($value, $route) {
         if (is_numeric($value)) {
             return \App\Role::find($value);
         } else {
             if (preg_match('/^[a-z0-9]{1,64}\\.(?P<id>\\d+)$/i', $value, $matches)) {
                 return \App\Role::find($matches['id']);
             }
         }
     });
     $router->bind('post_id', function ($value, $route) {
         $board = $route->getParameter('board');
         if (!$board instanceof Board) {
             $board = $this->app->make("\\App\\Board");
         }
         if (is_numeric($value) && $board instanceof Board) {
             return $board->getThreadByBoardId($value);
         }
     });
     // Binds a matched instance of a {board} as a singleton instance.
     $router->matched(function ($route, $request) {
         $board = $route->getParameter('board');
         if ($board instanceof Board && $board->exists) {
             // Binds the board to the application if it exists.
             $this->app->singleton("\\App\\Board", function ($app) use($board) {
                 return $board;
             });
         }
         // Binds the post to the application if it exists.
         $post = $route->getParameter('post_id');
         if ($post instanceof Post && $post->exists) {
             $route->setParameter('post', $post);
             //$this->app->instance("\App\Post", $post);
             $this->app->singleton("\\App\\Post", function ($app) use($post) {
                 return $post;
             });
         }
     });
     parent::boot($router);
 }