diff --git a/.gitignore b/.gitignore index 4efba1ddbe..a8e9bbcb11 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /index.php /index.html /preactalpha.html +/crossprotocol.html /data/* node_modules/ eslint-cache/ @@ -39,6 +40,7 @@ package-lock.json /js/panel-teambuilder-team.js /js/panel-teamdropdown.js /js/panel-battle.js +/js/replay-embed.js /replays/caches/ /replays/replay-config.inc.php diff --git a/action.php b/action.php index 22e4b0150a..4dc5d90fdf 100644 --- a/action.php +++ b/action.php @@ -9,9 +9,11 @@ error_reporting(E_ALL); +include_once __DIR__ . '/config/config.inc.php'; + if (@$_GET['act'] === 'dlteam') { header("Content-Type: text/plain; charset=utf-8"); - if (substr(@$_SERVER['HTTP_REFERER'], 0, 32) !== 'https://play.pokemonshowdown.com') { + if (substr(@$_SERVER['HTTP_REFERER'], 0, 32) !== 'https://' . $psconfig['routes']['client']) { // since this is only to support Chrome on HTTPS, we can get away with a very specific referer check die("access denied"); } @@ -26,9 +28,9 @@ } // header("X-Debug: " . @$_SERVER['HTTP_REFERER']); -include_once 'lib/ntbb-session.lib.php'; -include_once '../pokemonshowdown.com/config/servers.inc.php'; -include_once 'lib/dispatcher.lib.php'; +require_once __DIR__ . '/lib/ntbb-session.lib.php'; +include_once __DIR__ . '/../pokemonshowdown.com/config/servers.inc.php'; +include_once __DIR__ . '/lib/dispatcher.lib.php'; $dispatcher = new ActionDispatcher(array( new DefaultActionHandler(), diff --git a/build-tools/build-indexes b/build-tools/build-indexes index 4ff25d89d8..e580690410 100755 --- a/build-tools/build-indexes +++ b/build-tools/build-indexes @@ -8,18 +8,18 @@ const child_process = require("child_process"); const rootDir = path.resolve(__dirname, '..'); process.chdir(rootDir); -if (!fs.existsSync('data/Pokemon-Showdown')) { +if (!fs.existsSync('data/pokemon-showdown')) { child_process.execSync('git clone https://github.com/smogon/pokemon-showdown.git', { cwd: 'data', }); } process.stdout.write("Syncing data from Git repository... "); -child_process.execSync('git pull', {cwd: 'data/Pokemon-Showdown'}); -child_process.execSync('npm run build', {cwd: 'data/Pokemon-Showdown'}); +child_process.execSync('git pull', {cwd: 'data/pokemon-showdown'}); +child_process.execSync('npm run build', {cwd: 'data/pokemon-showdown'}); console.log("DONE"); -const Dex = require('../data/Pokemon-Showdown/.sim-dist/dex').Dex; +const Dex = require('../data/pokemon-showdown/.sim-dist/dex').Dex; const toID = Dex.getId; process.stdout.write("Loading gen 6 data... "); Dex.includeData(); @@ -985,7 +985,7 @@ console.log("DONE"); process.stdout.write("Building `data/pokedex.js`... "); { - const Pokedex = requireNoCache('../data/Pokemon-Showdown/.data-dist/pokedex.js').BattlePokedex; + const Pokedex = requireNoCache('../data/pokemon-showdown/.data-dist/pokedex.js').BattlePokedex; for (const id in Pokedex) { const entry = Pokedex[id]; if (Dex.data.FormatsData[id]) { @@ -1011,7 +1011,7 @@ console.log("DONE"); process.stdout.write("Building `data/moves,items,abilities,typechart,learnsets.js`..."); { - const Movedex = requireNoCache('../data/Pokemon-Showdown/.data-dist/moves.js').BattleMovedex; + const Movedex = requireNoCache('../data/pokemon-showdown/.data-dist/moves.js').BattleMovedex; const buf = 'exports.BattleMovedex = ' + es3stringify(Movedex) + ';'; fs.writeFileSync('data/moves.js', buf); } @@ -1021,7 +1021,7 @@ process.stdout.write("Building `data/moves,items,abilities,typechart,learnsets.j *********************************************************/ { - const Items = requireNoCache('../data/Pokemon-Showdown/.data-dist/items.js').BattleItems; + const Items = requireNoCache('../data/pokemon-showdown/.data-dist/items.js').BattleItems; const buf = 'exports.BattleItems = ' + es3stringify(Items) + ';'; fs.writeFileSync('data/items.js', buf); } @@ -1031,7 +1031,7 @@ process.stdout.write("Building `data/moves,items,abilities,typechart,learnsets.j *********************************************************/ { - const Abilities = requireNoCache('../data/Pokemon-Showdown/.data-dist/abilities.js').BattleAbilities; + const Abilities = requireNoCache('../data/pokemon-showdown/.data-dist/abilities.js').BattleAbilities; const buf = 'exports.BattleAbilities = ' + es3stringify(Abilities) + ';'; fs.writeFileSync('data/abilities.js', buf); } @@ -1041,7 +1041,7 @@ process.stdout.write("Building `data/moves,items,abilities,typechart,learnsets.j *********************************************************/ { - const TypeChart = requireNoCache('../data/Pokemon-Showdown/.data-dist/typechart.js').BattleTypeChart; + const TypeChart = requireNoCache('../data/pokemon-showdown/.data-dist/typechart.js').BattleTypeChart; const buf = 'exports.BattleTypeChart = ' + es3stringify(TypeChart) + ';'; fs.writeFileSync('data/typechart.js', buf); } @@ -1051,7 +1051,7 @@ process.stdout.write("Building `data/moves,items,abilities,typechart,learnsets.j *********************************************************/ { - const Aliases = requireNoCache('../data/Pokemon-Showdown/.data-dist/aliases.js').BattleAliases; + const Aliases = requireNoCache('../data/pokemon-showdown/.data-dist/aliases.js').BattleAliases; const buf = 'exports.BattleAliases = ' + es3stringify(Aliases) + ';'; fs.writeFileSync('data/aliases.js', buf); } @@ -1061,7 +1061,7 @@ process.stdout.write("Building `data/moves,items,abilities,typechart,learnsets.j *********************************************************/ { - const FormatsData = requireNoCache('../data/Pokemon-Showdown/.data-dist/formats-data.js').BattleFormatsData; + const FormatsData = requireNoCache('../data/pokemon-showdown/.data-dist/formats-data.js').BattleFormatsData; const buf = 'exports.BattleFormatsData = ' + es3stringify(FormatsData) + ';'; fs.writeFileSync('data/formats-data.js', buf); } @@ -1071,7 +1071,7 @@ process.stdout.write("Building `data/moves,items,abilities,typechart,learnsets.j *********************************************************/ { - const Formats = requireNoCache('../data/Pokemon-Showdown/.config-dist/formats.js').Formats; + const Formats = requireNoCache('../data/pokemon-showdown/.config-dist/formats.js').Formats; const buf = 'exports.Formats = ' + es3stringify(Formats) + ';'; fs.writeFileSync('data/formats.js', buf); } @@ -1081,7 +1081,7 @@ process.stdout.write("Building `data/moves,items,abilities,typechart,learnsets.j *********************************************************/ { - const Learnsets = requireNoCache('../data/Pokemon-Showdown/.data-dist/learnsets.js').BattleLearnsets; + const Learnsets = requireNoCache('../data/pokemon-showdown/.data-dist/learnsets.js').BattleLearnsets; const buf = 'exports.BattleLearnsets = ' + es3stringify(Learnsets) + ';'; fs.writeFileSync('data/learnsets.js', buf); } diff --git a/build-tools/build-learnsets b/build-tools/build-learnsets index c6ecc41b31..2fb7fbcc7d 100755 --- a/build-tools/build-learnsets +++ b/build-tools/build-learnsets @@ -18,7 +18,7 @@ const thisFile = __filename; const thisDir = __dirname; const rootDir = path.resolve(thisDir, '..'); -const Dex = require('../data/Pokemon-Showdown/.sim-dist/dex').Dex; +const Dex = require('../data/pokemon-showdown/.sim-dist/dex').Dex; const toID = Dex.getId; function updateLearnsets(callback) { diff --git a/build-tools/build-minidex b/build-tools/build-minidex index 9b9449fac9..c527292235 100755 --- a/build-tools/build-minidex +++ b/build-tools/build-minidex @@ -6,7 +6,7 @@ const path = require("path"); process.chdir(path.resolve(__dirname, '..')); const imageSize = require('image-size'); -const Dex = require('./../data/Pokemon-Showdown/.sim-dist/dex').Dex; +const Dex = require('./../data/pokemon-showdown/.sim-dist/dex').Dex; const toID = Dex.getId; process.stdout.write("Updating animated sprite dimensions... "); diff --git a/build-tools/update b/build-tools/update index a92e2e3af4..5cb049cce5 100755 --- a/build-tools/update +++ b/build-tools/update @@ -17,6 +17,13 @@ const thisDir = __dirname; const rootDir = path.resolve(thisDir, '..'); process.chdir(rootDir); +const AUTOCONFIG_START = '/*** Begin automatically generated configuration ***/'; +const AUTOCONFIG_END = '/*** End automatically generated configuration ***/'; + +function escapeRegex(string) { + return string.replace(/[\/\*\.]/g, '\\$&'); +} + /********************************************************* * Update version number *********************************************************/ @@ -36,9 +43,27 @@ try { version += ` (${head.slice(0, 8)}${head !== origin ? `/${origin.slice(0, 8)}` : ''})`; } catch (e) {} +const routes = JSON.parse(fs.readFileSync('config/routes.json')); +const autoconfigRegex = new RegExp(`${escapeRegex(AUTOCONFIG_START)}[^]+${escapeRegex(AUTOCONFIG_END)}`); +const autoconfig = `${AUTOCONFIG_START} +Config.version = ${JSON.stringify(version)}; + +Config.routes = { + root: '${routes.root}', + client: '${routes.client}', + dex: '${routes.dex}', + replays: '${routes.replays}', + users: '${routes.users}', +}; +${AUTOCONFIG_END}`; + +// remove old automatically generated configuration and add the new one let configBuf = fs.readFileSync('config/config.js', {encoding: 'utf8'}); -configBuf = configBuf.replace(/\/\* version \*\/[^;\n]*;/, `/* version */ Config.version = ${JSON.stringify(version)};`); - +if (autoconfigRegex.test(configBuf)) { + configBuf = configBuf.replace(autoconfigRegex, autoconfig); +} else { + configBuf += autoconfig; +} fs.writeFileSync('config/config.js', configBuf); console.log("DONE"); @@ -82,31 +107,50 @@ if (!ignoreGraphics) { * Update cachebuster and News *********************************************************/ -function updateIndex() { - // add hashes to js and css files - process.stdout.write("Updating hashes... "); - let indexContents = fs.readFileSync('index.template.html', {encoding: 'utf8'}); - indexContents = indexContents.replace(/(src|href)="\/(.*?)\?[a-z0-9]*?"/g, function (a, b, c) { - let hash = Math.random(); // just in case creating the hash fails - try { - const filename = c.replace('/play.pokemonshowdown.com/', ''); - const fstr = fs.readFileSync(filename, {encoding: 'utf8'}); - hash = crypto.createHash('md5').update(fstr).digest('hex').substr(0, 8); - } catch (e) {} +const URL_REGEX = /(src|href)="\/(.*?)(\?[a-z0-9]*?)?"/g; - return b + '="/' + c + '?' + hash + '"'; - }); - let indexContents2 = fs.readFileSync('preactalpha.template.html', {encoding: 'utf8'}); - indexContents2 = indexContents2.replace(/(src|href)="\/(.*?)\?[a-z0-9]*?"/g, function (a, b, c) { +function updateURL(a, b, c, d) { + c = c.replace('/replay.pokemonshowdown.com/', '/' + routes.replays + '/'); + c = c.replace('/dex.pokemonshowdown.com/', '/' + routes.dex + '/'); + c = c.replace('/play.pokemonshowdown.com/', '/' + routes.client + '/'); + c = c.replace('/pokemonshowdown.com/', '/' + routes.root + '/'); + + if (d) { let hash = Math.random(); // just in case creating the hash fails try { - const filename = c.replace('/play.pokemonshowdown.com/', ''); + const filename = c.replace('/' + routes.client + '/', ''); const fstr = fs.readFileSync(filename, {encoding: 'utf8'}); hash = crypto.createHash('md5').update(fstr).digest('hex').substr(0, 8); } catch (e) {} return b + '="/' + c + '?' + hash + '"'; - }); + } else { + return b + '="/' + c + '"'; + } +} + +function writeFiles(indexContents, preactIndexContents, crossprotocolContents, replayEmbedContents) { + process.stdout.write("Writing new HTML files... "); + fs.writeFileSync('index.html', indexContents); + fs.writeFileSync('preactalpha.html', preactIndexContents); + fs.writeFileSync('crossprotocol.html', crossprotocolContents); + console.log("DONE"); + process.stdout.write("Writing replay-embed.js... "); + fs.writeFileSync('js/replay-embed.js', replayEmbedContents); + console.log("DONE"); +} + +function updateFiles() { + // add hashes to js and css files and rewrite URLs + process.stdout.write("Updating hashes and URLs... "); + let indexContents = fs.readFileSync('index.template.html', {encoding: 'utf8'}); + indexContents = indexContents.replace(URL_REGEX, updateURL); + let preactIndexContents = fs.readFileSync('preactalpha.template.html', {encoding: 'utf8'}); + preactIndexContents = preactIndexContents.replace(URL_REGEX, updateURL); + let crossprotocolContents = fs.readFileSync('crossprotocol.template.html', {encoding: 'utf8'}); + crossprotocolContents = crossprotocolContents.replace(URL_REGEX, updateURL); + let replayEmbedContents = fs.readFileSync('js/replay-embed.template.js', {encoding: 'utf8'}); + replayEmbedContents = replayEmbedContents.replace(/play\.pokemonshowdown\.com/g, routes.client); console.log("DONE"); // add news, only if it's actually likely to exist @@ -128,12 +172,11 @@ function updateIndex() { indexContents = indexContents.replace(//g, newsData[1]); console.log("DONE"); - process.stdout.write("Writing new `index.html` file... "); - fs.writeFileSync('index.html', indexContents); - fs.writeFileSync('preactalpha.html', indexContents2); - console.log("DONE"); + writeFiles(indexContents, preactIndexContents, crossprotocolContents, replayEmbedContents); }); + } else { + writeFiles(indexContents, preactIndexContents, crossprotocolContents, replayEmbedContents); } } -updateIndex(); +updateFiles(); diff --git a/config/config-example.inc.php b/config/config-example.inc.php index 3c0660c990..408f40e57a 100644 --- a/config/config-example.inc.php +++ b/config/config-example.inc.php @@ -2,6 +2,8 @@ mb_internal_encoding('UTF-8'); +$routes = json_decode(file_get_contents(__DIR__ . '/routes.json'), true); + $psconfig = [ 'sysops' => ['zarel'], @@ -22,6 +24,9 @@ 'prefix' => 'ps_', 'charset' => 'utf8', +// routes + 'routes' => $routes, + // CORS requests 'cors' => [ diff --git a/config/config-example.js b/config/config-example.js index 6d4c58efd6..22aee1d73b 100644 --- a/config/config-example.js +++ b/config/config-example.js @@ -117,6 +117,17 @@ Config.whitelist = [ '4cdn\\.org' ]; +// `defaultserver` specifies the server to use when the domain name in the +// address bar is `Config.routes.client`. +Config.defaultserver = { + id: 'showdown', + host: 'sim3.psim.us', + port: 443, + httpport: 8000, + altport: 80, + registered: true +}; + Config.roomsFirstOpenScript = function () { }; diff --git a/config/routes.json b/config/routes.json new file mode 100644 index 0000000000..69553f29a3 --- /dev/null +++ b/config/routes.json @@ -0,0 +1,7 @@ +{ + "root": "pokemonshowdown.com", + "client": "play.pokemonshowdown.com", + "dex": "dex.pokemonshowdown.com", + "replays": "replay.pokemonshowdown.com", + "users": "pokemonshowdown.com/users" +} diff --git a/crossdomain.php b/crossdomain.php index c336c0c899..ebc4629950 100644 --- a/crossdomain.php +++ b/crossdomain.php @@ -1,12 +1,14 @@ ; var config = ; var yourOrigin = ; -var myOrigin = 'https://play.pokemonshowdown.com'; +var myOrigin = 'https://'; function postReply (message) { if (window.parent.postMessage === postReply) return; diff --git a/crossprotocol.html b/crossprotocol.template.html similarity index 100% rename from crossprotocol.html rename to crossprotocol.template.html diff --git a/customcss.php b/customcss.php index d0c95571e9..e6fc53f205 100644 --- a/customcss.php +++ b/customcss.php @@ -2,7 +2,8 @@ ini_set('max_execution_time', 60); // 1 minute -include '../pokemonshowdown.com/config/servers.inc.php'; +require_once __DIR__ . '/../pokemonshowdown.com/config/servers.inc.php'; +require_once __DIR__ . '/config/config.inc.php'; spl_autoload_register(function ($class) { require_once('lib/css-sanitizer/'.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php'); @@ -70,11 +71,11 @@ // Parse a stylesheet from a string $parser = Parser::newFromString($curlret); $stylesheet = $parser->parseStylesheet(); - + // Apply sanitization to the stylehseet $sanitizer = StylesheetSanitizer::newDefault(); $newStylesheet = $sanitizer->sanitize( $stylesheet ); - + // Convert the sanitized stylesheet back to text $outputcss = Wikimedia\CSS\Util::stringify( $newStylesheet, [ 'minify' => true ] ); @@ -98,7 +99,7 @@ Done: was reloaded.

- Back to server management + Back to server management

- + @@ -115,7 +115,6 @@

'; + var replayDownloadButton = ' Download replay

'; // battle has ended if (this.side) { diff --git a/js/client-chat.js b/js/client-chat.js index 908c4776de..3c1f3d3c6a 100644 --- a/js/client-chat.js +++ b/js/client-chat.js @@ -912,7 +912,7 @@ var userid = toID(targets[0]); var registered = app.user.get('registered'); if (registered && registered.userid === userid) { - buffer += 'Reset W/L'; + buffer += 'Reset W/L'; } buffer += ''; self.add('|raw|' + buffer); diff --git a/js/client-ladder.js b/js/client-ladder.js index 2824de43ac..077108cbb3 100644 --- a/js/client-ladder.js +++ b/js/client-ladder.js @@ -112,7 +112,7 @@ leave: function () {}, update: function () { if (!this.curFormat) { - var buf = '

See a user\'s ranking with User lookup

' + + var buf = '

See a user\'s ranking with User lookup

' + //'

I\'m really really sorry, but as a warning: we\'re going to reset the ladder again soon to fix some more ladder bugs.

' + '

(btw if you couldn\'t tell the ladder screens aren\'t done yet; they\'ll look nicer than this once I\'m done.)

' + '

    '; diff --git a/js/client-mainmenu.js b/js/client-mainmenu.js index b31c45990b..582689ac90 100644 --- a/js/client-mainmenu.js +++ b/js/client-mainmenu.js @@ -56,7 +56,7 @@ this.$('.mainmenu').html(buf); // right menu - if (document.location.hostname === 'play.pokemonshowdown.com') { + if (document.location.hostname === Config.routes.client) { this.$('.rightmenu').html(''); } else { this.$('.rightmenu').html(''); @@ -127,7 +127,7 @@ addNews: function () { var self = this; $.ajax({ - url: "https://pokemonshowdown.com/news.json", + url: "https://" + Config.routes.root + "/news.json", dataType: "json", success: function (data) { var html = ''; diff --git a/js/client-rooms.js b/js/client-rooms.js index 5b7cd3ce24..206138caf1 100644 --- a/js/client-rooms.js +++ b/js/client-rooms.js @@ -33,9 +33,10 @@ }, joinRoomPopup: function () { app.addPopupPrompt("Room name:", "Join room", function (room) { + var routeLength = (Config.routes.client + '/').length; if (room.substr(0, 7) === 'http://') room = room.slice(7); if (room.substr(0, 8) === 'https://') room = room.slice(8); - if (room.substr(0, 25) === 'play.pokemonshowdown.com/') room = room.slice(25); + if (room.substr(0, routeLength) === Config.routes.client + '/') room = room.slice(routeLength); if (room.substr(0, 8) === 'psim.us/') room = room.slice(8); if (room.substr(0, document.location.hostname.length + 1) === document.location.hostname + '/') room = room.slice(document.location.hostname.length + 1); room = toRoomid(room); diff --git a/js/client-teambuilder.js b/js/client-teambuilder.js index 8cd1e46164..84da17e219 100644 --- a/js/client-teambuilder.js +++ b/js/client-teambuilder.js @@ -829,7 +829,7 @@ var urlprefix = "data:text/plain;base64,"; if (document.location.protocol === 'https:') { // Chrome is dumb and doesn't support data URLs in HTTPS - urlprefix = "https://play.pokemonshowdown.com/action.php?act=dlteam&team="; + urlprefix = "https://" + Config.routes.client + "/action.php?act=dlteam&team="; } var contents = Storage.exportTeam(team.team).replace(/\n/g, '\r\n'); var downloadurl = "text/plain:" + filename + ":" + urlprefix + encodeURIComponent(window.btoa(unescape(encodeURIComponent(contents)))); @@ -1538,7 +1538,7 @@ // We fetch this as 'text' and JSON.parse it ourserves in order to have consistent behavior // between the localdev CORS helper and the real jQuery.get function, which would already parse // this into an object based on the content-type header. - $.get('https://play.pokemonshowdown.com/data/sets/' + format + '.json', {}, function (data) { + $.get('https://' + Config.routes.client + '/data/sets/' + format + '.json', {}, function (data) { try { self.smogonSets[format] = JSON.parse(data); } catch (e) { diff --git a/js/client-topbar.js b/js/client-topbar.js index 5cf4c31882..cab5739782 100644 --- a/js/client-topbar.js +++ b/js/client-topbar.js @@ -737,7 +737,7 @@ buf += '

    Default

    '; buf += '
    '; - buf += ''; + buf += ''; buf += '
    '; buf += '

    Official

    '; diff --git a/js/client.js b/js/client.js index eb8da4550e..2c8f2ae7c6 100644 --- a/js/client.js +++ b/js/client.js @@ -373,7 +373,7 @@ function toId() { app.socket.close(); }, setPersistentName: function (name) { - if (location.host !== 'play.pokemonshowdown.com') return; + if (location.host !== Config.routes.client) return; $.cookie('showdown_username', (name !== undefined) ? name : this.get('name'), { expires: 14 }); @@ -409,7 +409,7 @@ function toId() { // type: 'modal' // }); } else { - if (document.location.hostname === 'play.pokemonshowdown.com' || Config.testclient) { + if (document.location.hostname === Config.routes.client || Config.testclient) { this.addRoom('rooms', null, true); } else { this.addRoom('lobby', null, true); @@ -887,7 +887,7 @@ function toId() { } else if (data === 'nonexistent' && Config.server.id && roomid.slice(0, 7) === 'battle-' && errormessage) { var replayid = roomid.slice(7); if (Config.server.id !== 'showdown') replayid = Config.server.id + '-' + replayid; - var replayLink = 'https://replay.pokemonshowdown.com/' + replayid; + var replayLink = 'https://' + Config.routes.replays + '/' + replayid; $.ajax(replayLink + '.json', {dataType: 'json'}).done(function (replay) { if (replay) { var title = BattleLog.escapeHTML(replay.p1) + ' vs. ' + BattleLog.escapeHTML(replay.p2); @@ -1304,9 +1304,9 @@ function toId() { if (this.className === 'closebutton') return; // handled elsewhere if (this.className.indexOf('minilogo') >= 0) return; // handled elsewhere if (!this.href) return; // should never happen - var isReplayLink = this.host === 'replay.pokemonshowdown.com' && Config.server.id === 'showdown'; + var isReplayLink = this.host === Config.routes.replays && Config.server.id === 'showdown'; if (( - isReplayLink || ['play.pokemonshowdown.com', 'psim.us', location.host].includes(this.host) + isReplayLink || [Config.routes.client, 'psim.us', location.host].includes(this.host) ) && this.className !== 'no-panel-intercept') { if (!e.cmdKey && !e.metaKey && !e.ctrlKey) { var target = this.pathname.substr(1); @@ -1383,7 +1383,7 @@ function toId() { this.fixedWidth = true; } } - if (!app.roomsFirstOpen && !this.down && $(window).width() >= 916 && document.location.hostname === 'play.pokemonshowdown.com') { + if (!app.roomsFirstOpen && !this.down && $(window).width() >= 916 && document.location.hostname === Config.routes.client) { this.addRoom('rooms'); } this.updateLayout(); @@ -2516,7 +2516,7 @@ function toId() { var buf = '
    '; if (avatar) buf += ''; - buf += '' + BattleLog.escapeHTML(name) + '
    '; + buf += '' + BattleLog.escapeHTML(name) + '
    '; var offline = data.rooms === false; if (data.status || offline) { var status = offline ? '(Offline)' : data.status.startsWith('!') ? data.status.slice(1) : data.status; @@ -2723,7 +2723,7 @@ function toId() { initialize: function (data) { var buf = ''; buf = '

    Your replay has been uploaded! It\'s available at:

    '; - buf += '

    https://replay.pokemonshowdown.com/' + data.id + '

    '; + buf += '

    https://' + Config.routes.replays + '/' + data.id + '

    '; buf += '

    '; this.$el.html(buf).css('max-width', 620); }, diff --git a/js/replay-embed.js b/js/replay-embed.template.js similarity index 100% rename from js/replay-embed.js rename to js/replay-embed.template.js index c72a79ba84..acd7875c92 100644 --- a/js/replay-embed.js +++ b/js/replay-embed.template.js @@ -17,11 +17,11 @@ linkStyle('https://play.pokemonshowdown.com/style/battle.css?a7'); linkStyle('https://play.pokemonshowdown.com/style/replay.css?a7'); linkStyle('https://play.pokemonshowdown.com/style/utilichart.css?a7'); +requireScript('https://play.pokemonshowdown.com/js/config.js?a7'); requireScript('https://play.pokemonshowdown.com/js/lib/jquery-1.11.0.min.js'); requireScript('https://play.pokemonshowdown.com/js/lib/lodash.compat.js'); requireScript('https://play.pokemonshowdown.com/js/lib/html-sanitizer-minified.js'); requireScript('https://play.pokemonshowdown.com/js/lib/soundmanager2-nodebug-jsmin.js'); -requireScript('https://play.pokemonshowdown.com/js/config.js?a7'); requireScript('https://play.pokemonshowdown.com/js/battledata.js?a7'); requireScript('https://play.pokemonshowdown.com/data/pokedex-mini.js?a7'); requireScript('https://play.pokemonshowdown.com/data/pokedex-mini-bw.js?a7'); diff --git a/js/storage.js b/js/storage.js index 81c23bc904..b68d724346 100644 --- a/js/storage.js +++ b/js/storage.js @@ -1,15 +1,3 @@ -Config.origindomain = 'play.pokemonshowdown.com'; -// `defaultserver` specifies the server to use when the domain name in the -// address bar is `Config.origindomain`. -Config.defaultserver = { - id: 'showdown', - host: 'sim3.psim.us', - port: 443, - httpport: 8000, - altport: 80, - registered: true -}; - function Storage() {} Storage.initialize = function () { @@ -64,7 +52,7 @@ Storage.bg = { if (!bgid) { if (location.host === 'smogtours.psim.us') { bgid = 'shaymin'; - } else if (location.host === 'play.pokemonshowdown.com') { + } else if (location.host === Config.routes.client) { bgid = ['horizon', 'ocean', 'waterfall', 'shaymin', 'charizards', 'psday'][Math.floor(Math.random() * 6)]; } else { $(document.body).css({ @@ -226,7 +214,7 @@ if (!Storage.bg.id) { // localStorage is banned, and since prefs are cached in other // places in certain cases. -Storage.origin = 'https://play.pokemonshowdown.com'; +Storage.origin = 'https://' + Config.routes.client; Storage.prefs = function (prop, value, save) { if (value === undefined) { @@ -357,9 +345,9 @@ Storage.initPrefs = function () { $(window).on('message', Storage.onMessage); - if (document.location.hostname !== Config.origindomain) { + if (document.location.hostname !== Config.routes.client) { $( - '' + '' ).appendTo('body'); setTimeout(function () { // HTTPS may be blocked @@ -397,7 +385,7 @@ Storage.onMessage = function ($e) { Config.server = JSON.parse(data.substr(1)); if (Config.server.registered && Config.server.id !== 'showdown' && Config.server.id !== 'smogtours') { var $link = $(''); $('head').append($link); } @@ -432,7 +420,7 @@ Storage.onMessage = function ($e) { // in Safari, cross-origin local storage is apparently treated as session // storage, so mirror the storage in the current origin just in case - if (document.location.hostname === Config.origindomain) { + if (document.location.hostname === Config.routes.client) { try { localStorage.setItem('showdown_teams_local', packedTeams); } catch (e) {} diff --git a/lib/dispatcher.lib.php b/lib/dispatcher.lib.php index 03deec2fe3..8e9ce48dcc 100644 --- a/lib/dispatcher.lib.php +++ b/lib/dispatcher.lib.php @@ -243,7 +243,7 @@ public function changeusername($dispatcher, &$reqData, &$out) { } public function logout($dispatcher, &$reqData, &$out) { - global $users, $curuser; + global $users, $curuser, $psconfig; if (!$_POST || !isset($reqData['userid']) || @@ -252,7 +252,7 @@ public function logout($dispatcher, &$reqData, &$out) { die; } $users->logout(); // this kills the `sid` cookie - setcookie('showdown_username', '', time()-60*60*24*2, '/', 'play.pokemonshowdown.com'); + setcookie('showdown_username', '', time()-60*60*24*2, '/', $psconfig['routes']['client']); $out['actionsuccess'] = true; } @@ -492,7 +492,7 @@ public function addfriend($dispatcher, &$reqData, &$out) { // The ] denotes that it was successful die(']A friend request has been sent to ' . $player['username'] . '!'); } - + /** * This function simply removes the friend given in the query string. */ diff --git a/lib/ntbb-ladder.lib.php b/lib/ntbb-ladder.lib.php index 76415934c0..34421f165a 100644 --- a/lib/ntbb-ladder.lib.php +++ b/lib/ntbb-ladder.lib.php @@ -158,7 +158,7 @@ function getRating(&$user, $create=false) { } $rp = $this->getrp(); $ladderdb->query( - "INSERT INTO `{$ladderdb->prefix}ladder` (`formatid`,`userid`,`username`,`rptime`) VALUES (?,?,?,?)", + "INSERT INTO `{$ladderdb->prefix}ladder` (`formatid`,`userid`,`username`,`rptime`,`rpdata`,`col1`) VALUES (?,?,?,?,'',0)", [$this->formatid, $user['userid'], $user['username'], $rp] ); $user['rating'] = array( diff --git a/lib/ntbb-session.lib.php b/lib/ntbb-session.lib.php index 7c18bd9a30..5b9c9c3026 100644 --- a/lib/ntbb-session.lib.php +++ b/lib/ntbb-session.lib.php @@ -1,12 +1,12 @@ logout(); @@ -296,31 +296,33 @@ function login($name, $pass, $timeout = false, $debug = false) { unset($curuser['nonce']); unset($curuser['passwordhash']); - // setcookie('sid', $this->scookie, ['expires' => time() + (363)*24*60*60, 'path' => '/', 'domain' => $this->cookiedomain, 'secure' => true, 'httponly' => true, 'samesite' => 'None']); + // setcookie('sid', $this->scookie, ['expires' => time() + (363)*24*60*60, 'path' => '/', 'domain' => $psconfig['routes']['root'], 'secure' => true, 'httponly' => true, 'samesite' => 'None']); $encodedcookie = rawurlencode($this->scookie); - header("Set-Cookie: sid=$encodedcookie; Max-Age=31363200; Domain={$this->cookiedomain}; Path=/; Secure; SameSite=None"); + header("Set-Cookie: sid=$encodedcookie; Max-Age=31363200; Domain={$psconfig['routes']['root']}; Path=/; Secure; SameSite=None"); return $curuser; } function updateCookie() { + global $psconfig; if (!$this->sid) { $this->sid = $this->mksid($this->sid); $this->scookie = ',,' . $this->sid; - // setcookie('sid', $this->scookie, ['expires' => time() + (363)*24*60*60, 'path' => '/', 'domain' => $this->cookiedomain, 'secure' => true, 'httponly' => true, 'samesite' => 'None']); + // setcookie('sid', $this->scookie, ['expires' => time() + (363)*24*60*60, 'path' => '/', 'domain' => $psconfig['routes']['root'], 'secure' => true, 'httponly' => true, 'samesite' => 'None']); $encodedcookie = rawurlencode($this->scookie); - header("Set-Cookie: sid=$encodedcookie; Max-Age=31363200; Domain={$this->cookiedomain}; Path=/; Secure; SameSite=None"); + header("Set-Cookie: sid=$encodedcookie; Max-Age=31363200; Domain={$psconfig['routes']['root']}; Path=/; Secure; SameSite=None"); } } function killCookie() { + global $psconfig; if ($this->sid) { $this->scookie = ',,' . $this->sid; - // setcookie('sid', $this->scookie, ['expires' => time() + (363)*24*60*60, 'path' => '/', 'domain' => $this->cookiedomain, 'secure' => true, 'httponly' => true, 'samesite' => 'None']); + // setcookie('sid', $this->scookie, ['expires' => time() + (363)*24*60*60, 'path' => '/', 'domain' => $psconfig['routes']['root'], 'secure' => true, 'httponly' => true, 'samesite' => 'None']); $encodedcookie = rawurlencode($this->scookie); - header("Set-Cookie: sid=$encodedcookie; Max-Age=31363200; Domain={$this->cookiedomain}; Path=/; Secure; SameSite=None"); + header("Set-Cookie: sid=$encodedcookie; Max-Age=31363200; Domain={$psconfig['routes']['root']}; Path=/; Secure; SameSite=None"); } else { - // setcookie('sid', '', ['expires' => time() - 60*60*24*2, 'path' => '/', 'domain' => $this->cookiedomain, 'secure' => true, 'httponly' => true, 'samesite' => 'None']); - header("Set-Cookie: sid=; Max-Age=0; Domain={$this->cookiedomain}; Path=/; Secure; SameSite=None"); + // setcookie('sid', '', ['expires' => time() - 60*60*24*2, 'path' => '/', 'domain' => $psconfig['routes']['root'], 'secure' => true, 'httponly' => true, 'samesite' => 'None']); + header("Set-Cookie: sid=; Max-Age=0; Domain={$psconfig['routes']['root']}; Path=/; Secure; SameSite=None"); } } diff --git a/preactalpha.template.html b/preactalpha.template.html index f7ed8d64ba..bd86a2724f 100644 --- a/preactalpha.template.html +++ b/preactalpha.template.html @@ -51,6 +51,7 @@

    \n'; buf += '\n'; return buf; } diff --git a/src/battle-searchresults.tsx b/src/battle-searchresults.tsx index e5461c2e67..c4f41bc9bd 100644 --- a/src/battle-searchresults.tsx +++ b/src/battle-searchresults.tsx @@ -8,7 +8,7 @@ */ class PSSearchResults extends preact.Component<{search: DexSearch}> { - readonly URL_ROOT = '//dex.pokemonshowdown.com/'; + readonly URL_ROOT = `//${Config.routes.dex}/`; renderPokemonSortRow() { const search = this.props.search; diff --git a/src/client-connection.ts b/src/client-connection.ts index 23538723de..62d210785a 100644 --- a/src/client-connection.ts +++ b/src/client-connection.ts @@ -57,7 +57,7 @@ const PSLoginServer = new class { query(data: {}, callback: (res: {[k: string]: any} | null) => void) { let url = '/~~' + PS.server.id + '/action.php'; if (location.pathname.endsWith('.html')) { - url = 'https://play.pokemonshowdown.com' + url; + url = 'https://' + Config.routes.client + url; // @ts-ignore if (typeof POKEMON_SHOWDOWN_TESTCLIENT_KEY === 'string') { // @ts-ignore diff --git a/src/client-core.ts b/src/client-core.ts index 82b958c907..d63fbd5146 100644 --- a/src/client-core.ts +++ b/src/client-core.ts @@ -82,10 +82,7 @@ if (!window.console) { *********************************************************************/ // PS's model classes are defined here -const PSURL = ( - (document.location!.protocol !== 'http:' ? 'https:' : '') + - '//play.pokemonshowdown.com/' -); +const PSURL = `${document.location!.protocol !== 'http:' ? 'https:' : ''}//${Config.routes.client}/`; class PSSubscription { observable: PSModel | PSStreamModel; @@ -215,7 +212,7 @@ const PSBackground = new class extends PSStreamModel { if (!bgid) { if (location.host === 'smogtours.psim.us') { bgid = 'shaymin'; - } else if (location.host === 'play.pokemonshowdown.com') { + } else if (location.host === Config.routes.client) { const bgs = ['horizon', 'ocean', 'waterfall', 'shaymin', 'charizards']; bgid = bgs[Math.floor(Math.random() * 5)]; if (bgid === this.curId) bgid = bgs[Math.floor(Math.random() * 5)]; diff --git a/src/client-main.ts b/src/client-main.ts index 5b23fbb017..67e7c43903 100644 --- a/src/client-main.ts +++ b/src/client-main.ts @@ -59,7 +59,7 @@ class PSPrefs extends PSStreamModel { storageEngine: 'localStorage' | 'iframeLocalStorage' | '' = ''; storage: {[k: string]: any} = {}; - readonly origin = 'https://play.pokemonshowdown.com'; + readonly origin = `https://${Config.routes.client}`; constructor() { super(); @@ -222,7 +222,7 @@ class PSTeams extends PSStreamModel<'team' | 'format'> { this.byKey[team.key] = team; } unpackOldBuffer(buffer: string) { - alert("Your team storage format is too old for PS. You'll need to upgrade it at https://play.pokemonshowdown.com/recoverteams.html"); + alert(`Your team storage format is too old for PS. You'll need to upgrade it at https://${Config.routes.client}/recoverteams.html`); this.list = []; return; } @@ -298,13 +298,13 @@ interface PSGroup { } class PSServer { - id = 'showdown'; - host = 'sim3.psim.us'; - port = 8000; - altport = 80; - registered = true; + id = Config.defaultserver.id; + host = Config.defaultserver.host; + port = Config.defaultserver.port; + altport = Config.defaultserver.altport; + registered = Config.defaultserver.registered; prefix = '/showdown'; - protocol: 'http' | 'https' = 'https'; + protocol: 'http' | 'https' = Config.defaultserver.https ? 'https' : 'http'; groups: {[symbol: string]: PSGroup} = { '~': { name: "Administrator (~)", diff --git a/src/panel-mainmenu.tsx b/src/panel-mainmenu.tsx index 2c159355f6..b2aa2a9106 100644 --- a/src/panel-mainmenu.tsx +++ b/src/panel-mainmenu.tsx @@ -306,7 +306,7 @@ class MainMenuPanel extends PSRoomPanel { }

    - +
    Bear with us as we freak out.

    @@ -349,10 +349,10 @@ class MainMenuPanel extends PSRoomPanel { @@ -414,12 +414,12 @@ class TeamDropdown extends preact.Component<{format: string}> {
    Random team - - - - - - + + + + + +
    ; diff --git a/src/panel-topbar.tsx b/src/panel-topbar.tsx index 8f1c1546a2..9806fe8c59 100644 --- a/src/panel-topbar.tsx +++ b/src/panel-topbar.tsx @@ -88,8 +88,8 @@ class PSHeader extends preact.Component<{style: {}}> { return