Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
avatar
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 5
90
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 handle
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 is_allowed
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 decode_filename
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 prepare
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 *
4 * This file is part of the phpBB Forum Software package.
5 *
6 * @copyright (c) phpBB Limited <https://www.phpbb.com>
7 * @license GNU General Public License, version 2 (GPL-2.0)
8 *
9 * For full copyright and license information, please see
10 * the docs/CREDITS.txt file.
11 *
12 */
13
14namespace phpbb\storage\controller;
15
16use phpbb\cache\service;
17use phpbb\config\config;
18use phpbb\db\driver\driver_interface;
19use phpbb\mimetype\extension_guesser;
20use phpbb\storage\storage;
21use Symfony\Component\HttpFoundation\Request as symfony_request;
22use Symfony\Component\HttpFoundation\Response;
23use Symfony\Component\HttpFoundation\ResponseHeaderBag;
24use Symfony\Component\HttpFoundation\StreamedResponse;
25
26/**
27 * Controller for /download/avatar/{file} routes
28 */
29class avatar extends controller
30{
31    /** @var config */
32    protected $config;
33
34    /** @var array */
35    protected $allowed_extensions = ['png', 'gif', 'jpg', 'jpeg'];
36
37    /**
38     * Constructor
39     *
40     * @param service                $cache
41     * @param config                $config
42     * @param driver_interface        $db
43     * @param extension_guesser        $extension_guesser
44     * @param storage                $storage
45     * @param symfony_request        $symfony_request
46     */
47    public function __construct(service $cache, config $config, driver_interface $db, extension_guesser $extension_guesser, storage $storage, symfony_request $symfony_request)
48    {
49        parent::__construct($cache, $db , $extension_guesser, $storage, $symfony_request);
50
51        $this->config = $config;
52    }
53
54    /**
55     * {@inheritdoc}
56     */
57    public function handle(string $file): Response
58    {
59        $file = $this->decode_filename($file);
60
61        return parent::handle($file);
62    }
63
64    /**
65     * {@inheritdoc}
66     */
67    protected function is_allowed(string $file): bool
68    {
69        $ext = substr(strrchr($file, '.'), 1);
70
71        // If filename have point and have an allowed extension
72        return strpos($file, '.') && in_array($ext, $this->allowed_extensions, true);
73    }
74
75    /**
76     * Decode avatar filename
77     *
78     * @param string $file        Filename
79     *
80     * @return string Filename in filesystem
81     */
82    protected function decode_filename(string $file): string
83    {
84        $avatar_group = false;
85
86        if (isset($file[0]) && $file[0] === 'g')
87        {
88            $avatar_group = true;
89            $file = substr($file, 1);
90        }
91
92        $ext    = substr(strrchr($file, '.'), 1);
93        $file    = (int) $file;
94
95        return $this->config['avatar_salt'] . '_' . ($avatar_group ? 'g' : '') . $file . '.' . $ext;
96    }
97
98    /**
99     * {@inheritdoc}
100     */
101    protected function prepare(StreamedResponse $response, string $file): void
102    {
103        $response->setPublic();
104
105        $disposition = $response->headers->makeDisposition(
106            ResponseHeaderBag::DISPOSITION_INLINE,
107            rawurlencode($file)
108        );
109
110        $response->headers->set('Content-Disposition', $disposition);
111
112        $time = new \DateTime();
113        $response->setExpires($time->modify('+1 year'));
114
115        parent::prepare($response, $file);
116    }
117}