Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 232
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
phpbb_functional_ucp_attachments_test
0.00% covered (danger)
0.00%
0 / 232
0.00% covered (danger)
0.00%
0 / 7
342
0.00% covered (danger)
0.00%
0 / 1
 setUp
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 tearDown
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
42
 upload_file
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
2
 upload_file_pm
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
2
 test_ucp_list_attachments
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
2
 test_ucp_delete_expired_attachment
0.00% covered (danger)
0.00%
0 / 79
0.00% covered (danger)
0.00%
0 / 1
20
 test_pm_attachment
0.00% covered (danger)
0.00%
0 / 82
0.00% covered (danger)
0.00%
0 / 1
12
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
14/**
15 * @group functional
16 */
17class phpbb_functional_ucp_attachments_test extends phpbb_functional_test_case
18{
19    private $path;
20
21    protected function setUp(): void
22    {
23        parent::setUp();
24        $this->path = __DIR__ . '/fixtures/files/';
25        $this->add_lang('posting');
26
27        if (!$this->user_exists('ucp-file-test'))
28        {
29            $this->create_user('ucp-file-test');
30        }
31    }
32
33    protected function tearDown(): void
34    {
35        $iterator = new DirectoryIterator(__DIR__ . '/../../phpBB/files/');
36        foreach ($iterator as $fileinfo)
37        {
38            if ($fileinfo->isDot()
39                || $fileinfo->isDir()
40                || $fileinfo->getFilename() === 'index.htm'
41                || $fileinfo->getFilename() === '.htaccess'
42            )
43            {
44                continue;
45            }
46
47            unlink($fileinfo->getPathname());
48        }
49    }
50
51    private function upload_file($filename, $mimetype)
52    {
53        $crawler = self::$client->request(
54            'GET',
55            'posting.php?mode=reply&f=2&t=1&sid=' . $this->sid
56        );
57
58        $file_form_data = array_merge(['add_file' => $this->lang('ADD_FILE')], $this->get_hidden_fields($crawler, 'posting.php?mode=reply&f=2&t=1&sid=' . $this->sid));
59
60        $file = array(
61            'tmp_name' => $this->path . $filename,
62            'name' => $filename,
63            'type' => $mimetype,
64            'size' => filesize($this->path . $filename),
65            'error' => UPLOAD_ERR_OK,
66        );
67
68        $crawler = self::$client->request(
69            'POST',
70            'posting.php?mode=reply&t=1&sid=' . $this->sid,
71            $file_form_data,
72            array('fileupload' => $file)
73        );
74
75        return $crawler;
76    }
77
78    private function upload_file_pm($filename, $mimetype)
79    {
80        $crawler = self::$client->request(
81            'GET',
82            'ucp.php?i=pm&mode=compose&sid=' . $this->sid
83        );
84
85        $file_form_data = array_merge(['add_file' => $this->lang('ADD_FILE')], $this->get_hidden_fields($crawler, 'ucp.php?i=pm&mode=compose&sid=' . $this->sid));
86
87        $file = array(
88            'tmp_name' => $this->path . $filename,
89            'name' => $filename,
90            'type' => $mimetype,
91            'size' => filesize($this->path . $filename),
92            'error' => UPLOAD_ERR_OK,
93        );
94
95        $crawler = self::$client->request(
96            'POST',
97            'ucp.php?i=pm&mode=compose&sid=' . $this->sid,
98            $file_form_data,
99            array('fileupload' => $file)
100        );
101
102        return $crawler;
103    }
104
105    public function test_ucp_list_attachments()
106    {
107        $this->login('ucp-file-test');
108        $this->add_lang(['common', 'posting']);
109        $crawler = $this->upload_file('valid.jpg', 'image/jpeg');
110
111        // Ensure there was no error message rendered
112        $this->assertStringNotContainsString('<h2>' . $this->lang('INFORMATION') . '</h2>', $this->get_content());
113
114        // Also the file name should be in the first row of the files table
115        $this->assertEquals('valid.jpg', $crawler->filter('span.file-name > a')->text());
116
117        $attach_link = $crawler->filter('span.file-name > a')->attr('href');
118        preg_match('#download/attachment/([0-9]+)/valid.jpg#', $attach_link, $match);
119        $attach_id = $match[1];
120
121        // Submit post
122        $form = $crawler->selectButton($this->lang('SUBMIT'))->form([
123            'message'        => 'This is a test',
124        ]);
125        $crawler = self::submit($form);
126
127        $this->assertStringContainsString('This is a test', $crawler->text());
128        $this->assertEquals('valid.jpg', $crawler->filter('img.postimage')->attr('alt'));
129
130        // Navigate to ucp attachments for user
131        $crawler = self::request('GET', 'ucp.php?i=ucp_attachments&mode=attachments&sid=' . $this->sid);
132        $this->assertEquals(1, $crawler->filter('.attachment-filename')->count());
133
134        $attachment_filename = $crawler->filter('.attachment-filename');
135        $this->assertEquals('valid.jpg', $attachment_filename->attr('title'));
136        $this->assertStringContainsString('app.php/download/attachment/' . $attach_id . '/valid.jpg', $attachment_filename->attr('href'));
137        $this->assertFalse($crawler->filter('[name="attachment[' . $attach_id . ']"]')->getNode(0)->hasAttribute('disabled'));
138    }
139
140    public function test_ucp_delete_expired_attachment()
141    {
142        $this->login('ucp-file-test');
143        $this->add_lang(['common', 'posting']);
144
145        $this->set_flood_interval(0);
146
147        $crawler = $this->upload_file('valid.jpg', 'image/jpeg');
148
149        // Ensure there was no error message rendered
150        $this->assertStringNotContainsString('<h2>' . $this->lang('INFORMATION') . '</h2>', $this->get_content());
151
152        // Also the file name should be in the first row of the files table
153        $this->assertEquals('valid.jpg', $crawler->filter('span.file-name > a')->text());
154
155        $attach_link = $crawler->filter('span.file-name > a')->attr('href');
156        preg_match('#download/attachment/([0-9]+)/valid.jpg#', $attach_link, $match);
157        $attach_id = $match[1];
158
159        // Submit post
160        $form = $crawler->selectButton($this->lang('SUBMIT'))->form([
161            'message'        => 'This is a test',
162        ]);
163        $crawler = self::submit($form);
164        $post_url = $crawler->getUri();
165        $post_id = $this->get_parameter_from_link($post_url, 'p');
166
167        $this->assertStringContainsString('This is a test', $crawler->text());
168        $this->assertEquals('valid.jpg', $crawler->filter('img.postimage')->attr('alt'));
169        $this->set_flood_interval(15);
170
171        // Navigate to ucp attachments for user
172        $crawler = self::request('GET', 'ucp.php?i=ucp_attachments&mode=attachments&sid=' . $this->sid);
173        $crawler->filter('.attachment-filename')->each(function ($node, $i) use ($attach_id, &$attachment_node)
174        {
175            if (strpos($node->attr('href'), 'download/attachment/' . $attach_id . '/valid.jpg') !== false)
176            {
177                $attachment_node = $node;
178            }
179        });
180        $this->assertNotNull($attachment_node);
181
182        $this->assertEquals('valid.jpg', $attachment_node->attr('title'));
183        $this->assertStringContainsString('download/attachment/' . $attach_id . '/valid.jpg', $attachment_node->attr('href'));
184
185        $this->logout();
186
187        // Switch to admin user
188        $this->login();
189        $this->admin_login();
190        $this->add_lang(['acp/board', 'acp/common']);
191
192        $crawler = self::request('GET', 'adm/index.php?i=acp_board&mode=post&sid=' . $this->sid);
193        $form = $crawler->selectButton($this->lang('SUBMIT'))->form([
194            'config[edit_time]'        => 1,
195            'config[delete_time]'    => 1,
196        ]);
197
198        self::submit($form);
199
200        // Update post time to at least one minute before current time
201        $sql = 'UPDATE ' . POSTS_TABLE . '
202            SET post_time = post_time - ' . 60 . '
203            WHERE post_id = ' . (int) $post_id;
204        $this->db->sql_query($sql);
205
206        // Log out and back in as test user
207        $this->logout();
208        $this->login('ucp-file-test');
209
210        // Navigate to ucp attachments for user, deleting should be disabled
211        $crawler = self::request('GET', 'ucp.php?i=ucp_attachments&mode=attachments&sid=' . $this->sid);
212        $crawler->filter('.attachment-filename')->each(function ($node, $i) use ($attach_id, &$attachment_node)
213        {
214            if (strpos($node->attr('href'), 'download/attachment/' . $attach_id . '/valid.jpg') !== false)
215            {
216                $attachment_node = $node;
217            }
218        });
219
220        $this->assertEquals('valid.jpg', $attachment_node->attr('title'));
221        $this->assertStringContainsString('download/attachment/' . $attach_id . '/valid.jpg', $attachment_node->attr('href'));
222        $this->assertTrue($crawler->filter('[name="attachment[' . $attach_id . ']"]')->getNode(0)->hasAttribute('disabled'));
223
224        // It should not be possible to delete the attachment
225        $crawler = self::request('POST', 'ucp.php?i=ucp_attachments&mode=attachments&sid=' . $this->sid, [
226            'delete'        => true,
227            'attachment[' . $attach_id . ']'    => $attach_id,
228        ]);
229
230        $this->assertNotContainsLang('DELETE_ATTACHMENT_CONFIRM', $crawler->text());
231
232        $crawler->filter('.attachment-filename')->each(function ($node, $i) use ($attach_id, &$attachment_node)
233        {
234            if (strpos($node->attr('href'), 'download/attachment/' . $attach_id . '/valid.jpg') !== false)
235            {
236                $attachment_node = $node;
237            }
238        });
239        $this->assertEquals('valid.jpg', $attachment_node->attr('title'));
240        $this->assertStringContainsString('download/attachment/' . $attach_id . '/valid.jpg', $attachment_node->attr('href'));
241        $this->assertTrue($crawler->filter('[name="attachment[' . $attach_id . ']"]')->getNode(0)->hasAttribute('disabled'));
242
243        $this->logout();
244
245        // Switch to admin user
246        $this->login();
247        $this->admin_login();
248        $this->add_lang(['acp/board', 'acp/common']);
249
250        $crawler = self::request('GET', 'adm/index.php?i=acp_board&mode=post&sid=' . $this->sid);
251        $form = $crawler->selectButton($this->lang('SUBMIT'))->form([
252            'config[edit_time]'        => 0,
253            'config[delete_time]'    => 0,
254        ]);
255
256        self::submit($form);
257
258        // Update post time to original one
259        $sql = 'UPDATE ' . POSTS_TABLE . '
260            SET post_time = post_time + ' . 60 . '
261            WHERE post_id = ' . (int) $post_id;
262        $this->db->sql_query($sql);
263    }
264
265    public function test_pm_attachment()
266    {
267        $this->set_flood_interval(0);
268        // Switch to admin user
269        $this->login();
270        $this->admin_login();
271        $this->add_lang(['common', 'acp/attachments', 'acp/board', 'acp/common']);
272
273        $crawler = self::request('GET', 'adm/index.php?i=acp_attachments&mode=attach&sid=' . $this->sid);
274        $form = $crawler->selectButton($this->lang('SUBMIT'))->form([
275            'config[allow_pm_attach]'        => 1,
276        ]);
277        self::submit($form);
278
279        $crawler = self::request('GET', 'adm/index.php?i=acp_board&mode=message&sid=' . $this->sid);
280        $form = $crawler->selectButton($this->lang('SUBMIT'))->form([
281            'config[pm_edit_time]'            => 60,
282        ]);
283        self::submit($form);
284
285        $crawler = self::request('GET', 'adm/index.php?i=acp_attachments&mode=ext_groups&action=edit&g=1&sid=' . $this->sid);
286        $form = $crawler->selectButton($this->lang('SUBMIT'))->form([
287            'allow_in_pm'        => 1,
288        ]);
289        self::submit($form);
290
291        $this->logout();
292        $this->login('ucp-file-test');
293        $this->add_lang(['ucp']);
294        $crawler = $this->upload_file_pm('valid.jpg', 'image/jpeg');
295
296        $attach_link = $crawler->filter('span.file-name > a')->attr('href');
297        preg_match('#download/attachment/([0-9]+)/valid.jpg#', $attach_link, $match);
298        $attach_id = $match[1];
299
300        $form = $crawler->selectButton($this->lang('ADD'))->form([
301            'username_list'    => 'admin'
302        ]);
303        $crawler = self::submit($form);
304
305        $form = $crawler->selectButton($this->lang('SUBMIT'))->form([
306            'subject'        => 'Test PM',
307            'message'        => 'This is a test',
308        ]);
309        $crawler = self::submit($form);
310
311        $this->assertContainsLang('MESSAGE_STORED', $crawler->text());
312        $refresh_data = explode(';', $crawler->filterXpath("//meta[@http-equiv='refresh']")->attr('content'));
313        $pm_url = trim($refresh_data[1]);
314
315        $pm_id = $this->get_parameter_from_link($pm_url, 'p');
316
317        // Navigate to ucp attachments for user
318        $crawler = self::request('GET', 'ucp.php?i=ucp_attachments&mode=attachments&sid=' . $this->sid);
319        $crawler->filter('.attachment-filename')->each(function ($node, $i) use ($attach_id, &$attachment_node)
320        {
321            if (strpos($node->attr('href'), 'download/attachment/' . $attach_id . '/valid.jpg') !== false)
322            {
323                $attachment_node = $node;
324            }
325        });
326        $this->assertNotNull($attachment_node);
327
328        $this->assertEquals('valid.jpg', $attachment_node->attr('title'));
329        $this->assertStringContainsString('download/attachment/' . $attach_id . '/valid.jpg', $attachment_node->attr('href'));
330        $this->assertFalse($crawler->filter('[name="attachment[' . $attach_id . ']"]')->getNode(0)->hasAttribute('disabled'));
331
332        // Update message time to 60 minutes later
333        $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
334            SET message_time = message_time - ' . 60 * 60 . '
335            WHERE msg_id = ' . (int) $pm_id;
336        $this->db->sql_query($sql);
337
338        $crawler = self::request('GET', 'ucp.php?i=ucp_attachments&mode=attachments&sid=' . $this->sid);
339        $crawler->filter('.attachment-filename')->each(function ($node, $i) use ($attach_id, &$attachment_node)
340        {
341            if (strpos($node->attr('href'), 'download/attachment/' . $attach_id . '/valid.jpg') !== false)
342            {
343                $attachment_node = $node;
344            }
345        });
346        $this->assertNotNull($attachment_node);
347
348        $this->assertEquals('valid.jpg', $attachment_node->attr('title'));
349        $this->assertStringContainsString('download/attachment/' . $attach_id . '/valid.jpg', $attachment_node->attr('href'));
350        $this->assertTrue($crawler->filter('[name="attachment[' . $attach_id . ']"]')->getNode(0)->hasAttribute('disabled'));
351
352        $this->set_flood_interval(15);
353
354        // Switch to admin user and disable extra settings again
355        $this->logout();
356        $this->login();
357        $this->admin_login();
358        $this->add_lang(['common', 'acp/attachments', 'acp/board', 'acp/common']);
359
360        $crawler = self::request('GET', 'adm/index.php?i=acp_attachments&mode=attach&sid=' . $this->sid);
361        $form = $crawler->selectButton($this->lang('SUBMIT'))->form([
362            'config[allow_pm_attach]'        => 0,
363        ]);
364        self::submit($form);
365
366        $crawler = self::request('GET', 'adm/index.php?i=acp_board&mode=message&sid=' . $this->sid);
367        $form = $crawler->selectButton($this->lang('SUBMIT'))->form([
368            'config[pm_edit_time]'            => 0,
369        ]);
370        self::submit($form);
371
372        $crawler = self::request('GET', 'adm/index.php?i=acp_attachments&mode=ext_groups&action=edit&g=1&sid=' . $this->sid);
373        $form = $crawler->selectButton($this->lang('SUBMIT'))->form();
374        $form['allow_in_pm']->untick();
375        self::submit($form);
376    }
377}