/*! * Copyright (c) 2015, Salesforce.com, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of Salesforce.com nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ 'use strict'; var fs = require('fs'); var assert = require('assert'); var punycode = require('punycode'); fs.readFile('./public-suffix.txt', 'utf8', function(err,string) { if (err) { throw err; } var lines = string.split("\n"); process.nextTick(function() { processList(lines); }); }); var index = {}; var COMMENT = new RegExp('//.+'); function processList(lines) { while (lines.length) { var line = lines.shift(); line = line.replace(COMMENT,'').trim(); if (!line) { continue; } addToIndex(index,line); } pubSufTest(); var w = fs.createWriteStream('./lib/pubsuffix.js',{ flags: 'w', encoding: 'utf8', mode: parseInt('644',8) }); w.on('end', process.exit); w.write("/****************************************************\n"); w.write(" * AUTOMATICALLY GENERATED by generate-pubsuffix.js *\n"); w.write(" * DO NOT EDIT! *\n"); w.write(" ****************************************************/\n\n"); w.write('"use strict";\n\n'); w.write("var punycode = require('punycode');\n\n"); w.write("module.exports.getPublicSuffix = "); w.write(getPublicSuffix.toString()); w.write(";\n\n"); w.write("// The following generated structure is used under the MPL version 1.1\n"); w.write("// See public-suffix.txt for more information\n\n"); w.write("var index = module.exports.index = Object.freeze(\n"); w.write(JSON.stringify(index)); w.write(");\n\n"); w.write("// END of automatically generated file\n"); w.end(); } function addToIndex(index,line) { var prefix = ''; if (line.replace(/^(!|\*\.)/)) { prefix = RegExp.$1; line = line.slice(prefix.length); } line = prefix + punycode.toASCII(line); if (line.substr(0,1) == '!') { index[line.substr(1)] = false; } else { index[line] = true; } } // include the licence in the function since it gets written to pubsuffix.js function getPublicSuffix(domain) { /*! * Copyright (c) 2015, Salesforce.com, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of Salesforce.com nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ if (!domain) { return null; } if (domain.match(/^\./)) { return null; } var asciiDomain = punycode.toASCII(domain); var converted = false; if (asciiDomain !== domain) { domain = asciiDomain; converted = true; } if (index[domain]) { return null; } domain = domain.toLowerCase(); var parts = domain.split('.').reverse(); var suffix = ''; var suffixLen = 0; for (var i=0; i suffixLen) { var publicSuffix = parts.slice(0,suffixLen+1).reverse().join('.'); return converted ? punycode.toUnicode(publicSuffix) : publicSuffix; } return null; } function checkPublicSuffix(give,get) { var got = getPublicSuffix(give); assert.equal(got, get, give+' should be '+(get==null?'NULL':get)+' but got '+got); } // pubSufTest() was converted to JavaScript from http://mxr.mozilla.org/mozilla-central/source/netwerk/test/unit/data/test_psl.txt?raw=1 function pubSufTest() { // For this function-scope and this function-scope ONLY: // Any copyright is dedicated to the Public Domain. // http://creativecommons.org/publicdomain/zero/1.0/ // NULL input. checkPublicSuffix(null, null); // Mixed case. checkPublicSuffix('COM', null); checkPublicSuffix('example.COM', 'example.com'); checkPublicSuffix('WwW.example.COM', 'example.com'); // Leading dot. checkPublicSuffix('.com', null); checkPublicSuffix('.example', null); checkPublicSuffix('.example.com', null); checkPublicSuffix('.example.example', null); // Unlisted TLD. checkPublicSuffix('example', null); checkPublicSuffix('example.example', 'example.example'); checkPublicSuffix('b.example.example', 'example.example'); checkPublicSuffix('a.b.example.example', 'example.example'); // Listed, but non-Internet, TLD. //checkPublicSuffix('local', null); //checkPublicSuffix('example.local', null); //checkPublicSuffix('b.example.local', null); //checkPublicSuffix('a.b.example.local', null); // TLD with only 1 rule. checkPublicSuffix('biz', null); checkPublicSuffix('domain.biz', 'domain.biz'); checkPublicSuffix('b.domain.biz', 'domain.biz'); checkPublicSuffix('a.b.domain.biz', 'domain.biz'); // TLD with some 2-level rules. checkPublicSuffix('com', null); checkPublicSuffix('example.com', 'example.com'); checkPublicSuffix('b.example.com', 'example.com'); checkPublicSuffix('a.b.example.com', 'example.com'); checkPublicSuffix('uk.com', null); checkPublicSuffix('example.uk.com', 'example.uk.com'); checkPublicSuffix('b.example.uk.com', 'example.uk.com'); checkPublicSuffix('a.b.example.uk.com', 'example.uk.com'); checkPublicSuffix('test.ac', 'test.ac'); // TLD with only 1 (wildcard) rule. checkPublicSuffix('cy', null); checkPublicSuffix('c.cy', null); checkPublicSuffix('b.c.cy', 'b.c.cy'); checkPublicSuffix('a.b.c.cy', 'b.c.cy'); // More complex TLD. checkPublicSuffix('jp', null); checkPublicSuffix('test.jp', 'test.jp'); checkPublicSuffix('www.test.jp', 'test.jp'); checkPublicSuffix('ac.jp', null); checkPublicSuffix('test.ac.jp', 'test.ac.jp'); checkPublicSuffix('www.test.ac.jp', 'test.ac.jp'); checkPublicSuffix('kyoto.jp', null); checkPublicSuffix('test.kyoto.jp', 'test.kyoto.jp'); checkPublicSuffix('ide.kyoto.jp', null); checkPublicSuffix('b.ide.kyoto.jp', 'b.ide.kyoto.jp'); checkPublicSuffix('a.b.ide.kyoto.jp', 'b.ide.kyoto.jp'); checkPublicSuffix('c.kobe.jp', null); checkPublicSuffix('b.c.kobe.jp', 'b.c.kobe.jp'); checkPublicSuffix('a.b.c.kobe.jp', 'b.c.kobe.jp'); checkPublicSuffix('city.kobe.jp', 'city.kobe.jp'); checkPublicSuffix('www.city.kobe.jp', 'city.kobe.jp'); // TLD with a wildcard rule and exceptions. checkPublicSuffix('ck', null); checkPublicSuffix('test.ck', null); checkPublicSuffix('b.test.ck', 'b.test.ck'); checkPublicSuffix('a.b.test.ck', 'b.test.ck'); checkPublicSuffix('www.ck', 'www.ck'); checkPublicSuffix('www.www.ck', 'www.ck'); // US K12. checkPublicSuffix('us', null); checkPublicSuffix('test.us', 'test.us'); checkPublicSuffix('www.test.us', 'test.us'); checkPublicSuffix('ak.us', null); checkPublicSuffix('test.ak.us', 'test.ak.us'); checkPublicSuffix('www.test.ak.us', 'test.ak.us'); checkPublicSuffix('k12.ak.us', null); checkPublicSuffix('test.k12.ak.us', 'test.k12.ak.us'); checkPublicSuffix('www.test.k12.ak.us', 'test.k12.ak.us'); // IDN labels. checkPublicSuffix('食狮.com.cn', '食狮.com.cn'); checkPublicSuffix('食狮.公司.cn', '食狮.公司.cn'); checkPublicSuffix('www.食狮.公司.cn', '食狮.公司.cn'); checkPublicSuffix('shishi.公司.cn', 'shishi.公司.cn'); checkPublicSuffix('公司.cn', null); checkPublicSuffix('食狮.中国', '食狮.中国'); checkPublicSuffix('www.食狮.中国', '食狮.中国'); checkPublicSuffix('shishi.中国', 'shishi.中国'); checkPublicSuffix('中国', null); // Same as above, but punycoded. checkPublicSuffix('xn--85x722f.com.cn', 'xn--85x722f.com.cn'); checkPublicSuffix('xn--85x722f.xn--55qx5d.cn', 'xn--85x722f.xn--55qx5d.cn'); checkPublicSuffix('www.xn--85x722f.xn--55qx5d.cn', 'xn--85x722f.xn--55qx5d.cn'); checkPublicSuffix('shishi.xn--55qx5d.cn', 'shishi.xn--55qx5d.cn'); checkPublicSuffix('xn--55qx5d.cn', null); checkPublicSuffix('xn--85x722f.xn--fiqs8s', 'xn--85x722f.xn--fiqs8s'); checkPublicSuffix('www.xn--85x722f.xn--fiqs8s', 'xn--85x722f.xn--fiqs8s'); checkPublicSuffix('shishi.xn--fiqs8s', 'shishi.xn--fiqs8s'); checkPublicSuffix('xn--fiqs8s', null); }