Code jest otwarto-źródłową wklejką z funkcjonalnościami takimi jak drag 'n drop i obsługa więcej niż jednego pliku. Zachowuje prywatność wklejek, każdy plik jest szyfrowany przy użyciu algorytmu AES-256-CBC i jedyną osobą, która zna klucz, jesteś ty i każdy, komu wyślesz linka.
`;
181 |
182 | return overlay;
183 | },
184 |
185 | appendOverlay() {
186 | const overlayWrapper = document.querySelector(this.OVERLAY_WRAPPER_QUERY);
187 | this.overlay = this.getOverlayElement();
188 |
189 | overlayWrapper.appendChild(this.overlay);
190 | },
191 |
192 | showOverlay() {
193 | this.overlay.classList.add('drop-overlay__active');
194 | },
195 |
196 | hideOverlay() {
197 | this.overlay.classList.remove('drop-overlay__active');
198 | },
199 | };
200 |
201 | DragAndDrop.init();
202 | NewFormButton.init();
203 |
--------------------------------------------------------------------------------
/tests/Slim/DecoratingCallableResolverTest.php:
--------------------------------------------------------------------------------
1 | getContainerWithClassMethod();
17 | /** @var AbstractController $controller */
18 | $controller = $container->get('controller');
19 |
20 | $controllerDecorator = $this->createMock(ControllerDecorator::class);
21 | $controllerDecorator
22 | ->expects($this->once())
23 | ->method('decorate');
24 |
25 | $decoratingCallableResolver = new DecoratingCallableResolver(
26 | $container,
27 | $controllerDecorator
28 | );
29 |
30 | $resolved = $decoratingCallableResolver->resolve('controller:home');
31 | $this->assertEquals($controller, $resolved[0]);
32 | $this->assertEquals('home', $resolved[1]);
33 | }
34 |
35 | public function testResolveWithInvokableChildOfAbstractControllerInContainer()
36 | {
37 | $container = $this->getContainerWithInvokableClass();
38 | /** @var AbstractController $controller */
39 | $controller = $container->get('controller');
40 |
41 | $controllerDecorator = $this->createMock(ControllerDecorator::class);
42 | $controllerDecorator
43 | ->expects($this->once())
44 | ->method('decorate');
45 |
46 | $decoratingCallableResolver = new DecoratingCallableResolver(
47 | $container,
48 | $controllerDecorator
49 | );
50 |
51 | $resolved = $decoratingCallableResolver->resolve('controller');
52 | $this->assertEquals($controller, $resolved[0]);
53 | $this->assertEquals('__invoke', $resolved[1]);
54 | }
55 |
56 | public function testResolveWithChildOfAbstractControllerWithMethod()
57 | {
58 | $controller = new class() extends AbstractController {
59 | public function home(
60 | ServerRequestInterface $request,
61 | ResponseInterface $response
62 | ) {
63 | return $response;
64 | }
65 | };
66 |
67 | $controllerDecorator = $this->createMock(ControllerDecorator::class);
68 | $controllerDecorator
69 | ->expects($this->once())
70 | ->method('decorate');
71 |
72 | $decoratingCallableResolver = new DecoratingCallableResolver(
73 | $this->createMock(ContainerInterface::class),
74 | $controllerDecorator
75 | );
76 |
77 | $resolved = $decoratingCallableResolver->resolve([$controller, 'home']);
78 | $this->assertEquals($controller, $resolved[0]);
79 | $this->assertEquals('home', $resolved[1]);
80 | }
81 |
82 | public function testResolveWithInvokableChildOfAbstractController()
83 | {
84 | $controller = new class() extends AbstractController {
85 | public function __invoke(
86 | ServerRequestInterface $request,
87 | ResponseInterface $response
88 | ) {
89 | return $response;
90 | }
91 | };
92 |
93 | $controllerDecorator = $this->createMock(ControllerDecorator::class);
94 | $controllerDecorator
95 | ->expects($this->once())
96 | ->method('decorate');
97 |
98 | $decoratingCallableResolver = new DecoratingCallableResolver(
99 | $this->createMock(ContainerInterface::class),
100 | $controllerDecorator
101 | );
102 |
103 | $resolved = $decoratingCallableResolver->resolve($controller);
104 | $this->assertEquals($controller, $resolved);
105 | }
106 |
107 | public function testResolveWithNotChildOfAbstractController()
108 | {
109 | $controller = new class() {
110 | public function home(
111 | ServerRequestInterface $request,
112 | ResponseInterface $response
113 | ) {
114 | return $response;
115 | }
116 | };
117 |
118 | $controllerDecorator = $this->createMock(ControllerDecorator::class);
119 | $controllerDecorator
120 | ->expects($this->never())
121 | ->method('decorate');
122 |
123 | $decoratingCallableResolver = new DecoratingCallableResolver(
124 | $this->createMock(ContainerInterface::class),
125 | $controllerDecorator
126 | );
127 |
128 | $resolved = $decoratingCallableResolver->resolve([$controller, 'home']);
129 | $this->assertEquals($controller, $resolved[0]);
130 | $this->assertEquals('home', $resolved[1]);
131 | }
132 |
133 | private function getContainerWithClassMethod()
134 | {
135 | return new class() implements ContainerInterface {
136 | public function get($id)
137 | {
138 | return new class() extends AbstractController {
139 | public function home(
140 | ServerRequestInterface $request,
141 | ResponseInterface $response
142 | ) {
143 | return $response;
144 | }
145 | };
146 | }
147 |
148 | public function has($id)
149 | {
150 | return 'controller' == $id;
151 | }
152 | };
153 | }
154 |
155 | public function getContainerWithInvokableClass()
156 | {
157 | return new class() implements ContainerInterface {
158 | public function get($id)
159 | {
160 | return new class() extends AbstractController {
161 | public function __invoke(
162 | ServerRequestInterface $request,
163 | ResponseInterface $response
164 | ) {
165 | return $response;
166 | }
167 | };
168 | }
169 |
170 | public function has($id)
171 | {
172 | return 'controller' == $id;
173 | }
174 | };
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/src/AppKernel.php:
--------------------------------------------------------------------------------
1 | slim = new App();
47 |
48 | $this->setupConfig();
49 | $this->setupServices();
50 | $this->setupRoutes();
51 |
52 | // Middlewares
53 | $this->slim->add(new SymfonySessionMiddleware($this->slim->getContainer()['session']));
54 | }
55 |
56 | /**
57 | * Sets up config in container.
58 | */
59 | private function setupConfig(): void
60 | {
61 | $config = Yaml::parse(file_get_contents(__DIR__.'/config.yml'));
62 |
63 | $this->slim->getContainer()['config'] = $config;
64 | }
65 |
66 | /**
67 | * Sets up dependencies in container.
68 | */
69 | private function setupServices(): void
70 | {
71 | $container = $this->slim->getContainer();
72 | $container['settings']['displayErrorDetails'] = $container['config']['debug'];
73 | $container['logger'] = function () {
74 | return new Logger('application', [
75 | new StreamHandler(__DIR__.'/../logs/logs.log'),
76 | ]);
77 | };
78 | $container['foundHandler'] = function () {
79 | return new RequestResponseArgs();
80 | };
81 | $container['notFoundHandler'] = function (Container $container) {
82 | return [$container[ErrorController::class], 'notFound'];
83 | };
84 | $container['errorHandler'] = function (Container $container) {
85 | // Show pretty error page on production and Slim debug info on development.
86 | $next = $container['config']['debug'] ?
87 | new Error($container['config']['debug']) :
88 | [$container[ErrorController::class], 'error'];
89 |
90 | return new Slim\Handler\LoggingErrorHandler(
91 | $container->get('logger'),
92 | $next
93 | );
94 | };
95 | $container['phpErrorHandler'] = function (Container $container) {
96 | // Show pretty error page on production and Slim debug info on development.
97 | $next = $container['config']['debug'] ?
98 | new PhpError($container['config']['debug']) :
99 | [$container[ErrorController::class], 'error'];
100 |
101 | return new Slim\Handler\LoggingErrorHandler(
102 | $container->get('logger'),
103 | $next
104 | );
105 | };
106 | $container['translator'] = function (Container $container) {
107 | $translator = new Translator($container['config']['locale']);
108 | $translator->setFallbackLocales(['en']);
109 |
110 | $translator->addLoader('php', new PhpFileLoader());
111 | $translator->addResource('php', __DIR__.'/../resources/translations/messages.php', 'en');
112 | $translator->addResource('php', __DIR__.'/../resources/translations/messages.pl.php', 'pl');
113 |
114 | return $translator;
115 | };
116 | $container['twig'] = function (Container $container) {
117 | $twig = new Twig(__DIR__.'/../resources/views/', [
118 | 'debug' => $container['config']['debug'],
119 | ]);
120 | $twig->addExtension(new TwigExtension($container['router'], $container['config']['base_url']));
121 | $twig->addExtension(new SymfonyValidatorExtension());
122 | $twig->addExtension(new TransExtension($container['translator']));
123 |
124 | return $twig;
125 | };
126 | $container['session'] = function () {
127 | return new Session();
128 | };
129 | $container['controllerDecorator'] = function (Container $container) {
130 | return new ControllerDecorator(
131 | $container['twig'],
132 | $container['router'],
133 | $container['session']
134 | );
135 | };
136 | $container['callableResolver'] = function (Container $container) {
137 | return new DecoratingCallableResolver(
138 | $container,
139 | $container['controllerDecorator']
140 | );
141 | };
142 | $container['dbal'] = function (Container $container) {
143 | $config = new Configuration();
144 |
145 | return DriverManager::getConnection([
146 | 'driver' => 'pdo_mysql',
147 | 'host' => $container['config']['database']['host'],
148 | 'port' => $container['config']['database']['port'],
149 | 'dbname' => $container['config']['database']['name'],
150 | 'user' => $container['config']['database']['user'],
151 | 'password' => $container['config']['database']['password'],
152 | 'charset' => $container['config']['database']['charset'],
153 | ], $config);
154 | };
155 |
156 | // Controllers
157 | $container[PasteController::class] = function (Container $container) {
158 | $pasteRepository = new DbalPasteRepository($container['dbal'], new DbalPasteMapper());
159 |
160 | return new PasteController($pasteRepository, new AES256Crypter());
161 | };
162 | $container[ErrorController::class] = function (Container $container) {
163 | /** @var ControllerDecorator $controllerDecorator */
164 | $controllerDecorator = $container['controllerDecorator'];
165 |
166 | $errorController = new ErrorController(
167 | new HttpsXkcdRepository()
168 | );
169 | $controllerDecorator->decorate($errorController);
170 |
171 | return $errorController;
172 | };
173 | }
174 |
175 | /**
176 | * Sets up routes.
177 | */
178 | private function setupRoutes(): void
179 | {
180 | $routes = Yaml::parse(file_get_contents(__DIR__.'/routes.yml'));
181 |
182 | foreach ($routes as $routeName => $route) {
183 | $this->slim->map([$route['method']], $route['path'], $route['controller'])->setName($routeName);
184 | }
185 | }
186 |
187 | /**
188 | * Sends response to the client.
189 | */
190 | public function handle(): void
191 | {
192 | $this->slim->run();
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/tests/Infrastructure/AES256CrypterTest.php:
--------------------------------------------------------------------------------
1 | createMock(Paste\Id::class),
21 | 'title',
22 | new \DateTime()
23 | );
24 | $paste->addFile(new File('', $content));
25 |
26 | $encryptedPaste = clone $paste;
27 |
28 | $crypter->encrypt($encryptedPaste, $key);
29 |
30 | // FIXME: Why the fuck does this not pass
31 | // $this->assertNotEquals(
32 | // $paste->getFiles()[0]->getContent(),
33 | // $encryptedPaste->getFiles()[0]->getContent()
34 | // );
35 |
36 | $crypter->decrypt($encryptedPaste, $key);
37 |
38 | $this->assertEquals(
39 | $paste->getFiles()[0]->getContent(),
40 | $encryptedPaste->getFiles()[0]->getContent()
41 | );
42 | }
43 |
44 | public function crypterContentProvider()
45 | {
46 | return [
47 | ['Foobar'],
48 | [<<<'CONTENT'
49 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis a facilisis est. Donec bibendum metus ac ex eleifend, eu maximus dolor imperdiet. Donec eget metus magna. Duis et metus erat. Aliquam posuere nisi a orci rutrum, sed molestie dui gravida. Aliquam erat volutpat. Nam a quam in nulla efficitur pulvinar. Phasellus molestie, mauris feugiat volutpat rutrum, erat odio viverra magna, vitae bibendum nisi lectus id sapien.
50 |
51 | In blandit urna nibh. Aenean dictum nulla non dapibus aliquam. In non pulvinar urna. Cras eget venenatis massa. Cras rhoncus nisi at ante egestas suscipit. Suspendisse potenti. Suspendisse potenti. Sed vel magna quam.
52 |
53 | Sed eu est gravida, suscipit ex a, euismod nibh. In nunc magna, consequat vitae orci et, rutrum malesuada turpis. Cras scelerisque at est ut congue. Cras quis aliquet dolor, et pellentesque nisi. Sed venenatis dapibus ornare. Cras non placerat velit, non sollicitudin justo. Aenean eleifend et dui quis efficitur. In hac habitasse platea dictumst. Integer pulvinar, sapien a facilisis laoreet, tellus ipsum gravida tortor, eu semper libero neque at tellus. Aliquam eleifend nibh vel erat lacinia placerat. Duis quis felis elit. Duis sollicitudin sagittis risus, et consequat enim dictum non. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur dui mauris, tincidunt non purus molestie, porta semper mi. Donec placerat tempus nibh, vehicula vulputate turpis commodo eget.
54 |
55 | Vivamus finibus gravida lorem, eu sagittis orci tempor in. Quisque vestibulum, arcu quis mollis consectetur, risus mi placerat dolor, at sagittis erat est sit amet lacus. Nulla facilisi. Morbi a ante purus. Suspendisse ultricies dignissim diam, vel egestas nibh eleifend vel. Nulla tempus commodo nunc, at euismod risus pulvinar eget. Cras faucibus nisl porta cursus condimentum.
56 |
57 | Nullam sed sodales lectus, vitae porta purus. Phasellus porttitor accumsan diam eget feugiat. Duis sit amet ultricies dui, ut tincidunt ante. Phasellus elit arcu, ullamcorper sed lorem eget, blandit tempus quam. Etiam aliquet mollis nisl, et fringilla magna auctor sit amet. Phasellus iaculis lectus vitae lectus volutpat interdum. Sed condimentum pulvinar tempus. Curabitur eu sagittis neque, ac pharetra neque.
58 |
59 | Proin sed accumsan velit, vel dignissim erat. Donec pretium tincidunt metus laoreet semper. Praesent quam dui, lacinia id posuere sed, dictum id arcu. Nunc odio ligula, lacinia a condimentum at, pretium et neque. Ut rhoncus, ante et tristique finibus, magna nunc ornare erat, id ultricies augue lacus eget massa. Morbi massa tortor, tincidunt sit amet erat quis, varius iaculis nisi. Proin lobortis odio eu nisl accumsan posuere. Nam enim enim, sollicitudin vitae odio non, bibendum eleifend erat. Phasellus ligula quam, luctus sagittis lacinia eget, mollis at enim. Nam pulvinar quam est, vitae bibendum odio iaculis pulvinar. Vivamus id justo nibh. Curabitur elementum justo ac venenatis auctor. Vivamus rutrum, nunc nec dapibus bibendum, orci nibh efficitur nulla, ac posuere leo elit quis risus.
60 |
61 | Nullam vulputate tortor nec erat condimentum volutpat. Nulla a congue erat, ut bibendum neque. Etiam sem est, porta vitae faucibus quis, tempor nec ligula. Phasellus semper a massa quis lacinia. In mattis ullamcorper lectus vel placerat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Phasellus maximus porta aliquam. Aliquam aliquam molestie posuere. Maecenas eu dolor nec felis molestie pulvinar.
62 |
63 | Vivamus mi ex, finibus vel molestie eu, cursus at velit. Morbi consequat turpis lectus, tincidunt hendrerit odio viverra vitae. Donec metus ante, interdum a ullamcorper vitae, molestie sed urna. Proin et viverra neque, vitae faucibus urna. Cras accumsan ac massa eu fringilla. Donec efficitur rutrum diam a tempus. Phasellus at dictum tortor. Duis tempus orci lacus, vehicula finibus tortor cursus a. Nullam mollis tempus tincidunt. Integer fringilla sem in metus dictum sollicitudin.
64 |
65 | Nam consectetur euismod mi. Mauris mi leo, lacinia ac quam nec, pretium volutpat turpis. Cras suscipit ullamcorper tincidunt. Curabitur erat elit, tincidunt ut fermentum eget, facilisis ut lorem. Curabitur egestas commodo erat, eget volutpat arcu tincidunt accumsan. Sed lectus erat, finibus vitae vehicula a, posuere eu nisl. Morbi eget ornare massa. Duis vel egestas risus. Maecenas blandit augue quis libero semper cursus. In vitae diam maximus, faucibus risus id, dignissim nisl. Maecenas et erat vel enim efficitur fringilla ut eu augue. Nam viverra, tellus nec sollicitudin rhoncus, ex lacus bibendum justo, et tincidunt ex libero sed eros. Donec tortor diam, blandit sed lobortis ut, blandit sed sapien.
66 |
67 | Phasellus blandit cursus lobortis. Vivamus ac cursus lacus. Proin nec felis et lacus tincidunt commodo vel sit amet mauris. Morbi accumsan bibendum mauris. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Fusce odio lacus, pharetra quis augue a, rutrum mollis nisi. In id euismod metus. Morbi sit amet vestibulum lectus. Vivamus quis mi in elit aliquet convallis.
68 |
69 | Suspendisse eget volutpat felis. Praesent vel nisl vitae ipsum vulputate blandit. Vivamus ornare sit amet arcu in hendrerit. Nunc vulputate purus sit amet nisi imperdiet, non laoreet sem tempus. Aenean eu quam tristique, elementum orci a, placerat magna. Maecenas et dictum massa. Vestibulum viverra, purus pharetra dapibus euismod, libero tortor lobortis sem, non sagittis urna tortor ac nisi. In ligula nisl, faucibus ut nulla vitae, pulvinar ullamcorper mi. Ut vel risus diam. Nulla vel placerat elit.
70 |
71 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin auctor, velit eget varius finibus, ligula massa dignissim nisl, eu ornare nunc sem hendrerit arcu. Proin venenatis interdum neque, id fermentum justo aliquam at. Vivamus nec nisl viverra, tempor mi ut, rhoncus libero. Aliquam sed facilisis urna. Quisque vel odio id metus porta vulputate non in libero. Etiam non suscipit ligula.
72 |
73 | Suspendisse vehicula turpis semper risus dictum, eget tempus ligula fermentum. Aliquam erat volutpat. Suspendisse sed massa quis velit egestas pretium. Vestibulum rutrum, ligula at accumsan hendrerit, quam nunc fermentum magna, vitae vestibulum diam nulla non nulla. Suspendisse et dui velit. Fusce risus felis, mollis at nulla ac, consectetur venenatis diam. Sed lobortis lorem id vestibulum malesuada.
74 |
75 | Aliquam neque urna, interdum vitae tortor nec, dictum sodales risus. Cras risus magna, ullamcorper vitae libero non, pellentesque bibendum nisl. Vivamus aliquet nulla in augue consequat, at porta augue euismod. Curabitur finibus tincidunt bibendum. Suspendisse potenti. In hac habitasse platea dictumst. Suspendisse quam enim, dignissim eget dolor eu, consequat lobortis est.
76 |
77 | Etiam rutrum arcu ac dapibus egestas. Vestibulum a mi vel purus faucibus tempor. Maecenas varius elit vel elementum bibendum. Ut eget lectus eu neque dictum vehicula eget sit amet magna. Proin at erat tincidunt, lacinia velit a, auctor mi. Mauris a sem eu eros mattis suscipit porta nec odio. Nam at ligula pharetra, elementum magna vitae, fringilla sapien. Nunc consequat enim in massa consectetur efficitur. Phasellus scelerisque eros at dui suscipit, nec bibendum lectus congue. Fusce bibendum enim at diam posuere, quis laoreet dolor pulvinar. Quisque enim enim, placerat auctor dui non, scelerisque auctor turpis. Quisque iaculis felis vitae mauris dictum, eget lobortis nisl tincidunt. Nulla dapibus felis quis eros euismod porttitor.
78 |
79 | Donec gravida augue in ipsum convallis viverra. Nunc suscipit nunc et diam euismod aliquam viverra non lacus. Aliquam erat volutpat. Mauris semper justo a tincidunt dapibus. Nam eget eleifend nisl. Nulla feugiat, risus vel tempus eleifend, elit nisi convallis est, sit amet feugiat dui lectus sit amet dolor. Nunc eget eros erat.
80 |
81 | Suspendisse potenti. Duis consequat dolor facilisis arcu facilisis, sed maximus erat pulvinar. Nullam faucibus sem nec justo efficitur fringilla. Ut rhoncus vitae metus et blandit. Phasellus tempor mauris sit amet laoreet elementum. Vivamus eu arcu aliquam, aliquet dolor a, aliquam libero. Donec nec lorem velit. Nullam hendrerit turpis et mauris rhoncus hendrerit sit amet at dolor. Curabitur et urna imperdiet, laoreet libero at, tristique dolor.
82 |
83 | Quisque aliquam dignissim cursus. Sed eget tincidunt justo. Praesent pharetra facilisis sem in ullamcorper. Praesent mollis orci in lorem consequat convallis. Nulla ultrices sit amet lorem vitae fringilla. Phasellus dignissim auctor enim, vitae iaculis justo pretium non. Donec tempor diam commodo metus vulputate, ac volutpat purus efficitur. Etiam sit amet orci ut elit lobortis semper vel vel tortor. Phasellus molestie, nunc id euismod cursus, arcu turpis varius enim, eu tincidunt nisl massa et massa. Maecenas pulvinar odio dui, ut laoreet nisl porta non.
84 |
85 | Vivamus lobortis, odio vitae fringilla posuere, odio purus pharetra magna, ornare dapibus ipsum lectus sit amet ligula. Sed placerat urna non orci volutpat pellentesque. Aenean non tempus orci. Mauris sodales laoreet risus, vitae aliquet elit bibendum pellentesque. Sed ullamcorper laoreet venenatis. Fusce tortor dolor, egestas sit amet ullamcorper ut, malesuada in est. Proin lorem nibh, interdum et diam vitae, elementum feugiat lectus. Vivamus venenatis augue id risus mattis mollis. Mauris sit amet quam felis. Suspendisse potenti. Etiam euismod quam sit amet sapien ornare, a imperdiet massa eleifend. Nulla laoreet libero massa, eget vestibulum justo egestas eu. Nulla facilisi. Nam eu lorem vel orci maximus elementum sit amet auctor massa. Donec ut laoreet libero. Sed a velit ipsum.
86 |
87 | Nam urna mauris, elementum sit amet sapien eu, euismod pharetra dolor. Etiam sed sem sapien. Mauris eu scelerisque orci. Curabitur lobortis magna a ligula malesuada, eu aliquam justo euismod. Phasellus vel blandit est. Morbi pretium, nisi non condimentum gravida, orci elit mollis neque, in condimentum leo quam at nunc. Nulla aliquam pretium mauris eu condimentum. Nulla convallis sed dui sed facilisis. Morbi at metus viverra, consequat erat quis, euismod mi. Praesent in bibendum ante. In in purus tellus. Nunc est enim, volutpat sed mauris sit amet, cursus molestie urna. Donec dictum nisi id massa porttitor scelerisque sed.
88 | CONTENT
89 | ],
90 | ];
91 | }
92 | }
93 |
--------------------------------------------------------------------------------