4 |
5 | # GOG Games
6 | A continuitation of Good Old Downloads' [GOG Games](https://github.com/Good-Old-Downloads/gg) project. The goal is to create a copy of the original site by keeping games updated, voting, automated uploading, etc.
7 |
8 | # Authors & Credits
9 | * MachineGunnur
10 | * Lindre - thanks for help friend with english :)
11 | * GOD Team - thanks for giving us site source code on github
12 |
13 | # License
14 | This project is licensed under the GNU General Public License v3.0. See [LICENSE](LICENSE) for details or this [TL;DR](https://tldrlegal.com/license/gnu-general-public-license-v3-(gpl-3)).
15 |
--------------------------------------------------------------------------------
/web/static/img/hoster_logos/gofile.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/web/static/img/hoster_logos/mirrored.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/web/static/img/hoster_logos/letsupload.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/web/static/css/font-awesome/fa-brands.scss:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.6 by @fontawesome - http://fontawesome.com
3 | * License - http://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @import 'variables';
6 |
7 | @font-face {
8 | font-family: 'Font Awesome 5 Brands';
9 | font-style: normal;
10 | font-weight: normal;
11 | src: url('#{$fa-font-path}/fa-brands-400.eot');
12 | src: url('#{$fa-font-path}/fa-brands-400.eot?#iefix') format('embedded-opentype'),
13 | url('#{$fa-font-path}/fa-brands-400.woff2') format('woff2'),
14 | url('#{$fa-font-path}/fa-brands-400.woff') format('woff'),
15 | url('#{$fa-font-path}/fa-brands-400.ttf') format('truetype'),
16 | url('#{$fa-font-path}/fa-brands-400.svg#fontawesome') format('svg');
17 | }
18 |
19 | .fab {
20 | font-family: 'Font Awesome 5 Brands';
21 | }
22 |
--------------------------------------------------------------------------------
/web/static/css/font-awesome/fa-solid.scss:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.6 by @fontawesome - http://fontawesome.com
3 | * License - http://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @import 'variables';
6 |
7 | @font-face {
8 | font-family: 'Font Awesome 5 Free';
9 | font-style: normal;
10 | font-weight: 900;
11 | src: url('#{$fa-font-path}/fa-solid-900.eot');
12 | src: url('#{$fa-font-path}/fa-solid-900.eot?#iefix') format('embedded-opentype'),
13 | url('#{$fa-font-path}/fa-solid-900.woff2') format('woff2'),
14 | url('#{$fa-font-path}/fa-solid-900.woff') format('woff'),
15 | url('#{$fa-font-path}/fa-solid-900.ttf') format('truetype'),
16 | url('#{$fa-font-path}/fa-solid-900.svg#fontawesome') format('svg');
17 | }
18 |
19 | .fa,
20 | .fas {
21 | font-family: 'Font Awesome 5 Free';
22 | font-weight: 900;
23 | }
24 |
--------------------------------------------------------------------------------
/web/static/css/font-awesome/fa-regular.scss:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.6 by @fontawesome - http://fontawesome.com
3 | * License - http://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @import 'variables';
6 |
7 | @font-face {
8 | font-family: 'Font Awesome 5 Free';
9 | font-style: normal;
10 | font-weight: 400;
11 | src: url('#{$fa-font-path}/fa-regular-400.eot');
12 | src: url('#{$fa-font-path}/fa-regular-400.eot?#iefix') format('embedded-opentype'),
13 | url('#{$fa-font-path}/fa-regular-400.woff2') format('woff2'),
14 | url('#{$fa-font-path}/fa-regular-400.woff') format('woff'),
15 | url('#{$fa-font-path}/fa-regular-400.ttf') format('truetype'),
16 | url('#{$fa-font-path}/fa-regular-400.svg#fontawesome') format('svg');
17 | }
18 |
19 | .far {
20 | font-family: 'Font Awesome 5 Free';
21 | font-weight: 400;
22 | }
23 |
--------------------------------------------------------------------------------
/web/static/css/font-awesome/_rotated-flipped.scss:
--------------------------------------------------------------------------------
1 | // Rotated & Flipped Icons
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); }
5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); }
6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); }
7 |
8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); }
9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); }
10 | .#{$fa-css-prefix}-flip-horizontal.#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(-1, -1, 2); }
11 |
12 | // Hook for IE8-9
13 | // -------------------------
14 |
15 | :root {
16 | .#{$fa-css-prefix}-rotate-90,
17 | .#{$fa-css-prefix}-rotate-180,
18 | .#{$fa-css-prefix}-rotate-270,
19 | .#{$fa-css-prefix}-flip-horizontal,
20 | .#{$fa-css-prefix}-flip-vertical {
21 | filter: none;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/web/static/img/hoster_logos/userscloud.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
17 |
--------------------------------------------------------------------------------
/web/static/img/hoster_logos/clicknupload.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/templates/faq.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 | {% extends 'main.twig' %}
19 |
20 | {% block title %}{{ 'FAQ'|trans }}{% endblock title %}
21 |
22 | {% block content %}
23 |
24 | {% include 'imports/faq.twig' %}
25 |
26 | {% endblock content %}
27 |
28 | {% block scripts %}
29 | {% endblock scripts %}
--------------------------------------------------------------------------------
/templates/donate.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 | {% extends 'main.twig' %}
19 |
20 | {% block title %}{{ 'Donate'|trans }}{% endblock title %}
21 |
22 | {% block content %}
23 |
24 | {% include 'imports/donate.twig' %}
25 |
26 | {% endblock content %}
27 |
28 | {% block scripts %}
29 | {% endblock scripts %}
--------------------------------------------------------------------------------
/web/static/img/hoster_logos/krakenfiles.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
--------------------------------------------------------------------------------
/templates/404.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 |
19 |
20 |
21 |
22 | 404 - Good Old Downloads
23 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/templates/login.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 |
19 | {% extends 'main.twig' %}
20 |
21 | {% block title %}{{ 'Login'|trans }}{% endblock title %}
22 |
23 | {% block content %}
24 |
25 |
{{ 'Login'|trans }}
26 |
31 |
32 | {% endblock content %}
33 |
34 | {% block scripts %}
35 | {% endblock scripts %}
--------------------------------------------------------------------------------
/web/static/img/hoster_logos/downloadgg.svg:
--------------------------------------------------------------------------------
1 |
26 |
--------------------------------------------------------------------------------
/config_blank.php:
--------------------------------------------------------------------------------
1 | 'ayylmaosecretloginpageyolo',
5 | "BASEDIR" => "/var/www/gg",
6 |
7 | // Shows PHP errors, disables the Twig cache, probably does other things.
8 | // Set to false in production.
9 | "DEV" => true,
10 |
11 | // GG has no user system. Set up the login name and password here.
12 | // Again, use a script to change this once in a while if you're paranoid.
13 | "USER" => [
14 | "NAME" => "supasecretlogin",
15 | "PASS" => "123",
16 |
17 | // Key used with the http API
18 | "KEY" => "123-321-1337"
19 | ],
20 |
21 | // MySQL details
22 | "DB" => [
23 | "DBHOST" => "localhost",
24 | "DBNAME" => "gg",
25 | "DBUSER" => "root",
26 | "DBPASS" => "123"
27 | ],
28 |
29 | // Memcached details
30 | "MEMCACHED" => [
31 | "SERVER" => "127.0.0.1",
32 | "PORT" => 11211
33 | ],
34 |
35 | // ElasticSearch details
36 | "ES" => [
37 | "HOSTS" => [
38 | "localhost"
39 | ]
40 | ],
41 |
42 | // reCaptcha
43 | "CAPTCHA" => [
44 | "SECRET" => "",
45 | "SITE" => "",
46 | "TYPE" => "HCAPTCHA" // Can be "RECAPTCHA" or "HCAPTCHA"
47 | ]
48 | ];
49 |
--------------------------------------------------------------------------------
/web/static/js/prepend/polyfills.js:
--------------------------------------------------------------------------------
1 | /*
2 | Polyfill for el.closest()
3 | https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
4 | */
5 | if (!Element.prototype.matches)
6 | Element.prototype.matches = Element.prototype.msMatchesSelector ||
7 | Element.prototype.webkitMatchesSelector;
8 |
9 | if (!Element.prototype.closest)
10 | Element.prototype.closest = function(s) {
11 | var el = this;
12 | if (!document.documentElement.contains(el)) return null;
13 | do {
14 | if (el.matches(s)) return el;
15 | el = el.parentElement || el.parentNode;
16 | } while (el !== null && el.nodeType === 1);
17 | return null;
18 | };
19 |
20 | /*
21 | Polyfill for el.matches()
22 | https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill
23 | */
24 | if (!Element.prototype.matches) {
25 | Element.prototype.matches =
26 | Element.prototype.matchesSelector ||
27 | Element.prototype.mozMatchesSelector ||
28 | Element.prototype.msMatchesSelector ||
29 | Element.prototype.oMatchesSelector ||
30 | Element.prototype.webkitMatchesSelector ||
31 | function(s) {
32 | var matches = (this.document || this.ownerDocument).querySelectorAll(s),
33 | i = matches.length;
34 | while (--i >= 0 && matches.item(i) !== this) {}
35 | return i > -1;
36 | };
37 | }
--------------------------------------------------------------------------------
/web/static/img/hoster_logos/pixeldrain.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/web/static/css/_variables.scss:
--------------------------------------------------------------------------------
1 | // Ripped out of Bootstrap 4
2 |
3 | $font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default;
4 | $font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default;
5 | $font-family-base: "Roboto" !default;
6 |
7 | $font-size-base: 14px !default; // Assumes the browser default, typically `16px`
8 | $font-weight-normal: 300 !default;
9 | $font-weight-base: $font-weight-normal !default;
10 | $line-height-base: 1.5 !default;
11 |
12 | $text-muted: rgba(0, 0, 0, 0.45) !default;
13 |
14 | // Body
15 | //
16 | // Settings for the `` element.
17 |
18 | $body-bg: #f9f9f9 !default;
19 | $body-color: #212121 !default;
20 |
21 |
22 | $headings-margin-bottom: 7px !default;
23 |
24 | // Paragraphs
25 | //
26 | // Style p element.
27 |
28 | $paragraph-margin-bottom: 1rem !default;
29 |
30 | // Links
31 | //
32 | // Style anchor elements.
33 |
34 | $link-color: #6a4da5 !default;
35 | $link-decoration: none !default;
36 | $link-hover-color: darken($link-color, 15%) !default;
37 | $link-hover-decoration: underline !default;
38 |
39 | // Tables
40 | //
41 | // Customizes the `.table` component with basic values, each used across all table variations.
42 |
43 | $table-cell-padding: .75rem !default;
--------------------------------------------------------------------------------
/web/static/css/font-awesome/_mixins.scss:
--------------------------------------------------------------------------------
1 | // Mixins
2 | // --------------------------
3 |
4 | @mixin fa-icon {
5 | -webkit-font-smoothing: antialiased;
6 | -moz-osx-font-smoothing: grayscale;
7 | display: inline-block;
8 | font-style: normal;
9 | font-variant: normal;
10 | font-weight: normal;
11 | line-height: 1;
12 | vertical-align: -.125em;
13 | }
14 |
15 | @mixin fa-icon-rotate($degrees, $rotation) {
16 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})";
17 | transform: rotate($degrees);
18 | }
19 |
20 | @mixin fa-icon-flip($horiz, $vert, $rotation) {
21 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)";
22 | transform: scale($horiz, $vert);
23 | }
24 |
25 |
26 | // Only display content to screen readers. A la Bootstrap 4.
27 | //
28 | // See: http://a11yproject.com/posts/how-to-hide-content/
29 |
30 | @mixin sr-only {
31 | border: 0;
32 | clip: rect(0, 0, 0, 0);
33 | height: 1px;
34 | margin: -1px;
35 | overflow: hidden;
36 | padding: 0;
37 | position: absolute;
38 | width: 1px;
39 | }
40 |
41 | // Use in conjunction with .sr-only to only display content when it's focused.
42 | //
43 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
44 | //
45 | // Credit: HTML5 Boilerplate
46 |
47 | @mixin sr-only-focusable {
48 | &:active,
49 | &:focus {
50 | clip: auto;
51 | height: auto;
52 | margin: 0;
53 | overflow: visible;
54 | position: static;
55 | width: auto;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/templates/rss.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 |
19 |
20 |
21 | GOG Games
22 | {{ base_url() }}
23 | Newly added/updated games from GOG-Games.com
24 | en-us
25 | {{ now|date(DATE_RSS) }}
26 | http://blogs.law.harvard.edu/tech/rss
27 | {% for game in games %}
28 |
29 | {{ game.title }}
30 | {{ game.last_update|date(DATE_RSS) }}
31 |
32 |
33 | {{ base_url() }}/game/{{ game.slug }}
34 | {{ game.id }} {{ game.last_update }}
35 |
36 | {% endfor %}
37 |
38 |
39 |
--------------------------------------------------------------------------------
/web/static/css/_easings.scss:
--------------------------------------------------------------------------------
1 | $linear : cubic-bezier(0.250, 0.250, 0.750, 0.750);
2 | $ease : cubic-bezier(0.250, 0.100, 0.250, 1.000);
3 | $ease-in : cubic-bezier(0.420, 0.000, 1.000, 1.000);
4 | $ease-out : cubic-bezier(0.000, 0.000, 0.580, 1.000);
5 | $ease-in-out : cubic-bezier(0.420, 0.000, 0.580, 1.000);
6 |
7 | $easeInQuad : cubic-bezier(0.550, 0.085, 0.680, 0.530);
8 | $easeInCubic : cubic-bezier(0.550, 0.055, 0.675, 0.190);
9 | $easeInQuart : cubic-bezier(0.895, 0.030, 0.685, 0.220);
10 | $easeInQuint : cubic-bezier(0.755, 0.050, 0.855, 0.060);
11 | $easeInSine : cubic-bezier(0.470, 0.000, 0.745, 0.715);
12 | $easeInExpo : cubic-bezier(0.950, 0.050, 0.795, 0.035);
13 | $easeInCirc : cubic-bezier(0.600, 0.040, 0.980, 0.335);
14 | $easeInBack : cubic-bezier(0.600, -0.280, 0.735, 0.045);
15 |
16 | $easeOutQuad : cubic-bezier(0.250, 0.460, 0.450, 0.940);
17 | $easeOutCubic : cubic-bezier(0.215, 0.610, 0.355, 1.000);
18 | $easeOutQuart : cubic-bezier(0.165, 0.840, 0.440, 1.000);
19 | $easeOutQuint : cubic-bezier(0.230, 1.000, 0.320, 1.000);
20 | $easeOutSine : cubic-bezier(0.390, 0.575, 0.565, 1.000);
21 | $easeOutExpo : cubic-bezier(0.190, 1.000, 0.220, 1.000);
22 | $easeOutCirc : cubic-bezier(0.075, 0.820, 0.165, 1.000);
23 | $easeOutBack : cubic-bezier(0.175, 0.885, 0.320, 1.275);
24 |
25 | $easeInOutQuad : cubic-bezier(0.455, 0.030, 0.515, 0.955);
26 | $easeInOutCubic : cubic-bezier(0.645, 0.045, 0.355, 1.000);
27 | $easeInOutQuart : cubic-bezier(0.770, 0.000, 0.175, 1.000);
28 | $easeInOutQuint : cubic-bezier(0.860, 0.000, 0.070, 1.000);
29 | $easeInOutSine : cubic-bezier(0.445, 0.050, 0.550, 0.950);
30 | $easeInOutExpo : cubic-bezier(1.000, 0.000, 0.000, 1.000);
31 | $easeInOutCirc : cubic-bezier(0.785, 0.135, 0.150, 0.860);
32 | $easeInOutBack : cubic-bezier(0.680, -0.550, 0.265, 1.550);
--------------------------------------------------------------------------------
/memcached.php:
--------------------------------------------------------------------------------
1 | .
18 | */
19 |
20 | try {
21 | if ($CONFIG['DEV']) {
22 | // Use Memcache on windows cause i'm (still) too lazy to set up a VM for this project
23 | if (PHP_OS === "WINNT") {
24 | class MemcacheWrap extends Memcache {
25 | public function set($key, $val, $expire = 0) {
26 | return parent::set($key, $val, 0, $expire);
27 | }
28 | }
29 | $Memcached = new MemcacheWrap();
30 | $Memcached->connect($CONFIG["MEMCACHED"]["SERVER"], $CONFIG["MEMCACHED"]["PORT"]);
31 | } else {
32 | $Memcached = new Memcached();
33 | $Memcached->addServer($CONFIG["MEMCACHED"]["SERVER"], $CONFIG["MEMCACHED"]["PORT"]);
34 | }
35 | } else {
36 | $Memcached = new Memcached();
37 | $Memcached->addServer($CONFIG["MEMCACHED"]["SERVER"], $CONFIG["MEMCACHED"]["PORT"]);
38 | }
39 | } catch (Exception $e) {
40 | echo "Memcached has encountered an error.";
41 | die;
42 | } catch (Error $e) {
43 | echo "Memcached has encountered an error.";
44 | die;
45 | }
46 |
--------------------------------------------------------------------------------
/web/static/img/hoster_logos/1fichier.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/templates/index.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 | {% extends 'main.twig' %}
19 |
20 | {% block content %}
21 | {% import "imports/card.twig" as card %}
22 | {% include "imports/details.twig" %}
23 |
24 |
52 | {% endblock content %}
53 |
54 | {% block scripts %}
55 | {% endblock scripts %}
--------------------------------------------------------------------------------
/templates/imports/card.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 | {% macro input(games, elastic) %}
19 | {% if elastic %}
20 | {% set games = games.hits %}
21 | {% endif %}
22 | {% spaceless %}
23 | {% for game in games %}
24 | {% if elastic %}
25 | {% set game_id = game._id %}
26 | {% set game = game._source %}
27 | {% else %}
28 | {% set game_id = game.id %}
29 | {% endif %}
30 |
31 |
45 | {% endif %}
46 |
47 | {% endfor %}
48 | {% endspaceless %}
49 | {% endmacro %}
50 |
--------------------------------------------------------------------------------
/templates/imports/donate.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 |
{{ 'Donate'|trans }}
19 |
20 |
{{ 'Do you love this site? Then donate to help keep it alive! So, how can YOU donate?'|trans }}
21 |
22 |
23 |
24 |
{{ 'What are donations used for exactly?'|trans }}
25 |
{{ 'Each donation is used to help cover operating expenses (storage server, seedbox, VPN tunnel and hosting). All games found on this site are archived on a high-speed storage server in a data center. We are currently using over 9TB of storage. We DO NOT profit from any donations.'|trans }}
26 |
27 |
{{ 'What is the total cost to run the site?'|trans }}
28 |
{{ 'Total expenses are €117 (or $129) per month.'|trans }}
29 |
30 |
{{ 'How can I donate?'|trans }}
31 |
{{ 'You may donate via PayPal, credit/debit card, Bitcoin and other cryptocurrencies. See below for more information on each option.'|trans }}
32 |
33 |
{{ 'I want to donate via PayPal, credit/debit card or another cryptocurrency. How may I?'|trans }}
34 |
{{ 'Please send an email to %email% and let us know how you wish to donate and how much and then we will provide more details.'|trans|nl2br|replace({'%email%': 'admin@gog-games.com'})|raw }}
35 |
36 |
{{ 'I have Bitcoin. What is your address?'|trans }}
38 |
--------------------------------------------------------------------------------
/web/static/css/_modal.scss:
--------------------------------------------------------------------------------
1 | .modal-state {
2 | display: none;
3 | &:checked {
4 | + .modal {
5 | opacity: 1;
6 | visibility: visible;
7 | .modal__inner {
8 | box-sizing: content-box;
9 | top: 0;
10 | opacity: 1;
11 | }
12 | }
13 | }
14 | }
15 |
16 | .modal {
17 | opacity: 0;
18 | visibility: hidden;
19 | position: fixed;
20 | top: 0;
21 | right: 0;
22 | bottom: 0;
23 | left: 0;
24 | text-align: left;
25 | background: rgba(0,0,0, .5);
26 | transition: opacity 200ms ease;
27 | box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
28 | z-index: 999;
29 | .modal__bg {
30 | position: absolute;
31 | top: 0;
32 | right: 0;
33 | bottom: 0;
34 | left: 0;
35 | cursor: pointer;
36 | }
37 | .modal__inner {
38 | transition: top 200ms $ease-out, visibility 200ms $ease-out, opacity 200ms $ease-out;
39 | position: absolute;
40 | opacity: 0;
41 | top: 20%;
42 | bottom: 0;
43 | right: 0;
44 | left: 0;
45 | width: 90%;
46 | margin: auto;
47 | overflow: auto;
48 | background: $body-bg;
49 | padding: 25px;
50 | padding-top: 45px;
51 | height: 75%;
52 | border-radius: 4px;
53 | @include mq($from: md) {
54 | left: 50%;
55 | right: auto;
56 | min-width: 750px;
57 | width: auto;
58 | transform: translateX(-50%);
59 | }
60 | &.nopad {
61 | padding-top: 10px;
62 | }
63 | & > h4 {
64 | margin: -35px 0 5px 0;
65 | }
66 | .modal__close {
67 | position: absolute;
68 | right: 0;
69 | top: 0;
70 | padding: 20px;
71 | width: 20px;
72 | height: 20px;
73 | cursor: pointer;
74 | &:after, &:before {
75 | content: '';
76 | position: absolute;
77 | width: 2px;
78 | height: 1.5em;
79 | background: #ccc;
80 | display: block;
81 | transform: rotate(45deg);
82 | left: 50%;
83 | margin: -3px 0 0 -1px;
84 | top: 10px;
85 | }
86 | &:before {
87 | transform: rotate(-45deg);
88 | }
89 | &:hover {
90 | &:after, &:before {
91 | background: #aaa;
92 | }
93 | }
94 | }
95 | }
96 | }
--------------------------------------------------------------------------------
/templates/imports/faq.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 |
{{ 'Frequently Asked Questions'|trans }}
19 |
{{ 'What is the purpose of this site?'|trans }}
20 |
{{ 'Simple! To upload and share games from %goglink%.'|trans|nl2br|replace({'%goglink%': 'GOG.com'})|raw }}
21 |
{{ 'What is the easiest way to download or extract files?'|trans }}
22 |
{{ 'Please use %jdownloader2link% to download game files and %7ziplink% to extract them.'|trans|nl2br|replace({'%jdownloader2link%': 'JDownloader 2', '%7ziplink%': '7-Zip'})|raw }}
23 |
{{ 'Why do I have to complete captcha to view download links?'|trans }}
24 |
{{ 'This is to deter bots from scraping the site and issuing a DMCA takedown on filehosters.'|trans }}
25 |
{{ 'How are download links prevented from expiring?'|trans }}
26 |
{{ 'All games are available to be voted on for a re-upload 60 days after they were last uploaded to guard against dead links.'|trans }}
27 |
{{ 'How can I support the site?'|trans }}
28 |
{{ 'Finding bugs is one way! If you run into any issues or notice anything out of place, please open an issue on %githublink%.'|trans|nl2br|replace({'%githublink%': 'GitHub'})|raw }}
31 |
--------------------------------------------------------------------------------
/templates/queue.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 | {% extends 'main.twig' %}
19 |
20 | {% block title %}{{ 'Upload Queue'|trans }}{% endblock title %}
21 |
22 | {% set queue_starter %}
23 | {% trans %}Here is the list of games currently in the queue.
24 | New games are uploaded first, then updated games, then games ordered by most votes.{% endtrans %}
25 | {% endset %}
26 |
27 | {% block content %}
28 |
73 | {% endblock content %}
74 |
75 | {% block scripts %}
76 | {% endblock scripts %}
--------------------------------------------------------------------------------
/twig.ext.php:
--------------------------------------------------------------------------------
1 | .
18 | */
19 |
20 | class AppExtension extends \Twig_Extension {
21 | public function getFunctions(){
22 | return array(
23 | new \Twig_SimpleFunction('loadCSS', array($this, 'loadCSS'), array('is_safe' => array('html'))),
24 | new \Twig_SimpleFunction('loadJS', array($this, 'loadJS'), array('is_safe' => array('html'))),
25 | );
26 | }
27 |
28 | public function getFilters(){
29 | return array(
30 | new \Twig_SimpleFilter('long2ip', array($this, 'long2ip')),
31 | new \Twig_SimpleFilter('convertBytes', array($this, 'convertBytes')),
32 | );
33 | }
34 |
35 | public function long2ip($int){
36 | return long2ip($int);
37 | }
38 |
39 | public function convertBytes($bytes, $decimals = 2){
40 | // Jeffrey Sambells
41 | // http://jeffreysambells.com/2012/10/25/human-readable-filesize-php
42 | $size = array('B','KB','MB','GB','TB','PB','EB','ZB','YB');
43 | $factor = floor((strlen($bytes) - 1) / 3);
44 | return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) .' '. @$size[$factor];
45 | }
46 |
47 | public function loadCSS($styles, $integrity = null){
48 | $ret = array();
49 | if (is_array($styles)) {
50 | foreach ($styles as $key => $value) {
51 | if ($integrity !== null) {
52 | if (!empty($integrity[$key])) {
53 | $integStr = ' integrity="'.$integrity[$key].'"';
54 | } else {
55 | $integStr = '';
56 | }
57 | }
58 | if (file_exists(__DIR__.'/web/'.$value)) {
59 | $ret[] = '';
60 | }
61 | }
62 | }
63 | return join($ret, "\n");
64 | }
65 | public function loadJS($scripts, $integrity = null){
66 | $ret = array();
67 | if (is_array($scripts)) {
68 | foreach ($scripts as $key => $value) {
69 | if ($integrity !== null) {
70 | if (!empty($integrity[$key])) {
71 | $integStr = ' integrity="'.$integrity[$key].'"';
72 | } else {
73 | $integStr = '';
74 | }
75 | }
76 | if (file_exists(__DIR__.'/web/'.$value)) {
77 | $ret[] = '';
78 | }
79 | }
80 | }
81 | return join($ret, "\n");
82 | }
83 | }
--------------------------------------------------------------------------------
/web/static/css/_visualcaptcha.scss:
--------------------------------------------------------------------------------
1 | /*! visualCaptcha - v0.0.8 - 2016-01-23
2 | * http://visualcaptcha.net
3 | * Copyright (c) 2016 emotionLoop; Licensed MIT */
4 |
5 | /*---------------------------------------------------
6 | LESS Elements 0.9
7 | ---------------------------------------------------
8 | A set of useful LESS mixins
9 | More info at: http://lesselements.com
10 | ---------------------------------------------------*/
11 | .visualCaptcha {
12 | min-height: 120px;
13 | }
14 | .visualCaptcha * {
15 | -webkit-box-sizing: border-box;
16 | -moz-box-sizing: border-box;
17 | box-sizing: border-box;
18 | }
19 | .visualCaptcha .audioField {
20 | font-size: 15px;
21 | color: #495e62;
22 | font-weight: 100;
23 | padding: 5px;
24 | border: 1px solid #3bb6e4;
25 | height: 40px;
26 | width: 100%;
27 | -webkit-border-radius: 4px;
28 | -moz-border-radius: 4px;
29 | border-radius: 4px;
30 | }
31 |
32 | .accessibility-description,
33 | .visualCaptcha-explanation,
34 | .status.valid {
35 | padding: 10px;
36 | text-align: center;
37 | font-size: 26px;
38 | font-weight: 100;
39 | margin: 20px 0 24px;
40 | }
41 | .visualCaptcha-possibilities,
42 | .visualCaptcha-refresh-button,
43 | .visualCaptcha-accessibility-button,
44 | .visualCaptcha-button-group {
45 | display: inline-block;
46 | }
47 | .visualCaptcha-possibilities {
48 | vertical-align: middle;
49 | }
50 | .visualCaptcha-possibilities .img {
51 | border: 3px solid transparent;
52 | padding: 5px;
53 | display: inline-block;
54 | }
55 | .visualCaptcha-possibilities img {
56 | width: auto;
57 | height: 45px;
58 | z-index: 5;
59 | transition: all 200ms;
60 | -webkit-transition: all 200ms;
61 | }
62 | .visualCaptcha-possibilities img:hover {
63 | cursor: pointer;
64 | }
65 | .visualCaptcha-possibilities .visualCaptcha-selected {
66 | background-color: #cdbbf0;
67 | border-radius: 4px;
68 | border: 3px dashed #7f4fdb;
69 | }
70 | .visualCaptcha-refresh-button a {
71 | min-width: auto;
72 | }
73 | .visualCaptcha-refresh-button img {
74 | width: 16px;
75 | height: 16px;
76 | }
77 | .visualCaptcha-refresh-button:hover {
78 | cursor: pointer;
79 | }
80 | .visualCaptcha-accessibility-button {
81 | padding: 9px 10px 7px;
82 | border: 1px solid black;
83 | -webkit-border-radius: 100px;
84 | -moz-border-radius: 100px;
85 | border-radius: 100px;
86 | }
87 | .visualCaptcha-accessibility-button img {
88 | width: 16px;
89 | height: 16px;
90 | }
91 | .visualCaptcha-accessibility-button:hover {
92 | cursor: pointer;
93 | }
94 | /* Animations for hiding/showing accessibility option and images */
95 | @-webkit-keyframes fadeIn {
96 | from {
97 | opacity: 0;
98 | }
99 | to {
100 | opacity: 1;
101 | }
102 | }
103 | @keyframes fadeIn {
104 | from {
105 | opacity: 0;
106 | }
107 | to {
108 | opacity: 1;
109 | }
110 | }
111 | @-webkit-keyframes fadeOut {
112 | from {
113 | opacity: 1;
114 | }
115 | to {
116 | opacity: 0;
117 | }
118 | }
119 | @keyframes fadeOut {
120 | from {
121 | opacity: 1;
122 | }
123 | to {
124 | opacity: 0;
125 | }
126 | }
127 | div.visualCaptcha .visualCaptcha-show {
128 | -webkit-animation: fadeIn 300ms;
129 | animation: fadeIn 300ms;
130 | }
131 | div.visualCaptcha .visualCaptcha-hide {
132 | display: none !important;
133 | -webkit-animation: fadeOut 300ms;
134 | animation: fadeOut 300ms;
135 | }
136 |
--------------------------------------------------------------------------------
/templates/search.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 | {% extends 'main.twig' %}
19 |
20 | {% block title %}{% if all == false %}{{ term }}{% endif %}{% endblock title %}
21 |
22 | {% block content %}
23 | {% import "imports/card.twig" as card %}
24 | {% include "imports/details.twig" %}
25 |
26 |
27 | {% set term = term|e %}
28 | {% if all == false %}
29 |
{{ 'Search Results'|trans }}
30 | {% else %}
31 |
{% if developer %}{{ games.hits[0]._source.developer }}{% elseif pagination.genre != 'any' and term == 'all' %}{{ pagination.genre }}{% else %}{{ 'All Games'|trans }}{% endif %}
32 | {% endif %}
33 | {% if total > 0 %}
34 | {% import "pagination.twig" as pager %}
35 |
36 | {% if all == false %}
37 | {% trans %}
38 | 1 game found for "{{ term }}"
39 | {% plural total %}
40 | {{ total }} games found for "{{ term }}"
41 | {% endtrans %}
42 | {% endif %}
43 |
44 |
45 |
46 |
{% if pagination.sort is empty %}Sort{% else %}{{ pagination.sort|capitalize }}{% endif %}
47 |
48 |
{{ 'Title'|trans }}{% if pagination.sort == 'title' %} {% if pagination.sortby == 'asc' %}{% else %}{% endif %}{% endif %}
49 |
{{ 'Date'|trans }}{% if pagination.sort == 'date' %} {% if pagination.sortby == 'asc' %}{% else %}{% endif %}{% endif %}
77 | {% endblock content %}
78 |
79 | {% block scripts %}
80 | {% endblock scripts %}
--------------------------------------------------------------------------------
/web/static/js/prepend/scrollTo.js:
--------------------------------------------------------------------------------
1 | // https://github.com/ericktatsui/scroll-top-pure-js
2 | // Licensed under the MIT License
3 | var scrollTo = function (opt) {
4 | var self,
5 | cache = {};
6 |
7 | var scrollTo = function () {
8 | self = this;
9 |
10 | this.start = self.getCurrentPosition();
11 | this.change = self.getNewPosition() - this.start;
12 | this.currentTime = 0;
13 | this.increment = 20;
14 | this.duration = (typeof (opt.duration) === 'undefined') ? 500 : opt.duration;
15 |
16 | if (!this.fail) {
17 | this.animate();
18 | }
19 | };
20 |
21 | scrollTo.prototype.animate = function () {
22 | // increment the time
23 | self.currentTime += self.increment;
24 | // find the value with the quadratic in-out easing function
25 | var val = self.easing()(self.currentTime, self.start, self.change, self.duration);
26 | // move the document.body, document.documentElement and window all at once for maximum
27 | document.body.scrollTop = val;
28 | document.documentElement.scrollTop = val;
29 | window.scrollTop = val;
30 | // do the animation unless its over
31 | if (self.currentTime < self.duration) {
32 | self.requestAnimFrame()(self.animate);
33 | } else {
34 | if (opt.callback && typeof (opt.callback) === 'function') {
35 | // the animation is done so lets callback
36 | opt.callback();
37 | }
38 | }
39 | };
40 |
41 | scrollTo.prototype.callFail = function () {
42 | self.fail = true;
43 | console.error('Argument is not valid.');
44 | };
45 |
46 | scrollTo.prototype.getNewPosition = function () {
47 | var position = 0,
48 | element;
49 |
50 | if (typeof (opt.targetName) == 'string') {
51 | element = document.querySelector(opt.targetName);
52 |
53 | if (element) {
54 | position = (element.getBoundingClientRect()).top + window.scrollY;
55 | } else {
56 | self.callFail();
57 | }
58 | } else if (typeof (opt.position) == 'number') {
59 | position = opt.position;
60 | } else if (typeof (opt.target) == 'object' && 'getBoundingClientRect' in opt.target) {
61 | position = (opt.target.getBoundingClientRect()).top + window.scrollY;
62 | } else {
63 | self.callFail();
64 | }
65 |
66 | return position;
67 | };
68 |
69 | scrollTo.prototype.easing = function () {
70 | var easeType;
71 |
72 | if(!cache.easing){
73 | switch (opt.easing) {
74 | case 'easeInCubic':
75 | easeType = self.easeInCubic;
76 | break;
77 | case 'inOutQuintic':
78 | easeType = self.inOutQuintic;
79 | break;
80 | default:
81 | easeType = self.easeInOutQuad;
82 | break;
83 | }
84 |
85 | cache.easing = easeType;
86 | }else{
87 | easeType = cache.easing;
88 | }
89 |
90 | return easeType;
91 | };
92 |
93 | scrollTo.prototype.easeInOutQuad = function (t, b, c, d) {
94 | t /= d / 2;
95 | if (t < 1) {
96 | return c / 2 * t * t + b
97 | }
98 | t--;
99 | return -c / 2 * (t * (t - 2) - 1) + b;
100 | };
101 |
102 | scrollTo.prototype.easeInCubic = function (t, b, c, d) {
103 | var tc = (t /= d) * t * t;
104 | return b + c * (tc);
105 | };
106 |
107 | scrollTo.prototype.inOutQuintic = function (t, b, c, d) {
108 | var ts = (t /= d) * t,
109 | tc = ts * t;
110 | return b + c * (6 * tc * ts + -15 * ts * ts + 10 * tc);
111 | };
112 |
113 | // polyfill
114 | scrollTo.prototype.requestAnimFrame = function () {
115 | return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); };
116 | };
117 |
118 | scrollTo.prototype.getCurrentPosition = function () {
119 | return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop;
120 | };
121 |
122 | return new scrollTo();
123 | };
--------------------------------------------------------------------------------
/INSTALL.md:
--------------------------------------------------------------------------------
1 | # GOGGames Installation
2 |
3 | These instructions assume you have experience with installing, configuring, and securing web site software within Linux. Instructions have been tested with Ubuntu 16.04.4 LTS and Debian Stretch.
4 |
5 | That said, it is possible to run GOGGames on a Windows server.
6 | ### Prerequisites
7 |
8 | - PHP >= 7.2
9 |
10 | `apt-get install php`
11 | - MariaDB
12 |
13 | `apt-get install mariadb-server`
14 | - Java or OpenJDK (whichever version that whatever version of ElasticSearch you installed wants)
15 |
16 | `apt-get install openjdk-8-jdk`
17 | - ElasticSearch >= 6.2
18 |
19 | https://www.elastic.co/downloads/elasticsearch
20 | - memcached
21 |
22 | `apt-get install memcached`
23 | - Composer
24 |
25 | https://getcomposer.org/download/
26 |
27 | ### Installing
28 | ##### Getting the sauce:
29 |
30 | ```bash
31 | git clone https://github.com/Good-Old-Downloads/gg.git
32 | ```
33 |
34 | ##### Installing the PHP requirements:
35 | `cd` into the directory where the code now lies then install the site dependencies via Composer:
36 | ```bash
37 | cd gg
38 | php composer.phar install
39 | ```
40 | ##### Configuring the site:
41 | Make a copy of config_blank.php named config.php and edit it.
42 | ```bash
43 | cp config_blank.php config.php
44 | vi config.php
45 | ```
46 | config.php explantion:
47 | ```php
48 | 'ayylmaosecretloginpageyolo',
52 | "BASEDIR" => "/var/www/gg",
53 |
54 | // Storage paths for GOG iamges
55 | "BG_STORAGE" => "/var/www/gg/static/img/games/bg",
56 | "DETAILS_STORAGE" => "/var/www/god/static/img/games/details",
57 | "THUMB_STORAGE" => "/var/www/god/static/img/games/thumb",
58 |
59 | // Shows PHP errors, disables the Twig cache, probably does other things.
60 | // Set to false in production.
61 | "DEV" => true,
62 |
63 | // GG has no user system. Set up the login name and password here.
64 | // Again, use a script to change this once in a while if you're paranoid.
65 | "USER" => [
66 | "NAME" => "supasecretlogin",
67 | "PASS" => "123",
68 |
69 | // Key used with the http API
70 | "KEY" => "123-321-1337"
71 | ],
72 |
73 | // MySQL deets
74 | "DB" => [
75 | "DBNAME" => "gg",
76 | "DBUSER" => "root",
77 | "DBPASS" => ""
78 | ],
79 |
80 | // Memcached deets
81 | "MEMCACHED" => [
82 | "SERVER" => "127.0.0.1",
83 | "PORT" => 11211
84 | ]
85 | ];
86 |
87 | // Keys for the Vigenère cipher. Make a lot of these.
88 | // Shitty way to stop the most basic of HTML scrapers, if someone takes time to put the smallest amount of effort decypher this, then they deserve the links. (pretty sure someone from The Eye already made a dumper)
89 | $VKEYS = [
90 | "RANDKEYONE",
91 | "RANDKEYTWO",
92 | "RANDKEYTHREE",
93 | "RANDKEYFOUR",
94 | "RANDKEYFIVE",
95 | "RANDKEYSIX",
96 | "RANDKESVEN"
97 | ];
98 | ```
99 |
100 | ##### Importing the empty database:
101 | Login to MySQL, create a database, then import db.sql.
102 | ```
103 | MariaDB [(none)]> CREATE DATABASE `gg`;
104 | MariaDB [gg]> USE `gg`;
105 | MariaDB [gg]> SOURCE db.sql;
106 | ```
107 |
108 | ##### Configuring the Nginx:
109 | The Nginx config is pretty standard. I'll only list the relevant config values.
110 | ```nginx
111 | server {
112 | listen 443 ssl http2;
113 | root /var/www/gg/web; # <-- must point to /web directory
114 | index index.php
115 | autoindex on;
116 | location = /index.php {
117 | try_files $uri =404;
118 | fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
119 | fastcgi_index index.php;
120 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
121 | include fastcgi_params;
122 | }
123 | location / {
124 | try_files $uri /index.php$is_args$args;
125 | }
126 | location ~ \.php$ {
127 | # prevent exposure of any other .php files!!!
128 | return 404;
129 | }
130 | location ~ /\.ht {
131 | deny all;
132 | }
133 | }
134 | ```
135 |
136 | ##### Starting up memcached and ElasticSearch:
137 | If you made it this far, you should know how to start these up already, and how to secure them both.
138 |
139 | ### Running tests
140 | lol
141 |
142 | ### Coding style
143 | hahaha
144 |
--------------------------------------------------------------------------------
/web/static/css/_roboto.scss:
--------------------------------------------------------------------------------
1 | /* roboto-300 - greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext */
2 | @font-face {
3 | font-family: 'Roboto';
4 | font-style: normal;
5 | font-weight: 300;
6 | src: url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.eot'); /* IE9 Compat Modes */
7 | src: local('Roboto Light'), local('Roboto-Light'),
8 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
9 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.woff2') format('woff2'), /* Super Modern Browsers */
10 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.woff') format('woff'), /* Modern Browsers */
11 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.ttf') format('truetype'), /* Safari, Android, iOS */
12 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-300.svg#Roboto') format('svg'); /* Legacy iOS */
13 | }
14 |
15 | /* roboto-regular - greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext */
16 | @font-face {
17 | font-family: 'Roboto';
18 | font-style: normal;
19 | font-weight: 400;
20 | src: url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.eot'); /* IE9 Compat Modes */
21 | src: local('Roboto'), local('Roboto-Regular'),
22 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
23 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.woff2') format('woff2'), /* Super Modern Browsers */
24 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.woff') format('woff'), /* Modern Browsers */
25 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.ttf') format('truetype'), /* Safari, Android, iOS */
26 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-regular.svg#Roboto') format('svg'); /* Legacy iOS */
27 | }
28 |
29 | /* roboto-italic - greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext */
30 | @font-face {
31 | font-family: 'Roboto';
32 | font-style: italic;
33 | font-weight: 400;
34 | src: url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.eot'); /* IE9 Compat Modes */
35 | src: local('Roboto Italic'), local('Roboto-Italic'),
36 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
37 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.woff2') format('woff2'), /* Super Modern Browsers */
38 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.woff') format('woff'), /* Modern Browsers */
39 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.ttf') format('truetype'), /* Safari, Android, iOS */
40 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-italic.svg#Roboto') format('svg'); /* Legacy iOS */
41 | }
42 |
43 | /* roboto-500 - greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext */
44 | @font-face {
45 | font-family: 'Roboto';
46 | font-style: normal;
47 | font-weight: 500;
48 | src: url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.eot'); /* IE9 Compat Modes */
49 | src: local('Roboto Medium'), local('Roboto-Medium'),
50 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
51 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.woff2') format('woff2'), /* Super Modern Browsers */
52 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.woff') format('woff'), /* Modern Browsers */
53 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.ttf') format('truetype'), /* Safari, Android, iOS */
54 | url('../fonts/roboto-v18-greek-ext_latin_vietnamese_greek_cyrillic_latin-ext_cyrillic-ext-500.svg#Roboto') format('svg'); /* Legacy iOS */
55 | }
56 |
--------------------------------------------------------------------------------
/migrate.php:
--------------------------------------------------------------------------------
1 | prepare("SELECT `game_id`, `files`, `uploading` FROM old_gog.`games_filelist`");
12 | $get->execute();
13 | $old_data = $get->fetchAll(\PDO::FETCH_OBJ);
14 |
15 | $getTimes = $dbh->prepare("SELECT `id`, UNIX_TIMESTAMP(`time_upload`) as time_upload, UNIX_TIMESTAMP(`time_update`) as time_update FROM old_gog.`games`");
16 | $getTimes->execute();
17 | $times = $getTimes->fetchAll(\PDO::FETCH_OBJ);
18 |
19 | $setTime = $dbh->prepare("UPDATE `games` SET `last_update` = :update, `last_upload` = :upload WHERE `id` = :id");
20 | $setTime->bindParam(':id', $id, \PDO::PARAM_INT);
21 | $setTime->bindParam(':upload', $upload, \PDO::PARAM_INT);
22 | $setTime->bindParam(':update', $update, \PDO::PARAM_INT);
23 | foreach ($times as $key => $value) {
24 | $id = intval($value->id);
25 | $upload = $value->time_upload;
26 | $update = $value->time_update;
27 | $setTime->execute();
28 | }
29 |
30 | $getTags = $dbh->prepare("SELECT `id`, `updated`, `new`, `hidden` FROM old_gog.`games`");
31 | $getTags->execute();
32 | $tags = $getTags->fetchAll(\PDO::FETCH_OBJ);
33 |
34 | $setTags = $dbh->prepare("UPDATE `games` SET `new` = :new, `updated` = :updated, `hidden` = :hidden WHERE `id` = :id");
35 | $setTags->bindParam(':id', $id, \PDO::PARAM_INT);
36 | $setTags->bindParam(':new', $new, \PDO::PARAM_INT);
37 | $setTags->bindParam(':updated', $updated, \PDO::PARAM_INT);
38 | $setTags->bindParam(':hidden', $hidden, \PDO::PARAM_INT);
39 | foreach ($tags as $key => $value) {
40 | $id = intval($value->id);
41 | $updated = intval($value->updated);
42 | $new = intval($value->new);
43 | $hidden = intval($value->hidden);
44 | $setTags->execute();
45 | }
46 |
47 | foreach ($old_data as $key => $value) {
48 | if ($value->uploading == 1) {
49 | continue;
50 | }
51 | $id = intval($value->game_id);
52 | $file_info = json_decode($value->files);
53 | foreach ($file_info as $key => $file) {
54 | switch ($key) {
55 | case 'goodies':
56 | $set = $dbh->prepare("INSERT IGNORE INTO `links` (`game_id`, `link`, `type`) VALUES (:id, :link, 'GOODIES')");
57 | foreach ($file as $key => $link) {
58 | $set->bindParam(':id', $id, \PDO::PARAM_INT);
59 | $set->bindParam(':link', $link, \PDO::PARAM_STR);
60 | $set->execute();
61 | }
62 | break;
63 | case 'game':
64 | $set = $dbh->prepare("INSERT IGNORE INTO `links` (`game_id`, `link`, `type`) VALUES (:id, :link, 'GAME')");
65 | foreach ($file as $key => $link) {
66 | $set->bindParam(':id', $id, \PDO::PARAM_INT);
67 | $set->bindParam(':link', $link, \PDO::PARAM_STR);
68 | $set->execute();
69 | }
70 | break;
71 | case 'goodies_list':
72 | $set = $dbh->prepare("INSERT IGNORE INTO `files` (`game_id`, `name`, `type`) VALUES (:id, :name, 'GOODIES')");
73 | foreach ($file as $key => $name) {
74 | $set->bindParam(':id', $id, \PDO::PARAM_INT);
75 | $set->bindParam(':name', $name, \PDO::PARAM_STR);
76 | $set->execute();
77 | }
78 | break;
79 | case 'game_list':
80 | $set = $dbh->prepare("INSERT IGNORE INTO `files` (`game_id`, `name`, `type`) VALUES (:id, :name, 'GAME')");
81 | foreach ($file as $key => $name) {
82 | $set->bindParam(':id', $id, \PDO::PARAM_INT);
83 | $set->bindParam(':name', $name, \PDO::PARAM_STR);
84 | $set->execute();
85 | }
86 | break;
87 | case 'patch_list':
88 | $set = $dbh->prepare("INSERT IGNORE INTO `files` (`game_id`, `name`, `type`) VALUES (:id, :name, 'PATCHES')");
89 | foreach ($file as $key => $name) {
90 | $set->bindParam(':id', $id, \PDO::PARAM_INT);
91 | $set->bindParam(':name', $name, \PDO::PARAM_STR);
92 | $set->execute();
93 | }
94 | break;
95 | case 'patch':
96 | $set = $dbh->prepare("INSERT IGNORE INTO `links` (`game_id`, `link`, `type`) VALUES (:id, :link, 'PATCHES')");
97 | foreach ($file as $key => $link) {
98 | $set->bindParam(':id', $id, \PDO::PARAM_INT);
99 | $set->bindParam(':link', $link, \PDO::PARAM_STR);
100 | $set->execute();
101 | }
102 | break;
103 |
104 | default:
105 | echo "oh shit\n";
106 | echo $key;
107 | die;
108 | break;
109 | }
110 | }
111 | }
--------------------------------------------------------------------------------
/templates/pagination.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 |
19 | {# Welcome to hell #}
20 | {# Imported from SG. (it's even worse) #}
21 | {% macro input(pagination, path, adjacents = 2) %}
22 | {% if pagination.page < 1 %}
23 | {% set page = 1 %}
24 | {% else %}
25 | {% set page = pagination.page %}
26 | {% endif %}
27 |
28 | {% set lastpage = (pagination.total/pagination.limit)|round(0, 'ceil') %}
29 |
30 | {% if lastpage <= 0 %}
31 | {% set lastpage = 1 %}
32 | {% endif %}
33 |
34 | {% set prevpage = page - 1 %}
35 |
36 |
37 | {% if page > 1 %}
38 |
39 | {% else %}
40 |
41 | {% endif %}
42 |
43 | {% if lastpage < 7 + (adjacents * 2) %}
44 | {% for i in 1..lastpage %}
45 | {% if i == page %}
46 | {{ i }}
47 | {% else %}
48 | {{ i }}
49 | {% endif %}
50 | {% endfor %}
51 | {% elseif (pagination.total >= 7 + (adjacents * 2)) %} {# enough pages to hide some #}
52 | {# close to beginning; only hide later pages #}
53 | {% if page < 1 + (adjacents * 2) %}
54 | {% for i in 1..(4 + (adjacents * 2)) %}
55 | {% if i == page %}
56 | {{ i }}
57 | {% else %}
58 | {{ i }}
59 | {% endif %}
60 | {% endfor %}
61 | ...
62 | {{ lastpage - 1 }}
63 | {{ lastpage }}
64 | {# in middle; hide some front and some back #}
65 | {% elseif lastpage - (adjacents * 2) > page and page > (adjacents * 2) %}
66 | 1
67 | 2
68 | ...
69 | {% for i in (page - adjacents)..(page + adjacents) %}
70 | {% if i == page %}
71 | {{ i }}
72 | {% else %}
73 | {{ i }}
74 | {% endif %}
75 | {% endfor %}
76 | ...
77 | {{ lastpage - 1 }}
78 | {{ lastpage }}
79 | {% else %}
80 | {# close to end; only hide early pages #}
81 | 1
82 | 2
83 | ...
84 | {% for i in (lastpage - (2 + (adjacents * 2)))..lastpage %}
85 | {% if i == page %}
86 | {{ i }}
87 | {% else %}
88 | {{ i }}
89 | {% endif %}
90 | {% endfor %}
91 | {% endif %}
92 | {% endif %}
93 | {% if page < lastpage %}
94 |
95 | {% else %}
96 |
97 | {% endif %}
98 |
99 | {% endmacro %}
--------------------------------------------------------------------------------
/templates/drive_tutorial.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 | {% extends 'main.twig' %}
19 |
20 | {% block title %}{{ 'Google Drive Quota Exceeded Bypass Tutorial'|trans }}{% endblock title %}
21 |
22 | {% block content %}
23 |
TL;DR: Click the arrow ( ) to open all Google Drive links -> Go to https://drive.google.com/drive/shared-with-me -> Right click and Make a Copy -> Go to My Drive to download the copied file -> Remove file and empty your trash in Google Drive after download to free up cloud storage space to continue for large games.
26 |
27 |
This tutorial will show you how to bypass the Google Drive download limit for files. This does require a Google account. You can get one for free here: https://accounts.google.com/SignUp
28 |
29 | Please be aware: Google has implemented a user quota (or reduced) for the "Make a copy" option this tutorial uses to bypass file download quota. If your trash is empty and you recieve an error when making a copy of a file, you must create a new Google account and continue using the bypass or wait until your "Make a copy" quota resets (unknown amount of time until it resets -- it does seem to reset every day from our testing).
30 |
31 |
This is the error we want to bypass:
32 |
33 |
34 |
35 |
36 |
Steps to bypass:
37 |
38 |
First you must visit each Google Drive URL in your browser of the file(s) you want to make a copy of. This will make them appear in the "Shared with me" section of your Google Drive. The easiest way to do this with large games is to allow pop-ups for our site, then click the "Open all links" arrow.
39 |
40 |
Now go to https://drive.google.com/drive/shared-with-me. You will see the files we visited in the previous step which you can now click and select. If they are not listed, refresh the page and also make sure you have visited the URLs in your browser (see previous step)!
41 |
Next right click while your files are selected and choose MAKE A COPY from the drop down menu. DO NOT SELECT DOWNLOAD.
42 | Please note that free Google accounts only have 15GB of cloud storage.
43 | If a game is very large, you will have to download then remove the parts of the game you made a copy of from your Google Drive and repeat these steps (see step 7 and 8 on how to remove and delete files from your Google Drive) until you have all required files downloaded to install the game!
44 |
45 |
Next click "My Drive" found on the left hand side.
46 |
The items can now be found in your Google Drive.
47 |
Right click on the item you want to download, then select "Download" in the drop down menu.
48 | For larger files, we recommend you download each one individually as Google will take time to zip the files if you select them all and try to download.
49 |
After your download finishes, you should remove the copies from your Google Drive to free up space in the event you need to do this bypass again (or need to copy and download additional files for larger games).
50 | You can do this by selecting the copies you want to delete, then right click and select "Remove" at the bottom of the drop down menu.
51 |
Finally delete the copies from your trash. Click "Trash" found on the left hand side then click the "Trash" at the top and select "Empty Trash".
52 |
53 |
54 | {% endblock content %}
55 |
56 | {% block scripts %}
57 | {% endblock scripts %}
--------------------------------------------------------------------------------
/templates/admin.twig:
--------------------------------------------------------------------------------
1 | {#
2 | GOGGames
3 | Copyright (C) 2018 GoodOldDownloads
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | #}
18 | {% extends 'main.twig' %}
19 |
20 | {% block title %}{{ 'Administration'|trans }}{% endblock title %}
21 | {% block meta %}{{ loadCSS(['/static/css/admin.css'], []) }}{% endblock meta %}
22 | {% block content %}
23 |
` elements.
56 |
57 | body {
58 | margin: 0; // 1
59 | font-family: $font-family-base;
60 | font-size: $font-size-base;
61 | font-weight: $font-weight-base;
62 | line-height: $line-height-base;
63 | color: $body-color;
64 | text-align: left; // 3
65 | background-color: $body-bg; // 2
66 | }
67 |
68 | // Suppress the focus outline on elements that cannot be accessed via keyboard.
69 | // This prevents an unwanted focus outline from appearing around elements that
70 | // might still respond to pointer events.
71 | //
72 | // Credit: https://github.com/suitcss/base
73 | [tabindex="-1"]:focus {
74 | outline: 0 !important;
75 | }
76 |
77 |
78 | // Content grouping
79 | //
80 | // 1. Add the correct box sizing in Firefox.
81 | // 2. Show the overflow in Edge and IE.
82 |
83 | hr {
84 | box-sizing: content-box; // 1
85 | height: 0; // 1
86 | overflow: visible; // 2
87 | }
88 |
89 |
90 | //
91 | // Typography
92 | //
93 |
94 | // Remove top margins from headings
95 | //
96 | // By default, `
`-`
` all receive top and bottom margins. We nuke the top
97 | // margin for easier control within type scales as it avoids margin collapsing.
98 | // stylelint-disable selector-list-comma-newline-after
99 | h1, h2, h3, h4, h5, h6 {
100 | margin-top: 0;
101 | margin-bottom: $headings-margin-bottom;
102 | }
103 | // stylelint-enable selector-list-comma-newline-after
104 |
105 | // Reset margins on paragraphs
106 | //
107 | // Similarly, the top margin on `
`s get reset. However, we also reset the
108 | // bottom margin to use `rem` units instead of `em`.
109 | p {
110 | margin-top: 0;
111 | margin-bottom: $paragraph-margin-bottom;
112 | }
113 |
114 | // Abbreviations
115 | //
116 | // 1. Remove the bottom border in Firefox 39-.
117 | // 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
118 | // 3. Add explicit cursor to indicate changed behavior.
119 | // 4. Duplicate behavior to the data-* attribute for our tooltip plugin
120 |
121 | abbr[title],
122 | abbr[data-original-title] { // 4
123 | text-decoration: underline; // 2
124 | text-decoration: underline dotted; // 2
125 | cursor: help; // 3
126 | border-bottom: 0; // 1
127 | }
128 |
129 | address {
130 | margin-bottom: 1rem;
131 | font-style: normal;
132 | line-height: inherit;
133 | }
134 |
135 | ol,
136 | ul,
137 | dl {
138 | margin-top: 0;
139 | margin-bottom: 1rem;
140 | }
141 |
142 | ol ol,
143 | ul ul,
144 | ol ul,
145 | ul ol {
146 | margin-bottom: 0;
147 | }
148 |
149 | dt {
150 | font-weight: 600;
151 | }
152 |
153 | dd {
154 | margin-bottom: .5rem;
155 | margin-left: 0; // Undo browser default
156 | }
157 |
158 | blockquote {
159 | margin: 0 0 1rem;
160 | }
161 |
162 | dfn {
163 | font-style: italic; // Add the correct font style in Android 4.3-
164 | }
165 |
166 | // stylelint-disable font-weight-notation
167 | b,
168 | strong {
169 | font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari
170 | }
171 | // stylelint-enable font-weight-notation
172 |
173 | small {
174 | font-size: 80%; // Add the correct font size in all browsers
175 | }
176 |
177 | //
178 | // Prevent `sub` and `sup` elements from affecting the line height in
179 | // all browsers.
180 | //
181 |
182 | sub,
183 | sup {
184 | position: relative;
185 | font-size: 75%;
186 | line-height: 0;
187 | vertical-align: baseline;
188 | }
189 |
190 | sub { bottom: -.25em; }
191 | sup { top: -.5em; }
192 |
193 |
194 | //
195 | // Links
196 | //
197 |
198 | a {
199 | color: $link-color;
200 | text-decoration: $link-decoration;
201 | background-color: transparent; // Remove the gray background on active links in IE 10.
202 | -webkit-text-decoration-skip: objects; // Remove gaps in links underline in iOS 8+ and Safari 8+.
203 | &:hover {
204 | color: $link-hover-color;
205 | text-decoration: $link-hover-decoration;
206 | }
207 | }
208 |
209 | // And undo these styles for placeholder links/named anchors (without href)
210 | // which have not been made explicitly keyboard-focusable (without tabindex).
211 | // It would be more straightforward to just use a[href] in previous block, but that
212 | // causes specificity issues in many other styles that are too complex to fix.
213 | // See https://github.com/twbs/bootstrap/issues/19402
214 |
215 | a:not([href]):not([tabindex]) {
216 | color: inherit;
217 | text-decoration: none;
218 |
219 | &:focus,
220 | &:hover {
221 | color: inherit;
222 | text-decoration: none;
223 | }
224 |
225 | &:focus {
226 | outline: 0;
227 | }
228 | }
229 |
230 |
231 | //
232 | // Code
233 | //
234 |
235 | // stylelint-disable font-family-no-duplicate-names
236 | pre,
237 | code,
238 | kbd,
239 | samp {
240 | font-family: monospace, monospace; // Correct the inheritance and scaling of font size in all browsers.
241 | font-size: 1em; // Correct the odd `em` font sizing in all browsers.
242 | }
243 | // stylelint-enable font-family-no-duplicate-names
244 |
245 | pre {
246 | // Remove browser default top margin
247 | margin-top: 0;
248 | // Reset browser default of `1em` to use `rem`s
249 | margin-bottom: 1rem;
250 | // Don't allow content to break outside
251 | overflow: auto;
252 | // We have @viewport set which causes scrollbars to overlap content in IE11 and Edge, so
253 | // we force a non-overlapping, non-auto-hiding scrollbar to counteract.
254 | -ms-overflow-style: scrollbar;
255 | }
256 |
257 |
258 | //
259 | // Figures
260 | //
261 |
262 | figure {
263 | // Apply a consistent margin strategy (matches our type styles).
264 | margin: 0 0 1rem;
265 | }
266 |
267 |
268 | //
269 | // Images and content
270 | //
271 |
272 | img {
273 | vertical-align: middle;
274 | border-style: none; // Remove the border on images inside links in IE 10-.
275 | }
276 |
277 | svg:not(:root) {
278 | overflow: hidden; // Hide the overflow in IE
279 | }
280 |
281 |
282 | // Avoid 300ms click delay on touch devices that support the `touch-action` CSS property.
283 | //
284 | // In particular, unlike most other browsers, IE11+Edge on Windows 10 on touch devices and IE Mobile 10-11
285 | // DON'T remove the click delay when `` is present.
286 | // However, they DO support removing the click delay via `touch-action: manipulation`.
287 | // See:
288 | // * https://getbootstrap.com/docs/4.0/content/reboot/#click-delay-optimization-for-touch
289 | // * https://caniuse.com/#feat=css-touch-action
290 | // * https://patrickhlauke.github.io/touch/tests/results/#suppressing-300ms-delay
291 |
292 | a,
293 | area,
294 | button,
295 | [role="button"],
296 | input:not([type="range"]),
297 | label,
298 | select,
299 | summary,
300 | textarea {
301 | touch-action: manipulation;
302 | }
303 |
304 |
305 | //
306 | // Tables
307 | //
308 |
309 | table {
310 | border-collapse: collapse; // Prevent double borders
311 | }
312 |
313 | caption {
314 | padding-top: $table-cell-padding;
315 | padding-bottom: $table-cell-padding;
316 | color: $text-muted;
317 | text-align: left;
318 | caption-side: bottom;
319 | }
320 |
321 | th {
322 | // Matches default `
` alignment by inheriting from the ``, or the
323 | // closest parent with a set `text-align`.
324 | text-align: inherit;
325 | }
326 |
327 |
328 | //
329 | // Forms
330 | //
331 |
332 | label {
333 | // Allow labels to use `margin` for spacing.
334 | display: inline-block;
335 | margin-bottom: .5rem;
336 | }
337 |
338 | // Remove the default `border-radius` that macOS Chrome adds.
339 | //
340 | // Details at https://github.com/twbs/bootstrap/issues/24093
341 | button {
342 | border-radius: 0;
343 | }
344 |
345 | // Work around a Firefox/IE bug where the transparent `button` background
346 | // results in a loss of the default `button` focus styles.
347 | //
348 | // Credit: https://github.com/suitcss/base/
349 | button:focus {
350 | outline: 1px dotted;
351 | outline: 5px auto -webkit-focus-ring-color;
352 | }
353 |
354 | input,
355 | button,
356 | select,
357 | optgroup,
358 | textarea {
359 | margin: 0; // Remove the margin in Firefox and Safari
360 | font-family: inherit;
361 | font-size: inherit;
362 | line-height: inherit;
363 | }
364 |
365 | button,
366 | input {
367 | overflow: visible; // Show the overflow in Edge
368 | }
369 |
370 | button,
371 | select {
372 | text-transform: none; // Remove the inheritance of text transform in Firefox
373 | }
374 |
375 | // 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
376 | // controls in Android 4.
377 | // 2. Correct the inability to style clickable types in iOS and Safari.
378 | button,
379 | html [type="button"], // 1
380 | [type="reset"],
381 | [type="submit"] {
382 | -webkit-appearance: button; // 2
383 | }
384 |
385 | // Remove inner border and padding from Firefox, but don't restore the outline like Normalize.
386 | button::-moz-focus-inner,
387 | [type="button"]::-moz-focus-inner,
388 | [type="reset"]::-moz-focus-inner,
389 | [type="submit"]::-moz-focus-inner {
390 | padding: 0;
391 | border-style: none;
392 | }
393 |
394 | input[type="radio"],
395 | input[type="checkbox"] {
396 | box-sizing: border-box; // 1. Add the correct box sizing in IE 10-
397 | padding: 0; // 2. Remove the padding in IE 10-
398 | }
399 |
400 |
401 | input[type="date"],
402 | input[type="time"],
403 | input[type="datetime-local"],
404 | input[type="month"] {
405 | // Remove the default appearance of temporal inputs to avoid a Mobile Safari
406 | // bug where setting a custom line-height prevents text from being vertically
407 | // centered within the input.
408 | // See https://bugs.webkit.org/show_bug.cgi?id=139848
409 | // and https://github.com/twbs/bootstrap/issues/11266
410 | -webkit-appearance: listbox;
411 | }
412 |
413 | textarea {
414 | overflow: auto; // Remove the default vertical scrollbar in IE.
415 | // Textareas should really only resize vertically so they don't break their (horizontal) containers.
416 | resize: vertical;
417 | }
418 |
419 | fieldset {
420 | // Browsers set a default `min-width: min-content;` on fieldsets,
421 | // unlike e.g. `
`s, which have `min-width: 0;` by default.
422 | // So we reset that to ensure fieldsets behave more like a standard block element.
423 | // See https://github.com/twbs/bootstrap/issues/12359
424 | // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements
425 | min-width: 0;
426 | // Reset the default outline behavior of fieldsets so they don't affect page layout.
427 | padding: 0;
428 | margin: 0;
429 | border: 0;
430 | }
431 |
432 | // 1. Correct the text wrapping in Edge and IE.
433 | // 2. Correct the color inheritance from `fieldset` elements in IE.
434 | legend {
435 | display: block;
436 | width: 100%;
437 | max-width: 100%; // 1
438 | padding: 0;
439 | margin-bottom: .5rem;
440 | font-size: 1.5rem;
441 | line-height: inherit;
442 | color: inherit; // 2
443 | white-space: normal; // 1
444 | }
445 |
446 | progress {
447 | vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.
448 | }
449 |
450 | // Correct the cursor style of increment and decrement buttons in Chrome.
451 | [type="number"]::-webkit-inner-spin-button,
452 | [type="number"]::-webkit-outer-spin-button {
453 | height: auto;
454 | }
455 |
456 | [type="search"] {
457 | // This overrides the extra rounded corners on search inputs in iOS so that our
458 | // `.form-control` class can properly style them. Note that this cannot simply
459 | // be added to `.form-control` as it's not specific enough. For details, see
460 | // https://github.com/twbs/bootstrap/issues/11586.
461 | outline-offset: -2px; // 2. Correct the outline style in Safari.
462 | -webkit-appearance: none;
463 | }
464 |
465 | //
466 | // Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
467 | //
468 |
469 | [type="search"]::-webkit-search-cancel-button,
470 | [type="search"]::-webkit-search-decoration {
471 | -webkit-appearance: none;
472 | }
473 |
474 | //
475 | // 1. Correct the inability to style clickable types in iOS and Safari.
476 | // 2. Change font properties to `inherit` in Safari.
477 | //
478 |
479 | ::-webkit-file-upload-button {
480 | font: inherit; // 2
481 | -webkit-appearance: button; // 1
482 | }
483 |
484 | //
485 | // Correct element displays
486 | //
487 |
488 | output {
489 | display: inline-block;
490 | }
491 |
492 | summary {
493 | display: list-item; // Add the correct display in all browsers
494 | cursor: pointer;
495 | }
496 |
497 | template {
498 | display: none; // Add the correct display in IE
499 | }
500 |
501 | // Always hide an element with the `hidden` HTML attribute (from PureCSS).
502 | // Needed for proper display in IE 10-.
503 | [hidden] {
504 | display: none !important;
505 | }
506 |
--------------------------------------------------------------------------------