[
  {
    "path": ".gitignore",
    "content": "._*\nnode_modules\nsrc/home/assets/bundle.debug.js\nwww/assets/bundle.*.js"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n  // 使用 IntelliSense 了解相关属性。 \n  // 悬停以查看现有属性的描述。\n  // 欲了解更多信息，请访问: https://go.microsoft.com/fwlink/?linkid=830387\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"name\": \"clang build and debug active file\",\n      \"type\": \"cppdbg\",\n      \"request\": \"launch\",\n      \"program\": \"${fileDirname}/${fileBasenameNoExtension}\",\n      \"args\": [],\n      \"stopAtEntry\": false,\n      \"cwd\": \"${workspaceFolder}\",\n      \"environment\": [],\n      \"externalConsole\": false,\n      \"MIMode\": \"lldb\",\n      \"preLaunchTask\": \"clang build active file\"\n    }\n  ]\n}"
  },
  {
    "path": ".vscode/tasks.json",
    "content": "{\n  \"tasks\": [\n    {\n      \"type\": \"shell\",\n      \"label\": \"clang build active file\",\n      \"command\": \"/usr/bin/clang\",\n      \"args\": [\n        \"-g\",\n        \"${file}\",\n        \"-o\",\n        \"${fileDirname}/${fileBasenameNoExtension}\"\n      ],\n      \"options\": {\n        \"cwd\": \"/usr/bin\"\n      }\n    }\n  ],\n  \"version\": \"2.0.0\"\n}"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 EtherDream\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "JsProxy 浏览器端程序\n\n\n# 修改配置\n\n修改 `www/conf.js` 配置，发布 `www` 目录即可。\n\n\n## TODO\n\n* 增加网络错误重试、优先选择空闲节点功能\n\n* 在 SW 中替换 HTML 的 URL 属性，并支持流模式\n\n* CDN 文件使用 brotli 压缩\n\n* 使用 AST 修改 JS 代码\n\n* 动态页面压缩传输（反模板引擎，只传输变量，模板本身存储在 CDN）\n\n* 使用更多的免费图床作为 CDN 资源存储，并支持 Hash 校验\n\n* 计算程序使用 wasm 实现\n\n* 支持 blob/data/javascript 协议\n\n* 增加 qos 功能，优先满足资料查询网站流量\n\n* 改进同源策略的安全性，增加部分 API 的授权界面\n\n* 重新设计首页，增加更多功能\n\n* 完整的测试案例\n\n\n# 已知问题\n\n* 文件下载对话框取消后 SW 仍在下载（fetch.signal 的 onabort 未触发，可能是浏览器 BUG）\n\n* Chrome 图片无法保存\n\n* 非 UTF8 编码的 JS 会出现乱码（MIME 未指定 charset 的情况下出现）\n\n* Google 登陆页无法下一步\n\n* Google reCAPTCHA 无法执行\n\n* Google Maps 切换到卫星地图后卡死\n\n* iOS Safari 无法播放 Youtube 视频\n\n* twitter 在 Chrome 普通模式下无法登陆，但隐身模式可以\n\n* twitter iframe 经常加载不出来\n\n* SVG 脚本没有处理\n\n* Youtube 视频全屏播放会卡住\n\n* twitch.tv 首页报错（JS 代码修改导致错误，需要在 AST 层面修改）"
  },
  {
    "path": "src/home/404.html",
    "content": "<!--\n  该页面用于安装 Service Worker\n  用户首次访问时，无论请求哪个资源（包括首页），都返回该页面\n  该页面尽可能精简，兼容所有浏览器\n-->\n<html>\n<head>\n  <meta charset=\"utf-8\">\n</head>\n<body id=\"t\">\n  <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100%\" height=\"100%\" viewBox=\"0 0 100 100\" preserveAspectRatio=\"xMidYMid\" fill=\"none\"><circle cx=\"50\" cy=\"50\" r=\"25.944\" stroke=\"#93dbe9\"><animate attributeName=\"r\" calcMode=\"spline\" values=\"0;40\" keyTimes=\"0;1\" dur=\"1\" keySplines=\"0 0.2 0.8 1\" begin=\"-0.5s\" repeatCount=\"indefinite\" stroke-width=\"2\"/><animate attributeName=\"opacity\" calcMode=\"spline\" values=\"1;0\" keyTimes=\"0;1\" dur=\"1\" keySplines=\"0.2 0 0.8 1\" begin=\"-0.5s\" repeatCount=\"indefinite\" stroke-width=\"2\"/></circle><circle cx=\"50\" cy=\"50\" r=\"40\" stroke=\"#689cc5\"><animate attributeName=\"r\" calcMode=\"spline\" values=\"0;40\" keyTimes=\"0;1\" dur=\"1\" keySplines=\"0 0.2 0.8 1\" begin=\"0s\" repeatCount=\"indefinite\" stroke-width=\"2\"/><animate attributeName=\"opacity\" calcMode=\"spline\" values=\"1;0\" keyTimes=\"0;1\" dur=\"1\" keySplines=\"0.2 0 0.8 1\" begin=\"0s\" repeatCount=\"indefinite\" stroke-width=\"2\"/></circle></svg>\n  <script>\n  function reload() {\n    // 设置最小刷新间隔，防止出错时不停刷新\n    var curr = Date.now()\n    try {\n      var last = +sessionStorage._ts || 0\n      sessionStorage._ts = curr\n      if (curr - last < 100) {\n        return setTimeout(reload, 5000)\n      }\n    } catch (err) {\n    }\n    location.reload()\n  }\n\n  function onfail(err) {\n    showErr(err.message)\n  }\n\n  function showErr(str) {\n    t.innerHTML = str\n  }\n\n  function getRootPath() {\n    // https://a.com/ -> /\n    // https://a.com/index.html -> /\n    // https://a.com/path/to/ -> /path/to/\n    // https://a.com/path/to -> /path/to/\n    // https://a.com/path/to/index.html -> /path/to/\n    return location.pathname\n      .replace(/\\/-+https?:.+/, '')\n      .replace(/\\w+\\.\\w+$/, '')\n      .replace(/\\/*$/, '/')\n  }\n\n  function main() {\n    if (!self.isSecureContext) {\n      showErr('本程序需要 HTTPS 站点')\n      return\n    }\n    if (!self.ReadableStream) {\n      showErr('请使用最新的 HTML5 浏览器')\n      return\n    }\n    var sw = navigator.serviceWorker\n    if (!sw) {\n      var ua = navigator.userAgent\n      if (/Firefox/.test(ua)) {\n        showErr('本网站不支持 FireFox 隐身模式')\n      }\n      else if (/iPhone|iPad/.test(ua)) {\n        showErr('iOS 上请使用 Safari 浏览器')\n      }\n      return\n    }\n    sw\n      .register(getRootPath() + 'sw.js')\n      .then(reload)\n      .catch(onfail)\n  }\n  main()\n  </script>\n</body>\n</html>"
  },
  {
    "path": "src/home/README.md",
    "content": "## 404.html\n\n该页面用于安装 Service Worker。\n\n因为本项目只有一个 404.html，所以访问任意路径都会触发该页面。通过该页面安装 Service Worker 然后自动刷新，后续所有流量都可被 Service Worker 接管。\n\n\n## sw.js\n\nService Worker 脚本。\n\n虽然 Web 标准规定 Service Worker 脚本必须和站点同源，但是 JS 可通过 `importScripts` 加载站外脚本。因此可将主体代码部署在 CDN，该脚本仅仅作为一个加载器。\n\n\n## build.sh\n\n压缩当前目录 404.html 到 ../../www/404.html\n\n\n## conf.js\n\n配置文件。该文件首次运行时动态加载\n\n\n## assets\n\n该目录存放静态资源，可部署到 CDN。"
  },
  {
    "path": "src/home/assets/cors_v1.txt",
    "content": "# HTTP 返回头存在 access-control-allow-origin: * 的站点，不走代理直接连接\n# 收集了部分，实验中...\n\n# google\nssl.google-analytics.com\n\n# [public]\ncdn.jsdelivr.net\nunpkg.com\ncdnjs.cloudflare.com\ncdn.bootcss.com\nuse.fontawesome.com\nfast.fonts.net\nscript.hotjar.com\n\n# github\ngithub.githubassets.com\navatars0.githubusercontent.com\navatars1.githubusercontent.com\navatars2.githubusercontent.com\navatars3.githubusercontent.com\n\ndesktop.github.com\n\n# flickr\nstatus.flickr.net\n\n# ali\nat.alicdn.com\nimg.alicdn.com\ng.alicdn.com\ni.alicdn.com\natanx.alicdn.com\nwwc.alicdn.com\ngw.alicdn.com\nassets.alicdn.com\naeis.alicdn.com\natanx.alicdn.com\nhudong.alicdn.com\ngma.alicdn.com\n\nsc01.alicdn.com\nsc02.alicdn.com\nsc03.alicdn.com\nsc04.alicdn.com\n\ncbu01.alicdn.com\ncbu02.alicdn.com\ncbu03.alicdn.com\ncbu04.alicdn.com\n\n# baidu\n# img*.bdimg.com\nimg0.bdimg.com\nimg1.bdimg.com\nimg2.bdimg.com\nimg3.bdimg.com\nimg4.bdimg.com\nimg5.bdimg.com\n\nwebmap0.bdimg.com\nwebmap1.bdimg.com\niknowpc.bdimg.com\nbkssl.bdimg.com\nbaikebcs.bdimg.com\ngh.bdstatic.com\n\n# qq\n3gimg.qq.com\ncombo.b.qq.com\n\n# taotiao\nimages.taboola.com\nimages.taboola.com.cn\nimages-dup.taboola.com\n\n# zhihu\nstatic.zhihu.com\npic1.zhimg.com\npic2.zhimg.com\npic3.zhimg.com\npic4.zhimg.com\npic5.zhimg.com\npic7.zhimg.com\n\n# jd\nimg11.360buyimg.com\n\n# jianshu\nupload.jianshu.io\nupload-images.jianshu.io\ncdn2.jianshu.io\n\n# 163\nurswebzj.nosdn.127.net\nstatic.ws.126.net\nimg1.cache.netease.com\nimg2.cache.netease.com\nimg3.cache.netease.com\nimg4.cache.netease.com\nimg5.cache.netease.com\nimg6.cache.netease.com\n\n# sina\njs.t.sinajs.cn\nmjs.sinaimg.cn\nh5.sinaimg.cn\n\n# sohu\n0d077ef9e74d8.cdn.sohucs.com\n39d0825d09f05.cdn.sohucs.com\n5b0988e595225.cdn.sohucs.com\ncaaceed4aeaf2.cdn.sohucs.com\n\nimg01.sogoucdn.com\nimg02.sogoucdn.com\nimg03.sogoucdn.com\nimg04.sogoucdn.com\nimg05.sogoucdn.com\n\n# hupu\nw1.hoopchina.com.cn\nw2.hoopchina.com.cn\nw3.hoopchina.com.cn\nw4.hoopchina.com.cn\nshihuo.hupucdn.com\n\n# uc\nimage.uc.cn\n\n# ...\nstatic.cnodejs.org\nstatic2.cnodejs.org\n2b.zol-img.com.cn\nimg.pconline.com.cn\nangular.cn\nimg1.dxycdn.com\ncdn.kastatic.org\nstatic.geetest.com\ncdn.registerdisney.go.com\nsecure-us.imrworldwide.com\nimg1.doubanio.com\nqnwww2.autoimg.cn\nqnwww3.autoimg.cn\ns.autoimg.cn\n\nhb.imgix.net\nmain.qcloudimg.com\nvz-cdn2.contentabc.com\ntwemoji.maxcdn.com\nfgn.cdn.serverable.com\n\ns1.hdslb.com\ns2.hdslb.com\ns3.hdslb.com\n\n# cnblogs\ncommon.cnblogs.com\nmathjax.cnblogs.com\n\n# csdn\ncsdnimg.cn\ng.csdnimg.cn\nimg-ads.csdn.net\nimg-bss.csdn.net\nimg-blog.csdn.net\n\n# ...\nstatic.geekbang.org\nstatic001.infoq.cn\nstatic.docs.com\ncdn1.developermedia.com\ncdn2.developermedia.com\ncdn.optimizely.com\ncdn.ampproject.org\n\ncamshowverse.to\nstatic.camshowhub-cdn.to\n\nxqimg.imedao.com\nxavatar.imedao.com\n\n# ???\nimg-l3.xvideos-cdn.com\nstatic-egc.xvideos-cdn.com\nimg-hw.xvideos-cdn.com\nimg-hw.xnxx-cdn.com\nstatic-egc.xnxx-cdn.com\ndi.phncdn.com\ncv.phncdn.com\nroomimg.stream.highwebmedia.com\nw3.cdn.anvato.net"
  },
  {
    "path": "src/home/assets/index_v3.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <title>Page Sandbox</title>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0\">\n  <base target=\"_blank\">\n  <style>\n    body {\n      padding: 0 0.5em;\n    }\n    .box {\n      margin-top: 1em;\n    }\n    #txtURL {\n      width: 100%;\n      height: 2em;\n      text-indent: 0.5em;\n      padding: 0.25em 0;\n    }\n    #btnGo {\n      width: 100%;\n      font-size: 1.5em;\n    }\n    #list a {\n      margin: 1em;\n    }\n  </style>\n</head>\n<body>\n  <div class=\"box\">\n    <input id=\"txtURL\" type=\"text\" value=\"www.google.com\" autofocus>\n  </div>\n  <div class=\"box\">\n    <button id=\"btnGo\">Go</button>\n  </div>\n  <div class=\"box\">\n    <span>切换线路:</span>\n    <select id=\"selNode\"></select>\n  </div>\n  <div class=\"box\" id=\"list\">\n  </div>\n  <script>\n    const PAGE_CONF_SET = 110\n    const PAGE_CONF_GET = 111\n\n    const SW_CONF_RETURN = 112\n    const SW_CONF_CHANGE = 113\n\n    const PAGE_READY_CHECK = 200\n    const SW_READY = 201\n\n    const sw = navigator.serviceWorker\n\n\n    sw.addEventListener('message', onSwMsg)\n    sendMsgToSw(PAGE_READY_CHECK)\n\n    btnGo.onclick = function() {\n      const text = txtURL.value.trim()\n      if (text) {\n        const url = './-----' + text\n        open(url, '_blank', 'noopener,noreferrer')\n      }\n    }\n    txtURL.onkeypress = function(e) {\n      if (e.keyCode === 13) {\n        btnGo.onclick()\n      }\n    }\n    txtURL.setSelectionRange(0, txtURL.value.length)\n\n\n    function onSwMsg(e) {\n      const [cmd, msg] = e.data\n\n      switch (cmd) {\n      case SW_CONF_RETURN:\n        conf = msg\n        showConf()\n        break\n\n      case SW_CONF_CHANGE:\n        conf = msg\n        updateSelected()\n        break\n\n      case SW_READY:\n        console.log('sw ready')\n        showIcons()\n        sendMsgToSw(PAGE_CONF_GET)\n        break\n      }\n    }\n\n    function onSwFail(err) {\n      txtURL.value = err\n    }\n\n    selNode.onchange = function() {\n      const item = this.options[this.selectedIndex]\n      const node = item.value\n      conf.node_default = node\n      sendMsgToSw(PAGE_CONF_SET, conf)\n    }\n\n    function sendMsgToSw(cmd, val) {\n      const ctl = sw.controller\n      if (!ctl) {\n        console.log('ctl is null')\n        return\n      }\n      ctl.postMessage([cmd, val])\n    }\n\n    const SITE_LIST = [\n      ['google', ''],\n      ['youtube', ''],\n      ['twitter', 'twitter.com/google'],\n      ['flickr', ''],\n      ['quora', 'www.quora.com/topic/JavaScript-programming-language'],\n      ['twitch', 'www.twitch.tv/'],\n      ['reddit', ''],\n      ['wiki', 'zh.wikipedia.org/'],\n      ['gist', 'gist.github.com/'],\n      ['facebook', 'facebook.com/Google/'],\n      ['blogger', ''],\n    ]\n\n    function showIcons() {\n      list.innerHTML = SITE_LIST.map(v => {\n        let [id, url] = v\n        url = url || `www.${id}.com/`\n        return `\\\n<a rel=\"noopener noreferrer\" href=./-----https://${url}>\\\n<img width=128 height=128 src=__sys__/assets/ico/${id}.png></a>`\n      }).join('')\n    }\n\n    function addNodeItem(id, text) {\n      const optEl = document.createElement('option')\n      optEl.id = '--' + id\n      optEl.text = text\n      optEl.value = id\n      selNode.appendChild(optEl)\n    }\n\n    function updateSelected() {\n      const id = conf.node_default\n      const item = document.getElementById('--' + id)\n      if (item) {\n        item.selected = true\n      } else {\n        console.warn('unknown node:', id)\n      }\n    }\n\n    function showConf() {\n      for (const [id, node] of Object.entries(conf.node_map)) {\n        if (!node.hidden) {\n          addNodeItem(id, node.label)\n        }\n      }\n      updateSelected()\n    }\n  </script>\n</body>\n</html>"
  },
  {
    "path": "src/home/build.sh",
    "content": "# 压缩 404.html\nhtml-minifier \\\n  --collapse-whitespace \\\n  --remove-comments \\\n  --remove-redundant-attributes \\\n  --remove-script-type-attributes \\\n  --remove-tag-whitespace \\\n  --use-short-doctype \\\n  --remove-attribute-quotes \\\n  --minify-css true \\\n  --minify-js '{\"toplevel\": true, \"ie8\": true}' \\\n  -o ../../www/404.html \\\n  404.html\n"
  },
  {
    "path": "src/home/conf.js",
    "content": "jsproxy_config({\n  // 当前配置的版本（记录在日志中，用于排查问题）\n  // 每次修改配置，该值需要增加，否则不会生效。\n  // 默认每隔 5 分钟自动下载配置，若想立即验证，可通过隐私模式访问。\n  ver: '105',\n\n  // 通过 CDN 加速常用网站的静态资源（实验中）\n  static_boost: {\n    enable: true,\n    ver: 56\n  },\n\n  // 节点配置\n  node_map: {\n    'demo-hk': {\n      label: '演示服务-香港节点',\n      lines: {\n        // 主机:权重\n        'node-aliyun-hk-0.etherdream.com:8443': 1,\n        'node-aliyun-hk-1.etherdream.com:8443': 1,\n        'node-aliyun-hk-2.etherdream.com:8443': 1,\n      }\n    },\n    'demo-sg': {\n      label: '演示服务-新加坡节点',\n      lines: {\n        'node-aliyun-sg.etherdream.com:8443': 1,\n      },\n    },\n    'demo-la': {\n      label: '演示服务-洛杉矶节点',\n      lines: {\n        'node-bwh-la.etherdream.com:8443': 1,\n      },\n    },\n    'mysite': {\n      label: '当前站点',\n      lines: {\n        [location.host]: 1,\n      }\n    },\n    // 该节点用于加载大体积的静态资源\n    'cfworker': {\n      label: '',\n      hidden: true,\n      lines: {\n        'node-cfworker-2.etherdream.com': 1,\n      }\n    }\n  },\n\n  /**\n   * 默认节点\n   */\n  node_default: 'demo-hk',\n\n  /**\n   * 加速节点\n   */\n  node_acc: 'cfworker',\n\n  /**\n   * 静态资源 CDN 地址\n   * 用于加速 `assets` 目录中的资源访问\n   */\n  // assets_cdn: 'https://cdn.jsdelivr.net/gh/zjcqoo/zjcqoo.github.io@master/assets/',\n\n  // 本地测试时打开，否则访问的是线上的\n  assets_cdn: 'assets/',\n\n  // 首页路径\n  index_path: 'index_v3.html',\n\n  // 支持 CORS 的站点列表（实验中...）\n  direct_host_list: 'cors_v1.txt',\n\n  /**\n   * 自定义注入页面的 HTML\n   */\n  inject_html: '<!-- custom html -->',\n\n  /**\n   * URL 自定义处理（设计中）\n   */\n  url_handler: {\n    'https://www.baidu.com/img/baidu_resultlogo@2.png': {\n      replace: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png'\n    },\n    'https://www.pornhub.com/': {\n      redir: 'https://php.net/'\n    },\n    'http://haha.com/': {\n      content: 'Hello World'\n    },\n  }\n})"
  },
  {
    "path": "src/home/sw.js",
    "content": "jsproxy_config=x=>{__CONF__=x;importScripts(__FILE__=x.assets_cdn+'bundle.debug.js')};importScripts('conf.js')"
  },
  {
    "path": "src/proxy/.eslintrc.json",
    "content": "{\n    \"env\": {\n        \"browser\": true,\n        \"es6\": true,\n        \"serviceworker\": true\n    },\n    \"extends\": \"eslint:recommended\",\n    \"globals\": {\n        \"Atomics\": \"readonly\",\n        \"SharedArrayBuffer\": \"readonly\"\n    },\n    \"parserOptions\": {\n        \"ecmaVersion\": 2017,\n        \"sourceType\": \"module\"\n    },\n    \"rules\": {\n        \"no-console\": \"warn\",\n        \"no-empty\": \"warn\",\n        \"no-unused-vars\": \"warn\",\n        \"no-debugger\": \"warn\",\n        \"no-constant-condition\": \"warn\"\n    }\n}"
  },
  {
    "path": "src/proxy/.package-lock.json",
    "content": "{\n  \"name\": \"jsproxy-client\",\n  \"version\": \"0.0.1\",\n  \"lockfileVersion\": 1,\n  \"requires\": true,\n  \"dependencies\": {\n    \"@babel/code-frame\": {\n      \"version\": \"7.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz\",\n      \"integrity\": \"sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==\",\n      \"dev\": true,\n      \"requires\": {\n        \"@babel/highlight\": \"^7.0.0\"\n      }\n    },\n    \"@babel/highlight\": {\n      \"version\": \"7.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz\",\n      \"integrity\": \"sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==\",\n      \"dev\": true,\n      \"requires\": {\n        \"chalk\": \"^2.0.0\",\n        \"esutils\": \"^2.0.2\",\n        \"js-tokens\": \"^4.0.0\"\n      }\n    },\n    \"acorn\": {\n      \"version\": \"6.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz\",\n      \"integrity\": \"sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==\",\n      \"dev\": true\n    },\n    \"acorn-jsx\": {\n      \"version\": \"5.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz\",\n      \"integrity\": \"sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==\",\n      \"dev\": true\n    },\n    \"ajv\": {\n      \"version\": \"6.10.0\",\n      \"resolved\": \"https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz\",\n      \"integrity\": \"sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==\",\n      \"dev\": true,\n      \"requires\": {\n        \"fast-deep-equal\": \"^2.0.1\",\n        \"fast-json-stable-stringify\": \"^2.0.0\",\n        \"json-schema-traverse\": \"^0.4.1\",\n        \"uri-js\": \"^4.2.2\"\n      }\n    },\n    \"ansi-escapes\": {\n      \"version\": \"3.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz\",\n      \"integrity\": \"sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==\",\n      \"dev\": true\n    },\n    \"ansi-regex\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz\",\n      \"integrity\": \"sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=\",\n      \"dev\": true\n    },\n    \"ansi-styles\": {\n      \"version\": \"3.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz\",\n      \"integrity\": \"sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==\",\n      \"dev\": true,\n      \"requires\": {\n        \"color-convert\": \"^1.9.0\"\n      }\n    },\n    \"argparse\": {\n      \"version\": \"1.0.10\",\n      \"resolved\": \"https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz\",\n      \"integrity\": \"sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==\",\n      \"dev\": true,\n      \"requires\": {\n        \"sprintf-js\": \"~1.0.2\"\n      }\n    },\n    \"astral-regex\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz\",\n      \"integrity\": \"sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==\",\n      \"dev\": true\n    },\n    \"balanced-match\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz\",\n      \"integrity\": \"sha1-ibTRmasr7kneFk6gK4nORi1xt2c=\",\n      \"dev\": true\n    },\n    \"brace-expansion\": {\n      \"version\": \"1.1.11\",\n      \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz\",\n      \"integrity\": \"sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==\",\n      \"dev\": true,\n      \"requires\": {\n        \"balanced-match\": \"^1.0.0\",\n        \"concat-map\": \"0.0.1\"\n      }\n    },\n    \"callsites\": {\n      \"version\": \"3.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz\",\n      \"integrity\": \"sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==\",\n      \"dev\": true\n    },\n    \"chalk\": {\n      \"version\": \"2.4.2\",\n      \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz\",\n      \"integrity\": \"sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==\",\n      \"dev\": true,\n      \"requires\": {\n        \"ansi-styles\": \"^3.2.1\",\n        \"escape-string-regexp\": \"^1.0.5\",\n        \"supports-color\": \"^5.3.0\"\n      }\n    },\n    \"chardet\": {\n      \"version\": \"0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz\",\n      \"integrity\": \"sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==\",\n      \"dev\": true\n    },\n    \"cli-cursor\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz\",\n      \"integrity\": \"sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=\",\n      \"dev\": true,\n      \"requires\": {\n        \"restore-cursor\": \"^2.0.0\"\n      }\n    },\n    \"cli-width\": {\n      \"version\": \"2.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz\",\n      \"integrity\": \"sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=\",\n      \"dev\": true\n    },\n    \"color-convert\": {\n      \"version\": \"1.9.3\",\n      \"resolved\": \"https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz\",\n      \"integrity\": \"sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==\",\n      \"dev\": true,\n      \"requires\": {\n        \"color-name\": \"1.1.3\"\n      }\n    },\n    \"color-name\": {\n      \"version\": \"1.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz\",\n      \"integrity\": \"sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=\",\n      \"dev\": true\n    },\n    \"concat-map\": {\n      \"version\": \"0.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz\",\n      \"integrity\": \"sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=\",\n      \"dev\": true\n    },\n    \"cross-spawn\": {\n      \"version\": \"6.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz\",\n      \"integrity\": \"sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==\",\n      \"dev\": true,\n      \"requires\": {\n        \"nice-try\": \"^1.0.4\",\n        \"path-key\": \"^2.0.1\",\n        \"semver\": \"^5.5.0\",\n        \"shebang-command\": \"^1.2.0\",\n        \"which\": \"^1.2.9\"\n      }\n    },\n    \"debug\": {\n      \"version\": \"4.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/debug/-/debug-4.1.1.tgz\",\n      \"integrity\": \"sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==\",\n      \"dev\": true,\n      \"requires\": {\n        \"ms\": \"^2.1.1\"\n      }\n    },\n    \"deep-is\": {\n      \"version\": \"0.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz\",\n      \"integrity\": \"sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=\",\n      \"dev\": true\n    },\n    \"doctrine\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz\",\n      \"integrity\": \"sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==\",\n      \"dev\": true,\n      \"requires\": {\n        \"esutils\": \"^2.0.2\"\n      }\n    },\n    \"emoji-regex\": {\n      \"version\": \"7.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz\",\n      \"integrity\": \"sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==\",\n      \"dev\": true\n    },\n    \"escape-string-regexp\": {\n      \"version\": \"1.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz\",\n      \"integrity\": \"sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=\",\n      \"dev\": true\n    },\n    \"eslint\": {\n      \"version\": \"5.16.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz\",\n      \"integrity\": \"sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==\",\n      \"dev\": true,\n      \"requires\": {\n        \"@babel/code-frame\": \"^7.0.0\",\n        \"ajv\": \"^6.9.1\",\n        \"chalk\": \"^2.1.0\",\n        \"cross-spawn\": \"^6.0.5\",\n        \"debug\": \"^4.0.1\",\n        \"doctrine\": \"^3.0.0\",\n        \"eslint-scope\": \"^4.0.3\",\n        \"eslint-utils\": \"^1.3.1\",\n        \"eslint-visitor-keys\": \"^1.0.0\",\n        \"espree\": \"^5.0.1\",\n        \"esquery\": \"^1.0.1\",\n        \"esutils\": \"^2.0.2\",\n        \"file-entry-cache\": \"^5.0.1\",\n        \"functional-red-black-tree\": \"^1.0.1\",\n        \"glob\": \"^7.1.2\",\n        \"globals\": \"^11.7.0\",\n        \"ignore\": \"^4.0.6\",\n        \"import-fresh\": \"^3.0.0\",\n        \"imurmurhash\": \"^0.1.4\",\n        \"inquirer\": \"^6.2.2\",\n        \"js-yaml\": \"^3.13.0\",\n        \"json-stable-stringify-without-jsonify\": \"^1.0.1\",\n        \"levn\": \"^0.3.0\",\n        \"lodash\": \"^4.17.11\",\n        \"minimatch\": \"^3.0.4\",\n        \"mkdirp\": \"^0.5.1\",\n        \"natural-compare\": \"^1.4.0\",\n        \"optionator\": \"^0.8.2\",\n        \"path-is-inside\": \"^1.0.2\",\n        \"progress\": \"^2.0.0\",\n        \"regexpp\": \"^2.0.1\",\n        \"semver\": \"^5.5.1\",\n        \"strip-ansi\": \"^4.0.0\",\n        \"strip-json-comments\": \"^2.0.1\",\n        \"table\": \"^5.2.3\",\n        \"text-table\": \"^0.2.0\"\n      }\n    },\n    \"eslint-scope\": {\n      \"version\": \"4.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz\",\n      \"integrity\": \"sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==\",\n      \"dev\": true,\n      \"requires\": {\n        \"esrecurse\": \"^4.1.0\",\n        \"estraverse\": \"^4.1.1\"\n      }\n    },\n    \"eslint-utils\": {\n      \"version\": \"1.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz\",\n      \"integrity\": \"sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==\",\n      \"dev\": true\n    },\n    \"eslint-visitor-keys\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz\",\n      \"integrity\": \"sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==\",\n      \"dev\": true\n    },\n    \"espree\": {\n      \"version\": \"5.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/espree/-/espree-5.0.1.tgz\",\n      \"integrity\": \"sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==\",\n      \"dev\": true,\n      \"requires\": {\n        \"acorn\": \"^6.0.7\",\n        \"acorn-jsx\": \"^5.0.0\",\n        \"eslint-visitor-keys\": \"^1.0.0\"\n      }\n    },\n    \"esprima\": {\n      \"version\": \"4.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz\",\n      \"integrity\": \"sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==\",\n      \"dev\": true\n    },\n    \"esquery\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz\",\n      \"integrity\": \"sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==\",\n      \"dev\": true,\n      \"requires\": {\n        \"estraverse\": \"^4.0.0\"\n      }\n    },\n    \"esrecurse\": {\n      \"version\": \"4.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz\",\n      \"integrity\": \"sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==\",\n      \"dev\": true,\n      \"requires\": {\n        \"estraverse\": \"^4.1.0\"\n      }\n    },\n    \"estraverse\": {\n      \"version\": \"4.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz\",\n      \"integrity\": \"sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=\",\n      \"dev\": true\n    },\n    \"esutils\": {\n      \"version\": \"2.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz\",\n      \"integrity\": \"sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=\",\n      \"dev\": true\n    },\n    \"external-editor\": {\n      \"version\": \"3.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz\",\n      \"integrity\": \"sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==\",\n      \"dev\": true,\n      \"requires\": {\n        \"chardet\": \"^0.7.0\",\n        \"iconv-lite\": \"^0.4.24\",\n        \"tmp\": \"^0.0.33\"\n      }\n    },\n    \"fast-deep-equal\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz\",\n      \"integrity\": \"sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=\",\n      \"dev\": true\n    },\n    \"fast-json-stable-stringify\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz\",\n      \"integrity\": \"sha1-1RQsDK7msRifh9OnYREGT4bIu/I=\",\n      \"dev\": true\n    },\n    \"fast-levenshtein\": {\n      \"version\": \"2.0.6\",\n      \"resolved\": \"https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz\",\n      \"integrity\": \"sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=\",\n      \"dev\": true\n    },\n    \"figures\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/figures/-/figures-2.0.0.tgz\",\n      \"integrity\": \"sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=\",\n      \"dev\": true,\n      \"requires\": {\n        \"escape-string-regexp\": \"^1.0.5\"\n      }\n    },\n    \"file-entry-cache\": {\n      \"version\": \"5.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz\",\n      \"integrity\": \"sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==\",\n      \"dev\": true,\n      \"requires\": {\n        \"flat-cache\": \"^2.0.1\"\n      }\n    },\n    \"flat-cache\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz\",\n      \"integrity\": \"sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==\",\n      \"dev\": true,\n      \"requires\": {\n        \"flatted\": \"^2.0.0\",\n        \"rimraf\": \"2.6.3\",\n        \"write\": \"1.0.3\"\n      }\n    },\n    \"flatted\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz\",\n      \"integrity\": \"sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==\",\n      \"dev\": true\n    },\n    \"fs.realpath\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz\",\n      \"integrity\": \"sha1-FQStJSMVjKpA20onh8sBQRmU6k8=\",\n      \"dev\": true\n    },\n    \"functional-red-black-tree\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz\",\n      \"integrity\": \"sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=\",\n      \"dev\": true\n    },\n    \"glob\": {\n      \"version\": \"7.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/glob/-/glob-7.1.3.tgz\",\n      \"integrity\": \"sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==\",\n      \"dev\": true,\n      \"requires\": {\n        \"fs.realpath\": \"^1.0.0\",\n        \"inflight\": \"^1.0.4\",\n        \"inherits\": \"2\",\n        \"minimatch\": \"^3.0.4\",\n        \"once\": \"^1.3.0\",\n        \"path-is-absolute\": \"^1.0.0\"\n      }\n    },\n    \"globals\": {\n      \"version\": \"11.12.0\",\n      \"resolved\": \"https://registry.npmjs.org/globals/-/globals-11.12.0.tgz\",\n      \"integrity\": \"sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==\",\n      \"dev\": true\n    },\n    \"has-flag\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz\",\n      \"integrity\": \"sha1-tdRU3CGZriJWmfNGfloH87lVuv0=\",\n      \"dev\": true\n    },\n    \"iconv-lite\": {\n      \"version\": \"0.4.24\",\n      \"resolved\": \"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz\",\n      \"integrity\": \"sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==\",\n      \"dev\": true,\n      \"requires\": {\n        \"safer-buffer\": \">= 2.1.2 < 3\"\n      }\n    },\n    \"ignore\": {\n      \"version\": \"4.0.6\",\n      \"resolved\": \"https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz\",\n      \"integrity\": \"sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==\",\n      \"dev\": true\n    },\n    \"import-fresh\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz\",\n      \"integrity\": \"sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==\",\n      \"dev\": true,\n      \"requires\": {\n        \"parent-module\": \"^1.0.0\",\n        \"resolve-from\": \"^4.0.0\"\n      }\n    },\n    \"imurmurhash\": {\n      \"version\": \"0.1.4\",\n      \"resolved\": \"https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz\",\n      \"integrity\": \"sha1-khi5srkoojixPcT7a21XbyMUU+o=\",\n      \"dev\": true\n    },\n    \"inflight\": {\n      \"version\": \"1.0.6\",\n      \"resolved\": \"https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz\",\n      \"integrity\": \"sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=\",\n      \"dev\": true,\n      \"requires\": {\n        \"once\": \"^1.3.0\",\n        \"wrappy\": \"1\"\n      }\n    },\n    \"inherits\": {\n      \"version\": \"2.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz\",\n      \"integrity\": \"sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=\",\n      \"dev\": true\n    },\n    \"inquirer\": {\n      \"version\": \"6.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz\",\n      \"integrity\": \"sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==\",\n      \"dev\": true,\n      \"requires\": {\n        \"ansi-escapes\": \"^3.2.0\",\n        \"chalk\": \"^2.4.2\",\n        \"cli-cursor\": \"^2.1.0\",\n        \"cli-width\": \"^2.0.0\",\n        \"external-editor\": \"^3.0.3\",\n        \"figures\": \"^2.0.0\",\n        \"lodash\": \"^4.17.11\",\n        \"mute-stream\": \"0.0.7\",\n        \"run-async\": \"^2.2.0\",\n        \"rxjs\": \"^6.4.0\",\n        \"string-width\": \"^2.1.0\",\n        \"strip-ansi\": \"^5.1.0\",\n        \"through\": \"^2.3.6\"\n      },\n      \"dependencies\": {\n        \"ansi-regex\": {\n          \"version\": \"4.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz\",\n          \"integrity\": \"sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==\",\n          \"dev\": true\n        },\n        \"strip-ansi\": {\n          \"version\": \"5.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz\",\n          \"integrity\": \"sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==\",\n          \"dev\": true,\n          \"requires\": {\n            \"ansi-regex\": \"^4.1.0\"\n          }\n        }\n      }\n    },\n    \"is-fullwidth-code-point\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz\",\n      \"integrity\": \"sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=\",\n      \"dev\": true\n    },\n    \"is-promise\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz\",\n      \"integrity\": \"sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=\",\n      \"dev\": true\n    },\n    \"isexe\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz\",\n      \"integrity\": \"sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=\",\n      \"dev\": true\n    },\n    \"js-tokens\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz\",\n      \"integrity\": \"sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==\",\n      \"dev\": true\n    },\n    \"js-yaml\": {\n      \"version\": \"3.13.1\",\n      \"resolved\": \"https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz\",\n      \"integrity\": \"sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==\",\n      \"dev\": true,\n      \"requires\": {\n        \"argparse\": \"^1.0.7\",\n        \"esprima\": \"^4.0.0\"\n      }\n    },\n    \"json-schema-traverse\": {\n      \"version\": \"0.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz\",\n      \"integrity\": \"sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==\",\n      \"dev\": true\n    },\n    \"json-stable-stringify-without-jsonify\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz\",\n      \"integrity\": \"sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=\",\n      \"dev\": true\n    },\n    \"levn\": {\n      \"version\": \"0.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/levn/-/levn-0.3.0.tgz\",\n      \"integrity\": \"sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=\",\n      \"dev\": true,\n      \"requires\": {\n        \"prelude-ls\": \"~1.1.2\",\n        \"type-check\": \"~0.3.2\"\n      }\n    },\n    \"lodash\": {\n      \"version\": \"4.17.11\",\n      \"resolved\": \"https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz\",\n      \"integrity\": \"sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==\",\n      \"dev\": true\n    },\n    \"mimic-fn\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz\",\n      \"integrity\": \"sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==\",\n      \"dev\": true\n    },\n    \"minimatch\": {\n      \"version\": \"3.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz\",\n      \"integrity\": \"sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==\",\n      \"dev\": true,\n      \"requires\": {\n        \"brace-expansion\": \"^1.1.7\"\n      }\n    },\n    \"minimist\": {\n      \"version\": \"0.0.8\",\n      \"resolved\": \"https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz\",\n      \"integrity\": \"sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=\",\n      \"dev\": true\n    },\n    \"mkdirp\": {\n      \"version\": \"0.5.1\",\n      \"resolved\": \"https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz\",\n      \"integrity\": \"sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=\",\n      \"dev\": true,\n      \"requires\": {\n        \"minimist\": \"0.0.8\"\n      }\n    },\n    \"ms\": {\n      \"version\": \"2.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/ms/-/ms-2.1.1.tgz\",\n      \"integrity\": \"sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==\",\n      \"dev\": true\n    },\n    \"mute-stream\": {\n      \"version\": \"0.0.7\",\n      \"resolved\": \"https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz\",\n      \"integrity\": \"sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=\",\n      \"dev\": true\n    },\n    \"natural-compare\": {\n      \"version\": \"1.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz\",\n      \"integrity\": \"sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=\",\n      \"dev\": true\n    },\n    \"nice-try\": {\n      \"version\": \"1.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz\",\n      \"integrity\": \"sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==\",\n      \"dev\": true\n    },\n    \"once\": {\n      \"version\": \"1.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/once/-/once-1.4.0.tgz\",\n      \"integrity\": \"sha1-WDsap3WWHUsROsF9nFC6753Xa9E=\",\n      \"dev\": true,\n      \"requires\": {\n        \"wrappy\": \"1\"\n      }\n    },\n    \"onetime\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz\",\n      \"integrity\": \"sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=\",\n      \"dev\": true,\n      \"requires\": {\n        \"mimic-fn\": \"^1.0.0\"\n      }\n    },\n    \"optionator\": {\n      \"version\": \"0.8.2\",\n      \"resolved\": \"https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz\",\n      \"integrity\": \"sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=\",\n      \"dev\": true,\n      \"requires\": {\n        \"deep-is\": \"~0.1.3\",\n        \"fast-levenshtein\": \"~2.0.4\",\n        \"levn\": \"~0.3.0\",\n        \"prelude-ls\": \"~1.1.2\",\n        \"type-check\": \"~0.3.2\",\n        \"wordwrap\": \"~1.0.0\"\n      }\n    },\n    \"os-tmpdir\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz\",\n      \"integrity\": \"sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=\",\n      \"dev\": true\n    },\n    \"parent-module\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz\",\n      \"integrity\": \"sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==\",\n      \"dev\": true,\n      \"requires\": {\n        \"callsites\": \"^3.0.0\"\n      }\n    },\n    \"path-is-absolute\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz\",\n      \"integrity\": \"sha1-F0uSaHNVNP+8es5r9TpanhtcX18=\",\n      \"dev\": true\n    },\n    \"path-is-inside\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz\",\n      \"integrity\": \"sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=\",\n      \"dev\": true\n    },\n    \"path-key\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz\",\n      \"integrity\": \"sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=\",\n      \"dev\": true\n    },\n    \"prelude-ls\": {\n      \"version\": \"1.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz\",\n      \"integrity\": \"sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=\",\n      \"dev\": true\n    },\n    \"progress\": {\n      \"version\": \"2.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/progress/-/progress-2.0.3.tgz\",\n      \"integrity\": \"sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==\",\n      \"dev\": true\n    },\n    \"punycode\": {\n      \"version\": \"2.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz\",\n      \"integrity\": \"sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==\",\n      \"dev\": true\n    },\n    \"regexpp\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz\",\n      \"integrity\": \"sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==\",\n      \"dev\": true\n    },\n    \"resolve-from\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz\",\n      \"integrity\": \"sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==\",\n      \"dev\": true\n    },\n    \"restore-cursor\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz\",\n      \"integrity\": \"sha1-n37ih/gv0ybU/RYpI9YhKe7g368=\",\n      \"dev\": true,\n      \"requires\": {\n        \"onetime\": \"^2.0.0\",\n        \"signal-exit\": \"^3.0.2\"\n      }\n    },\n    \"rimraf\": {\n      \"version\": \"2.6.3\",\n      \"resolved\": \"https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz\",\n      \"integrity\": \"sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==\",\n      \"dev\": true,\n      \"requires\": {\n        \"glob\": \"^7.1.3\"\n      }\n    },\n    \"run-async\": {\n      \"version\": \"2.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz\",\n      \"integrity\": \"sha1-A3GrSuC91yDUFm19/aZP96RFpsA=\",\n      \"dev\": true,\n      \"requires\": {\n        \"is-promise\": \"^2.1.0\"\n      }\n    },\n    \"rxjs\": {\n      \"version\": \"6.5.1\",\n      \"resolved\": \"https://registry.npmjs.org/rxjs/-/rxjs-6.5.1.tgz\",\n      \"integrity\": \"sha512-y0j31WJc83wPu31vS1VlAFW5JGrnGC+j+TtGAa1fRQphy48+fDYiDmX8tjGloToEsMkxnouOg/1IzXGKkJnZMg==\",\n      \"dev\": true,\n      \"requires\": {\n        \"tslib\": \"^1.9.0\"\n      }\n    },\n    \"safer-buffer\": {\n      \"version\": \"2.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz\",\n      \"integrity\": \"sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==\",\n      \"dev\": true\n    },\n    \"semver\": {\n      \"version\": \"5.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/semver/-/semver-5.7.0.tgz\",\n      \"integrity\": \"sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==\",\n      \"dev\": true\n    },\n    \"shebang-command\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz\",\n      \"integrity\": \"sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=\",\n      \"dev\": true,\n      \"requires\": {\n        \"shebang-regex\": \"^1.0.0\"\n      }\n    },\n    \"shebang-regex\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz\",\n      \"integrity\": \"sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=\",\n      \"dev\": true\n    },\n    \"signal-exit\": {\n      \"version\": \"3.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz\",\n      \"integrity\": \"sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=\",\n      \"dev\": true\n    },\n    \"slice-ansi\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz\",\n      \"integrity\": \"sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==\",\n      \"dev\": true,\n      \"requires\": {\n        \"ansi-styles\": \"^3.2.0\",\n        \"astral-regex\": \"^1.0.0\",\n        \"is-fullwidth-code-point\": \"^2.0.0\"\n      }\n    },\n    \"sprintf-js\": {\n      \"version\": \"1.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz\",\n      \"integrity\": \"sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=\",\n      \"dev\": true\n    },\n    \"string-width\": {\n      \"version\": \"2.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz\",\n      \"integrity\": \"sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==\",\n      \"dev\": true,\n      \"requires\": {\n        \"is-fullwidth-code-point\": \"^2.0.0\",\n        \"strip-ansi\": \"^4.0.0\"\n      }\n    },\n    \"strip-ansi\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz\",\n      \"integrity\": \"sha1-qEeQIusaw2iocTibY1JixQXuNo8=\",\n      \"dev\": true,\n      \"requires\": {\n        \"ansi-regex\": \"^3.0.0\"\n      }\n    },\n    \"strip-json-comments\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz\",\n      \"integrity\": \"sha1-PFMZQukIwml8DsNEhYwobHygpgo=\",\n      \"dev\": true\n    },\n    \"supports-color\": {\n      \"version\": \"5.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz\",\n      \"integrity\": \"sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==\",\n      \"dev\": true,\n      \"requires\": {\n        \"has-flag\": \"^3.0.0\"\n      }\n    },\n    \"table\": {\n      \"version\": \"5.2.3\",\n      \"resolved\": \"https://registry.npmjs.org/table/-/table-5.2.3.tgz\",\n      \"integrity\": \"sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==\",\n      \"dev\": true,\n      \"requires\": {\n        \"ajv\": \"^6.9.1\",\n        \"lodash\": \"^4.17.11\",\n        \"slice-ansi\": \"^2.1.0\",\n        \"string-width\": \"^3.0.0\"\n      },\n      \"dependencies\": {\n        \"ansi-regex\": {\n          \"version\": \"4.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz\",\n          \"integrity\": \"sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==\",\n          \"dev\": true\n        },\n        \"string-width\": {\n          \"version\": \"3.1.0\",\n          \"resolved\": \"https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz\",\n          \"integrity\": \"sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==\",\n          \"dev\": true,\n          \"requires\": {\n            \"emoji-regex\": \"^7.0.1\",\n            \"is-fullwidth-code-point\": \"^2.0.0\",\n            \"strip-ansi\": \"^5.1.0\"\n          }\n        },\n        \"strip-ansi\": {\n          \"version\": \"5.2.0\",\n          \"resolved\": \"https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz\",\n          \"integrity\": \"sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==\",\n          \"dev\": true,\n          \"requires\": {\n            \"ansi-regex\": \"^4.1.0\"\n          }\n        }\n      }\n    },\n    \"text-table\": {\n      \"version\": \"0.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz\",\n      \"integrity\": \"sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=\",\n      \"dev\": true\n    },\n    \"through\": {\n      \"version\": \"2.3.8\",\n      \"resolved\": \"https://registry.npmjs.org/through/-/through-2.3.8.tgz\",\n      \"integrity\": \"sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=\",\n      \"dev\": true\n    },\n    \"tmp\": {\n      \"version\": \"0.0.33\",\n      \"resolved\": \"https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz\",\n      \"integrity\": \"sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==\",\n      \"dev\": true,\n      \"requires\": {\n        \"os-tmpdir\": \"~1.0.2\"\n      }\n    },\n    \"tslib\": {\n      \"version\": \"1.9.3\",\n      \"resolved\": \"https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz\",\n      \"integrity\": \"sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==\",\n      \"dev\": true\n    },\n    \"type-check\": {\n      \"version\": \"0.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz\",\n      \"integrity\": \"sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=\",\n      \"dev\": true,\n      \"requires\": {\n        \"prelude-ls\": \"~1.1.2\"\n      }\n    },\n    \"uri-js\": {\n      \"version\": \"4.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz\",\n      \"integrity\": \"sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==\",\n      \"dev\": true,\n      \"requires\": {\n        \"punycode\": \"^2.1.0\"\n      }\n    },\n    \"which\": {\n      \"version\": \"1.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/which/-/which-1.3.1.tgz\",\n      \"integrity\": \"sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==\",\n      \"dev\": true,\n      \"requires\": {\n        \"isexe\": \"^2.0.0\"\n      }\n    },\n    \"wordwrap\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz\",\n      \"integrity\": \"sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=\",\n      \"dev\": true\n    },\n    \"wrappy\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz\",\n      \"integrity\": \"sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=\",\n      \"dev\": true\n    },\n    \"write\": {\n      \"version\": \"1.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/write/-/write-1.0.3.tgz\",\n      \"integrity\": \"sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==\",\n      \"dev\": true,\n      \"requires\": {\n        \"mkdirp\": \"^0.5.1\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/proxy/.package.json",
    "content": "{\n  \"name\": \"jsproxy-client\",\n  \"version\": \"0.0.1\",\n  \"description\": \"\",\n  \"main\": \"boot.js\",\n  \"directories\": {\n    \"lib\": \"lib\"\n  },\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"keywords\": [],\n  \"author\": \"EtherDream\",\n  \"license\": \"MIT\",\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"eslint\": \"^5.16.0\"\n  }\n}\n"
  },
  {
    "path": "src/proxy/README.md",
    "content": "浏览器脚本的源文件\n\n# src\n\n源文件目录\n\n\n# debug.sh\n\n开发模式。\n\n# release.sh\n\n发布脚本。\n"
  },
  {
    "path": "src/proxy/debug.sh",
    "content": "webpack \\\n  --o \"../home/assets/bundle.debug.js\" \\\n  --mode development -w"
  },
  {
    "path": "src/proxy/gen-tld/README.md",
    "content": "顶级域名后缀生成脚本\n\n# 生成\n\n```bash\nnode gen\n```\n\n# TODO\n\n该列表较大，导致最终 JS 增加上百 KB 的体积。\n\n未考虑 `!` 和 `*.` 开头的域名。\n\n未来考虑将结果保存为单独的文件，JS 运行时动态加载。"
  },
  {
    "path": "src/proxy/gen-tld/gen.js",
    "content": "const https = require('https')\nconst fs = require('fs')\nconst {stdout} = process\n\nconst SRC_PATH = 'https://publicsuffix.org/list/effective_tld_names.dat'\nconst DST_PATH = '../src/tld-data.js'\n\n\nstdout.write('loading')\n\nhttps.get(SRC_PATH, res => {\n  let str = ''\n  res.on('data', s => {\n    str += s\n    stdout.write('.');\n  }).on('end', _ => {\n    proc(str)\n  }).setEncoding('utf8')\n})\n\n\nfunction proc(str) {\n  const list = str\n    .split('\\n')\n    .filter(v => v)\n    .filter(v => !v.startsWith('//'))\n    .filter(v => !v.startsWith('!'))\n    .map(v => v.replace('*.', ''))\n    .sort((a, b) => a > b ? 1 : -1)\n    .join(',')\n\n  const result = `\\\n// THIS FILE WAS GENERATED BY './tools/tld/gen.js'\nexport default '${list}'\n`\n  fs.writeFileSync(DST_PATH, result)\n\n  console.log('\\nok')\n}\n"
  },
  {
    "path": "src/proxy/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"checkJs\": true,\n    \"lib\": [\"webworker\", \"dom\", \"es2017\"],\n    \"target\": \"es2017\"\n  },\n  \"include\": [\n    \"src/*\"\n  ]\n}"
  },
  {
    "path": "src/proxy/release.sh",
    "content": "DST=../../www/assets\n\nrm $DST/bundle.*.js\n\nwebpack \\\n  --o \"$DST/bundle.[hash:8].js\" \\\n  --mode production\n\ncd $DST\n\nfor i in bundle.*.js; do\n  printf \"\\\njsproxy_config=\\\nx=>{\\\n__CONF__=x;\\\nimportScripts(__FILE__=x.assets_cdn+'$i')\\\n};\\\nimportScripts('conf.js')\\\n\" > ../sw.js\ndone"
  },
  {
    "path": "src/proxy/src/cdn.js",
    "content": "import * as util from './util'\n\n// 暂时先用 jsdelivr 试验。之后换成速度很快、容量更大的免费图床\nconst CDN = 'https://cdn.jsdelivr.net/npm/jsproxy-cache-01@0.0.'\n\nlet mCurVer = -1\n\n/** @type {Map<number, number>} */\nlet mUrlHashVerMap = new Map()\n\n/** @type {Set<string>} */\nlet mDirectHostSet = new Set()\n\n\nasync function loadDirectList(conf) {\n  const url = conf.assets_cdn + conf.direct_host_list\n  const res = await fetch(url)\n  const txt = await res.text()\n\n  for (const host of txt.split('\\n')) {\n    if (host && host[0] !== '#') {\n      mDirectHostSet.add(host)\n    }\n  }\n}\n\nasync function loadStaticList(conf) {\n  const info = conf.static_boost\n  if (!info || !info.enable) {\n    return\n  }\n  const latest = info.ver\n  if (mCurVer >= latest) {\n    return\n  }\n  mCurVer = latest\n  console.log('[jsproxy] cdn cache ver:', latest)\n\n  const res = await fetch(CDN + latest + '/full')\n  const buf = await res.arrayBuffer()\n  const u32 = new Uint32Array(buf)\n\n  let p = 0\n  for (let ver = 0; ver <= latest; ver++) {\n    const num = u32[p++]\n\n    for (let i = 0; i < num; i++) {\n      const urlHash = u32[p++]\n      mUrlHashVerMap.set(urlHash, ver)\n    }\n  }\n}\n\n\nexport function setConf(conf) {\n  return Promise.all([\n    loadStaticList(conf),\n    loadDirectList(conf),\n  ])\n}\n\n/**\n * @param {string} host \n */\nexport function isDirectHost(host) {\n  return mDirectHostSet.has(host)\n}\n\n\n/**\n * @param {string} url \n */\nexport async function proxyDirect(url) {\n  try {\n    const res = await fetch(url, {\n      referrerPolicy: 'no-referrer',\n    })\n    const {status} = res\n    if (status === 200 || status === 206) {\n      return res\n    }\n    console.warn('direct status:', status, url)\n  } catch (err) {\n    console.warn('direct fail:', url)\n  }\n}\n\n\n/**\n * @param {number} urlHash \n */\nexport function getFileVer(urlHash) {\n  return mUrlHashVerMap.get(urlHash)\n}\n\n\n/**\n * @param {number} urlHash \n * @param {number} urlVer \n */\nasync function proxyStaticMain(urlHash, urlVer) {\n  const hashHex = util.numToHex(urlHash, 8)\n  const res = await fetch(CDN + urlVer + '/' + hashHex + '.txt')\n  if (res.status !== 200) {\n    throw 'bad status: ' + res.status\n  }\n  const buf = await res.arrayBuffer()\n  const b = new Uint8Array(buf)\n\n  const hdrLen = b[0] << 8 | b[1]\n  const hdrBuf = b.subarray(2, 2 + hdrLen)\n  const hdrStr = util.bytesToStr(hdrBuf)\n  const hdrObj = JSON.parse(hdrStr)\n\n  const body = b.subarray(2 + hdrLen)\n  hdrObj['date'] = new Date().toUTCString()\n\n  return new Response(body, {\n    headers: hdrObj\n  })\n}\n\n\n/**\n * @param {number} urlHash \n * @param {number} urlVer \n */\nexport async function proxyStatic(urlHash, urlVer) {\n  // TODO: 使用多个 CDN\n  try {\n    return await proxyStaticMain(urlHash, urlVer)\n  } catch(err) {\n    console.warn('cdn fail:', err)\n  }\n}\n"
  },
  {
    "path": "src/proxy/src/client.js",
    "content": "import * as urlx from './urlx.js'\nimport * as route from './route.js'\nimport * as env from './env.js'\nimport * as hook from './hook.js'\nimport {createFakeLoc} from './fakeloc.js'\nimport {createStorage} from './storage.js'\n\n\nconst {\n  apply,\n  construct,\n} = Reflect\n\n\n/**\n * Hook 页面和 Worker 相同的 API\n * \n * @param {Window} global WindowOrWorkerGlobalScope\n * @param {string} origin \n */\nexport function init(global, origin) {\n  // lockNative(win)\n\n  // hook Storage API\n  createStorage(global, origin)\n\n  // hook Location API\n  const fakeLoc = createFakeLoc(global)\n\n  // hook Performance API\n  const perfProto = global['PerformanceEntry'].prototype\n  hook.prop(perfProto, 'name',\n    getter => function() {\n      const val = getter.call(this)\n      if (/^https?:/.test(val)) {\n        return urlx.decUrlStrAbs(val)\n      }\n      return val\n    }\n  )\n\n\n  // hook AJAX API\n  const xhrProto = global['XMLHttpRequest'].prototype\n  hook.func(xhrProto, 'open', oldFn => function(_0, url) {\n    if (url) {\n      arguments[1] = urlx.encUrlStrRel(url, this)\n    }\n    return apply(oldFn, this, arguments)\n  })\n\n  hook.prop(xhrProto, 'responseURL',\n    getter => function(oldFn) {\n      const val = getter.call(this)\n      return urlx.decUrlStrRel(val, this)\n    }\n  )\n\n\n  hook.func(global, 'fetch', oldFn => function(v) {\n    if (v) {\n      if (v.url) {\n        // v is Request\n        const newUrl = urlx.encUrlStrAbs(v.url)\n        arguments[0] = new Request(newUrl, v)\n      } else {\n        // v is string\n        // TODO: 字符串不传引用，无法获取创建时的 constructor\n        arguments[0] = urlx.encUrlStrRel(v, v)\n      }\n    }\n    return apply(oldFn, this, arguments)\n  })\n\n\n  hook.func(global, 'WebSocket', oldFn => function(url) {\n    const urlObj = urlx.newUrl(url)\n    if (urlObj) {\n      const {ori} = env.get(this)\n      if (ori) {\n        const args = {\n          'origin': ori.origin,\n        }\n        arguments[0] = route.genWsUrl(urlObj, args)\n      }\n    }\n    return construct(oldFn, arguments)\n  })\n\n  /**\n   * @param {string} type \n   */\n  function hookWorker(type) {\n    hook.func(global, type, oldFn => function(url) {\n      if (url) {\n        console.log('[jsproxy] new %s: %s', type, url)\n        arguments[0] = urlx.encUrlStrRel(url, this)\n      }\n      return construct(oldFn, arguments)\n    })\n  }\n  \n  hookWorker('Worker')\n  hookWorker('SharedWorker')\n\n\n  hook.func(global, 'importScripts', oldFn => function(...args) {\n    const urls = args.map(urlx.encUrlStrRel)\n    console.log('[jsproxy] importScripts:', urls)\n    return apply(oldFn, this, urls)\n  })\n}"
  },
  {
    "path": "src/proxy/src/cookie.js",
    "content": "import {Database} from './database.js'\n\n/** @type {Set<Cookie>} */\nlet mDirtySet = new Set()\n\n\nfunction Cookie() {\n  this.id = ''\n  this.name = ''\n  this.value = ''\n  this.domain = ''\n  this.hostOnly = false\n  this.path = ''\n  this.expires = NaN\n  this.isExpired = false\n  this.secure = false\n  this.httpOnly = false\n  this.sameSite = ''\n}\n\n/**\n * @param {Cookie} src \n * @param {Cookie} dst \n */\nfunction copy(dst, src) {\n  dst.id = src.id\n  dst.name = src.name\n  dst.value = src.value\n  dst.domain = src.domain\n  dst.hostOnly = src.hostOnly\n  dst.path = src.path\n  dst.expires = src.expires\n  dst.isExpired = src.isExpired\n  dst.secure = src.secure\n  dst.httpOnly = src.httpOnly\n  dst.sameSite = src.sameSite\n}\n\n\n/**\n * @param {string} cookiePath \n * @param {string} urlPath \n */\nfunction isSubPath(cookiePath, urlPath) {\n  if (urlPath === cookiePath) {\n    return true\n  }\n  if (!cookiePath.endsWith('/')) {\n    cookiePath += '/'\n  }\n  return urlPath.startsWith(cookiePath)\n}\n\n\n/**\n * @param {string} cookieDomain \n * @param {string} urlDomain \n */\nfunction isSubDomain(cookieDomain, urlDomain) {\n  return urlDomain === cookieDomain ||\n    urlDomain.endsWith('.' + cookieDomain)\n}\n\n\n/**\n * @param {Cookie} item \n * @param {number} now\n */\nfunction isExpire(item, now) {\n  const v = item.expires\n  return !isNaN(v) && v < now\n}\n\n\nclass CookieDomainNode {\n  constructor() {\n    /** @type {Cookie[]} */\n    this.items = null\n\n    /** @type {Object<string, CookieDomainNode>} */\n    this.children = {}\n  }\n\n  /**\n   * @param {string} name \n   */\n  nextChild(name) {\n    return this.children[name] || (\n      this.children[name] = new CookieDomainNode\n    )\n  }\n\n  /**\n   * @param {string} name \n   */\n  getChild(name) {\n    return this.children[name]\n  }\n\n  /**\n   * @param {Cookie} cookie \n   */\n  addCookie(cookie) {\n    if (this.items) {\n      this.items.push(cookie)\n    } else {\n      this.items = [cookie]\n    }\n  }\n}\n\n/** @type {Map<string, Cookie>} */\nconst mIdCookieMap = new Map()\n\nconst mCookieNodeRoot = new CookieDomainNode()\n\n\n\nexport function getNonHttpOnlyItems() {\n  const ret = []\n  for (const item of mIdCookieMap.values()) {\n    if (!item.httpOnly) {\n      ret.push(item)\n    }\n  }\n  return ret\n}\n\n\n/**\n * @param {string} str \n * @param {URL} urlObj \n * @param {number} now \n */\nexport function parse(str, urlObj, now) {\n  const item = new Cookie()\n  const arr = str.split(';')\n\n  for (let i = 0; i < arr.length; i++) {\n    let key, val\n    const s = arr[i].trim()\n    const p = s.indexOf('=')\n\n    if (p !== -1) {\n      key = s.substr(0, p)\n      val = s.substr(p + 1)\n    } else {\n      //\n      // cookie = 's; secure; httponly'\n      //  0: { key: '', val: 's' }\n      //  1: { key: 'secure', val: '' }\n      //  2: { key: 'httponly', val: '' }\n      //\n      key = (i === 0) ? '' : s\n      val = (i === 0) ? s : ''\n    }\n\n    if (i === 0) {\n      item.name = key\n      item.value = val\n      continue\n    }\n\n    switch (key.toLocaleLowerCase()) {\n    case 'expires':\n      if (isNaN(item.expires)) {\n        item.expires = Date.parse(val)\n      }\n      break\n    case 'domain':\n      if (val[0] === '.') {\n        val = val.substr(1)\n      }\n      item.domain = val\n      break\n    case 'path':\n      item.path = val\n      break\n    case 'httponly':\n      item.httpOnly = true\n      break\n    case 'secure':\n      item.secure = true\n      break\n    case 'max-age':\n      item.expires = now + (+val) * 1000\n      break\n    case 'samesite':\n      item.sameSite = val\n      break\n    }\n  }\n\n  if (isExpire(item, now)) {\n    item.isExpired = true\n  }\n\n  // https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Set-Cookie\n  if (item.name.startsWith('__Secure-')) {\n    if (!(\n      urlObj.protocol === 'https:' &&\n      item.secure\n    )) {\n      return\n    }\n  }\n  if (item.name.startsWith('__Host-')) {\n    if (!(\n      urlObj.protocol === 'https:' &&\n      item.secure &&\n      item.domain === '' &&\n      item.path === '/'\n    )) {\n      return\n    }\n  }\n\n  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Compatibility_notes\n  if (item.secure && urlObj.protocol === 'http:') {\n    return\n  }\n\n  // check hostname\n  const domain = urlObj.hostname\n\n  if (item.domain) {\n    if (!isSubDomain(item.domain, domain)) {\n      console.warn('[jsproxy] invalid cookie domain! `%s` ⊄ `%s`',\n        item.domain, domain)\n      return\n    }\n  } else {\n    item.domain = domain\n    item.hostOnly = true\n  }\n\n  // check pathname\n  const path = urlObj.pathname\n\n  if (item.path) {\n    if (!isSubPath(item.path, path)) {\n      console.warn('[jsproxy] invalid cookie path! `%s` ⊄ `%s`',\n        item.path, path)\n      return\n    }\n  } else {\n    item.path = path\n  }\n\n  item.id = (item.secure ? ';' : '') +\n    item.name + ';' +\n    item.domain +\n    item.path\n\n  return item\n}\n\n\n/**\n * @param {Cookie} item\n */\nexport function set(item) {\n  // console.log('set:', item)\n  const id = item.id\n  const matched = mIdCookieMap.get(id)\n\n  if (matched) {\n    if (item.isExpired) {\n      // delete\n      mIdCookieMap.delete(id)\n      matched.isExpired = true\n      // TODO: remove node\n    } else {\n      // update\n      copy(matched, item)\n    }\n    mDirtySet.add(matched)\n  } else {\n    // create\n    const labels = item.domain.split('.')\n    let labelPos = labels.length\n    let node = mCookieNodeRoot\n    do {\n      node = node.nextChild(labels[--labelPos])\n    } while (labelPos !== 0)\n  \n    node.addCookie(item)\n    mIdCookieMap.set(id, item)\n\n    mDirtySet.add(item)\n  }\n}\n\n\n/**\n * @param {URL} urlObj \n */\nexport function query(urlObj) {\n  const ret = []\n  const now = Date.now()\n  const domain = urlObj.hostname\n  const path = urlObj.pathname\n  const isHttps = (urlObj.protocol === 'https:')\n\n  const labels = domain.split('.')\n  let labelPos = labels.length\n  let node = mCookieNodeRoot\n\n  do {\n    node = node.getChild(labels[--labelPos])\n    if (!node) {\n      break\n    }\n    const items = node.items\n    if (!items) {\n      continue\n    }\n    for (let i = 0; i < items.length; i++) {\n      const item = items[i]\n      // https url | secure flag | carry\n      //   ✔       |   ✔         |   ✔\n      //   ✔       |   ✘         |   ✔\n      //   ✘       |   ✘         |   ✔\n      //   ✘       |   ✔         |   ✘\n      if (!isHttps && item.secure) {\n        continue\n      }\n      // HostOnly Cookie 需匹配完整域名\n      if (item.hostOnly && labelPos !== 0) {\n        continue\n      }\n      if (!isSubPath(item.path, path)) {\n        continue\n      }\n      if (item.isExpired) {\n        continue\n      }\n      if (isExpire(item, now)) {\n        item.isExpired = true\n        continue\n      }\n      // TODO: same site\n\n      let str = item.value\n      if (item.name) {\n        str = item.name + '=' + str\n      }\n      ret.push(str)\n    }\n  } while (labelPos !== 0)\n\n  return ret.join('; ')\n}\n\n\n/** @type {Database} */\nlet mDB\n\nexport async function setDB(db) {\n  mDB = db\n\n  const now = Date.now()\n  await mDB.enum('cookie', v => {\n    if (isExpire(v, now)) {\n      mDB.delete('cookie', v.id)\n    } else {\n      set(v)\n    }\n    return true\n  })\n\n  setInterval(save, 1000 * 3)\n}\n\n\nexport async function save() {\n  if (mDirtySet.size === 0) {\n    return\n  }\n\n  const tmp = mDirtySet\n  mDirtySet = new Set()\n\n  for (const item of tmp) {\n    if (item.isExpired) {\n      await mDB.delete('cookie', item.id)\n    } else if (!isNaN(item.expires)) {\n      // 不保存 session cookie\n      await mDB.put('cookie', item)\n    }\n  }\n}\n"
  },
  {
    "path": "src/proxy/src/database.js",
    "content": "import {Signal} from './signal.js'\n\n\nexport class Database {\n  /**\n   * @param {string} name \n   */\n  constructor(name) {\n    this._name = name\n\n    /** @type {IDBDatabase} */\n    this._db = null\n  }\n\n  /**\n   * @param {string} table \n   * @param {IDBTransactionMode} mode \n   */\n  _getStore(table, mode) {\n    return this._db\n      .transaction(table, mode)\n      .objectStore(table)\n  }\n\n  /**\n   * @param {Object<string, IDBObjectStoreParameters>} opts \n   */\n  open(opts) {\n    const s = new Signal()\n    const req = indexedDB.open(this._name)\n\n    req.onsuccess = (e) => {\n      const idb = req.result\n      this._db = idb\n\n      idb.onclose = (e) => {\n        console.warn('[jsproxy] indexedDB disconnected, reopen...')\n        this.open(opts)\n      }\n      s.notify()\n    }\n    req.onerror = (e) => {\n      console.warn('req.onerror:', e)\n      s.abort(req.error)\n    }\n    req.onupgradeneeded = (e) => {\n      const idb = req.result\n      for (const [k, v] of Object.entries(opts)) {\n        idb.createObjectStore(k, v)\n      }\n    }\n    return s.wait()\n  }\n\n\n  close() {\n    this._db.close()\n  }\n\n  /**\n   * @param {string} table \n   * @param {any} key \n   */\n  get(table, key) {\n    const s = new Signal()\n    const obj = this._getStore(table, 'readonly')\n    const req = obj.get(key)\n\n    req.onsuccess = (e) => {\n      s.notify(req.result)\n    }\n    req.onerror = (e) => {\n      s.abort(req.error)\n    }\n    return s.wait()\n  }\n\n  /**\n   * @param {string} table \n   * @param {any} record \n   */\n  put(table, record) {\n    const s = new Signal()\n    const obj = this._getStore(table, 'readwrite')\n    const req = obj.put(record)\n\n    req.onsuccess = (e) => {\n      s.notify()\n    }\n    req.onerror = (e) => {\n      s.abort(req.error)\n    }\n    return s.wait()\n  }\n\n  /**\n   * @param {string} table \n   * @param {any} key \n   */\n  delete(table, key) {\n    const s = new Signal()\n    const obj = this._getStore(table, 'readwrite')\n    const req = obj.delete(key)\n\n    req.onsuccess = (e) => {\n      s.notify()\n    }\n    req.onerror = (e) => {\n      s.abort(req.error)\n    }\n    return s.wait()\n  }\n\n  /**\n   * @param {string} table \n   * @param {(any) => boolean} callback \n   */\n  enum(table, callback, ...args) {\n    const s = new Signal()\n    const obj = this._getStore(table, 'readonly')\n    const req = obj.openCursor(...args)\n\n    req.onsuccess = (e) => {\n      const {result} = req\n      if (result) {\n        if (callback(result.value) !== false) {\n          result.continue()\n        }\n      } else {\n        s.notify()\n      }\n    }\n    req.onerror = (e) => {\n      s.abort(req.error)\n    }\n    return s.wait()\n  }\n}\n"
  },
  {
    "path": "src/proxy/src/env.js",
    "content": "export const ENV_PAGE = 1\nexport const ENV_WORKER = 2\nexport const ENV_SW = 3\n\nlet mEnvType = 0\n\nexport function setEnvType(v) {\n  mEnvType = v\n}\n\nexport function isSwEnv() {\n  return mEnvType === ENV_SW\n}\n\nexport function isWorkerEnv() {\n  return mEnvType === ENV_WORKER\n}\n\n\n/**\n * @type {WeakMap<Object, {loc: Location, doc: Document, ori: URL, domHook: object}>}\n */\nconst objInfoMap = new WeakMap()\n\nexport function add(win, info) {\n  objInfoMap.set(win.Function, info)\n}\n\nexport function get(obj) {\n  const Function = obj.constructor.constructor\n  return objInfoMap.get(Function)\n}"
  },
  {
    "path": "src/proxy/src/fakeloc.js",
    "content": "import * as urlx from \"./urlx\";\n\nconst {\n  defineProperty,\n  setPrototypeOf,\n} = Object\n\n\nfunction setup(obj, fakeLoc) {\n  defineProperty(obj, '__location', {\n    get() {\n      return fakeLoc\n    },\n    set(val) {\n      console.log('[jsproxy] %s set location: %s', obj, val)\n      fakeLoc.href = val\n    }\n  })\n}\n\n\n/**\n * @param {Window} global  WindowOrWorkerGlobalScope\n */\nexport function createFakeLoc(global) {\n  const location = global.location\n  let ancestorOrigins\n\n  /**\n   * @param {Location | URL} loc \n   */\n  function getPageUrlObj(loc) {\n    return new URL(urlx.decUrlObj(loc))\n  }\n\n\n  // 不缓存 location 属性，因为 beforeunload 事件会影响赋值\n  const locObj = {\n    get href() {\n      // console.log('[jsproxy] get location.href')\n      return getPageUrlObj(location).href\n    },\n\n    // TODO: 精简合并\n    get protocol() {\n      return getPageUrlObj(location).protocol\n    },\n\n    get host() {\n      return getPageUrlObj(location).host\n    },\n\n    get hostname() {\n      return getPageUrlObj(location).hostname\n    },\n\n    get port() {\n      return getPageUrlObj(location).port\n    },\n\n    get pathname() {\n      return getPageUrlObj(location).pathname\n    },\n\n    get search() {\n      return getPageUrlObj(location).search\n    },\n\n    get hash() {\n      return getPageUrlObj(location).hash\n    },\n\n    get origin() {\n      return getPageUrlObj(location).origin\n    },\n\n    toString() {\n      return this.href\n    },\n\n    toLocaleString() {\n      return this.href\n    },\n\n    // TODO: Worker 中没有以下属性\n    get ancestorOrigins() {\n      if (!ancestorOrigins) {\n        // TODO: DOMStringList[]\n        ancestorOrigins = []\n\n        let p = global\n        while ((p = p.parent) !== top) {\n          const u = getPageUrlObj(p.location)\n          ancestorOrigins.unshift(u.origin)\n        }\n      }\n      return ancestorOrigins\n    },\n\n    set href(val) {\n      console.log('[jsproxy] set location.href:', val)\n      location.href = urlx.encUrlStrRel(val, this)\n    },\n\n    set protocol(val) {\n      console.log('[jsproxy] set location.protocol:', val)\n      const urlObj = getPageUrlObj(location)\n      urlObj.href = val\n      location.href = urlx.encUrlObj(urlObj)\n    },\n\n    set host(val) {\n      console.log('[jsproxy] set location.host:', val)\n      const urlObj = getPageUrlObj(location)\n      urlObj.host = val\n      location.href = urlx.encUrlObj(urlObj)\n    },\n\n    set hostname(val) {\n      console.log('[jsproxy] set location.hostname:', val)\n      const urlObj = getPageUrlObj(location)\n      urlObj.hostname = val\n      location.href = urlx.encUrlObj(urlObj)\n    },\n\n    set port(val) {\n      console.log('[jsproxy] set location.port:', val)\n      const urlObj = getPageUrlObj(location)\n      urlObj.port = val\n      location.href = urlx.encUrlObj(urlObj)\n    },\n\n    set pathname(val) {\n      console.log('[jsproxy] set location.pathname:', val)\n      const urlObj = getPageUrlObj(location)\n      urlObj.pathname = val\n      location.href = urlx.encUrlObj(urlObj)\n    },\n\n    set search(val) {\n      location.search = val\n    },\n\n    set hash(val) {\n      location.hash = val\n    },\n\n    reload() {\n      console.warn('[jsproxy] location.reload')\n      // @ts-ignore\n      return location.reload(...arguments)\n    },\n\n    replace(val) {\n      if (val) {\n        console.warn('[jsproxy] location.replace:', val)\n        arguments[0] = urlx.encUrlStrRel(val, this)\n      }\n      // @ts-ignore\n      return location.replace(...arguments)\n    },\n\n    assign(val) {\n      if (val) {\n        console.warn('[jsproxy] location.assign:', val)\n        arguments[0] = urlx.encUrlStrRel(val, this)\n      }\n      // @ts-ignore\n      return location.assign(...arguments)\n    },\n  }\n\n  const locProto = location.constructor.prototype\n  const fakeLoc = setPrototypeOf(locObj, locProto)\n  setup(global, fakeLoc)\n\n  // 非 Worker 环境\n  const Document = global['Document']\n  if (Document) {\n    // TODO: document.hasOwnProperty('location') 原本是 true\n    setup(Document.prototype, fakeLoc)\n  }\n\n  return fakeLoc\n}\n"
  },
  {
    "path": "src/proxy/src/hook.js",
    "content": "const {\n  getOwnPropertyDescriptor,\n  defineProperty,\n  apply,\n} = Reflect\n\n\nexport const DROP = {}\n\n/**\n * hook function\n * \n * @param {object} obj \n * @param {string} key \n * @param {(oldFn: Function) => Function} factory\n */\nexport function func(obj, key, factory) {\n  /** @type {Function} */\n  const oldFn = obj[key]\n  if (!oldFn) {\n    return false\n  }\n\n  const newFn = factory(oldFn)\n\n  Object.keys(oldFn).forEach(k => {\n    newFn[k] = oldFn[k]\n  })\n\n  const proto = oldFn.prototype\n  if (proto) {\n    newFn.prototype = proto\n  }\n\n  obj[key] = newFn\n  return true\n}\n\n/**\n * hook property\n * \n * @param {object} obj \n * @param {string} key \n * @param {(oldFn: () => any) => Function=} g \n * @param {(oldFn: () => void) => Function=} s \n */\nexport function prop(obj, key, g, s) {\n  const desc = getOwnPropertyDescriptor(obj, key)\n  if (!desc) {\n    return false\n  }\n  if (g) {\n    func(desc, 'get', g)\n  }\n  if (s) {\n    func(desc, 'set', s)\n  }\n  defineProperty(obj, key, desc)\n  return true\n}\n\n\n/**\n * @param {Window} win WindowOrWorkerGlobalScope\n */\nexport function createDomHook(win) {\n  /**\n   * @param {object} proto \n   * @param {string} name \n   * @param {Function} onget \n   * @param {Function} onset \n   */\n  function hookElemProp(proto, name, onget, onset) {\n    prop(proto, name,\n      getter => function() {\n        const val = getter.call(this)\n        return onget.call(this, val)\n      },\n      setter => function(val) {\n        val = onset.call(this, val)\n        if (val === DROP) {\n          return\n        }\n        setter.call(this, val)\n      }\n    )\n  }\n\n  const elemProto = win['Element'].prototype\n  const rawGetAttr = elemProto.getAttribute\n  const rawSetAttr = elemProto.setAttribute\n\n  const tagAttrHandlersMap = {}\n  const tagTextHandlerMap = {}\n  const tagKeySetMap = {}\n  const tagKeyGetMap = {}\n\n  /**\n   * @param {string} tag \n   * @param {object} proto \n   * @param  {...any} handlers \n   */\n  function attr(tag, proto, ...handlers) {\n    /** @type {boolean} */\n    let hasBind\n\n    /** @type {boolean} */\n    let hasAttr\n    \n    let keySetMap\n    let keyGetMap\n\n    // TODO: 未考虑上下文\n  \n    handlers.forEach(v => {\n      // 带划线的 attr 属性名，转换成驼峰形式的 prop 属性名。\n      // 例如 `http-equiv` -> `httpEquiv`\n      const prop = v.name.replace(/-(\\w)/g,\n        (_, char) => char.toUpperCase()\n      )\n      hookElemProp(proto, prop, v.onget, v.onset)\n\n      // #text\n      if (prop === 'innerText') {\n        tagTextHandlerMap[tag] = v\n        return\n      }\n\n      // attribute\n      if (tagAttrHandlersMap[tag]) {\n        tagAttrHandlersMap[tag].push(v)\n        hasBind = true\n      } else {\n        tagAttrHandlersMap[tag] = [v]\n        tagKeySetMap[tag] = {}\n        tagKeyGetMap[tag] = {}\n      }\n\n      if (!keySetMap) {\n        keySetMap = tagKeySetMap[tag]\n        keyGetMap = tagKeyGetMap[tag]\n      }\n      const key = v.name.toLocaleLowerCase()\n      keySetMap[key] = v.onset\n      keyGetMap[key] = v.onget\n      hasAttr = true\n    })\n\n    if (hasBind || !hasAttr) {\n      return\n    }\n\n    // 如果之前调用过 setAttribute，直接返回上次设置的值；\n    // 如果没有调用过，则返回 onget 的回调值。\n    func(proto, 'getAttribute', oldFn => function(name) {\n      const key = (name + '').toLocaleLowerCase()\n\n      const onget = keyGetMap[key]\n      if (!onget) {\n        return apply(oldFn, this, arguments)\n      }\n\n      const lastVal = this['_k' + key]\n      if (lastVal !== undefined) {\n        return lastVal\n      }\n      const val = apply(oldFn, this, arguments)\n      return onget.call(this, val)\n    })\n\n    func(proto, 'setAttribute', oldFn => function(name, val) {\n      const key = (name + '').toLocaleLowerCase()\n      const onset = keySetMap[key]\n      if (onset) {\n        this['_k' + key] = val\n\n        const ret = onset.call(this, val)\n        if (ret === DROP) {\n          return\n        }\n        arguments[1] = ret\n      }\n      return apply(oldFn, this, arguments)\n    })\n\n    func(proto, 'setAttributeNode', oldFn => function(node) {\n      console.warn('setAttributeNode:', node, this)\n      // TODO:\n      return apply(oldFn, this, arguments)\n    })\n\n    // ...\n  }\n\n  /**\n   * @param {Node} node\n   * @param {object} handler\n   * @param {Element} elem \n   */\n  function parseNewTextNode(node, handler, elem) {\n// console.log('parseTextNode')\n    const val = node.nodeValue\n    const ret = handler.onset.call(elem, val, true)\n    if (ret === DROP) {\n      return\n    }\n    node.nodeValue = ret\n  }\n\n  /**\n   * @param {Element} elem \n   * @param {object} handler\n   */\n  function parseNewElemNode(elem, handler) {\n    const name = handler.name\n    if (!elem.hasAttribute(name)) {\n      return\n    }\n    const val = rawGetAttr.call(elem, name)\n    const ret = handler.onset.call(elem, val, true)\n    if (ret === DROP) {\n      return\n    }\n    rawSetAttr.call(elem, name, ret)\n  }\n\n  \n  /**\n   * @param {Node} node \n   */\n  function addNode(node) {\n    const type = node.nodeType\n    if (type === 1) {\n      /** @type {Element} */\n      // @ts-ignore\n      const elem = node\n      const handlers = tagAttrHandlersMap[elem.tagName]\n      handlers && handlers.forEach(v => {\n        parseNewElemNode(elem, v)\n      })\n    }\n    else if (type === 3) {\n      // TEXT_NODE\n      const parent = node.parentElement\n      if (parent) {\n        const handler = tagTextHandlerMap[parent.tagName]\n        if (handler) {\n          parseNewTextNode(node, handler, parent)\n        }\n      }\n    }\n  }\n\n  /**\n   * @param {Node} node \n   */\n  function delNode(node) {\n    // TODO: 增加节点删除后的回调\n  }\n\n  return {\n    attr,\n    addNode,\n    delNode,\n  }\n}"
  },
  {
    "path": "src/proxy/src/index.js",
    "content": "import * as env from \"./env\";\n\n\nfunction pageEnv(win) {\n  env.setEnvType(env.ENV_PAGE)\n\n  if (win === top) {\n    // 开放一个接口，可供 iframe 调用\n    win.__init__ = function(win) {\n      page.init(win)\n      console.log('[jsproxy] child page inited.', win.location.href)\n    }\n\n    // 用于记录 postMessage 发起者的 win\n    let lastSrcWin\n    win.__set_srcWin = function(obj) {\n      lastSrcWin = obj || win\n      return []\n    }\n    win.__get_srcWin = function() {\n      const ret = lastSrcWin\n      lastSrcWin = null\n      return ret\n    }\n\n    // eslint-disable-next-line no-undef\n    const page = require('./page.js')\n    page.init(win)\n\n    console.log('[jsproxy] top page inited')\n  } else {\n    // 子页面直接调用 top 提供的接口，无需重复初始化\n    top['__init__'](win)\n\n    win.__set_srcWin = function() {\n      return top['__set_srcWin'](win)\n    }\n  }\n}\n\nfunction swEnv() {\n  env.setEnvType(env.ENV_SW)\n  // eslint-disable-next-line no-undef\n  require('./sw.js')\n}\n\nfunction workerEnv(global) {\n  env.setEnvType(env.ENV_WORKER)\n\n  // eslint-disable-next-line no-undef\n  require('./client.js').init(global, location.origin)\n  global.__set_srcWin = function() {\n    return []\n  }\n}\n\nfunction main(global) {\n  if ('onclick' in global) {\n    pageEnv(global)\n  } else if ('onfetch' in global) {\n    swEnv()\n  } else {\n    workerEnv(global)\n  }\n}\n\nmain(self)"
  },
  {
    "path": "src/proxy/src/inject.js",
    "content": "import * as path from './path.js'\nimport * as util from \"./util\"\n// import * as jsfilter from './jsfilter.js'\n\nlet mConf\n\n\nconst WORKER_INJECT = util.strToBytes(`\\\nif (typeof importScripts === 'function' && !self.window && !self.__PATH__) {\n  self.__PATH__ = '${path.ROOT}';\n  importScripts('${path.HELPER}');\n}\n`)\n\n\nexport function getWorkerCode() {\n  return WORKER_INJECT\n}\n\n\nexport function setConf(conf) {\n  mConf = conf\n}\n\n\nconst PADDING = ' '.repeat(500)\n\nconst CSP = `\\\n'self' \\\n'unsafe-inline' \\\nfile: \\\ndata: \\\nblob: \\\nmediastream: \\\nfilesystem: \\\nchrome-extension-resource: \\\n`\n\n/**\n * @param {URL} urlObj \n * @param {number} pageId \n */\nexport function getHtmlCode(urlObj, pageId) {\n  const icoUrl = path.PREFIX + urlObj.origin + '/favicon.ico'\n  const custom = mConf.inject_html || ''\n\n  return util.strToBytes(`\\\n<!-- JS PROXY HELPER -->\n<!doctype html>\n<link rel=\"icon\" href=\"${icoUrl}\" type=\"image/x-icon\">\n<meta http-equiv=\"content-security-policy\" content=\"frame-src ${CSP}; object-src ${CSP}\">\n<base href=\"${urlObj.href}\">\n<script data-id=\"${pageId}\" src=\"${path.HELPER}\"></script>\n${custom}\n<!-- PADDING ${PADDING} -->\n\n`)\n}\n"
  },
  {
    "path": "src/proxy/src/jsfilter.js",
    "content": "import * as util from './util.js'\n\n\n/**\n * @param {string} code \n */\nexport function parseStr(code) {\n  // TODO: parse js ast\n  let match = false\n\n  code = code.replace(/(\\b)location(\\b)/g, (_, $1, $2) => {\n    match = true\n    return $1 + '__location' + $2\n  })\n  code = code.replace(/postMessage\\s*\\(/g, s => {\n    match = true\n    return s + `...(self.__set_srcWin?__set_srcWin():[]), `\n  })\n  if (match) {\n    return code\n  }\n  return null\n}\n\n/**\n * @param {Uint8Array} buf\n * @param {string} charset\n */\nexport function parseBin(buf, charset) {\n  const str = util.bytesToStr(buf, charset)\n  const ret = parseStr(str)\n  if (ret !== null) {\n    return util.strToBytes(ret)\n  }\n  if (charset && !util.isUtf8(charset)) {\n    return util.strToBytes(str)\n  }\n  return null\n}"
  },
  {
    "path": "src/proxy/src/msg.js",
    "content": "export const PAGE_INFO_PULL = 1\nexport const SW_INFO_PUSH = 2\n\nexport const PAGE_COOKIE_PUSH = 3\nexport const SW_COOKIE_PUSH = 4\n\nexport const PAGE_INIT_BEG = 5\nexport const PAGE_INIT_END = 6\n\nexport const PAGE_CONF_SET = 110\nexport const PAGE_CONF_GET = 111\nexport const PAGE_RELOAD_CONF = 112\n\nexport const SW_CONF_RETURN = 112\nexport const SW_CONF_CHANGE = 113\n\nexport const PAGE_READY_CHECK = 200\nexport const SW_READY = 201"
  },
  {
    "path": "src/proxy/src/network.js",
    "content": "import * as route from './route.js'\nimport * as cookie from './cookie.js'\nimport * as urlx from './urlx.js'\nimport * as util from './util'\nimport * as tld from './tld.js'\nimport * as cdn from './cdn.js'\nimport {Database} from './database.js'\n\n\nconst REFER_ORIGIN = location.origin + '/'\nconst ENABLE_3RD_COOKIE = true\n\n/** @type {Database} */\nlet mDB\n\n\n// 部分浏览器不支持 access-control-expose-headers: *\n// https://developer.mz.jsproxy.tk/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers#Compatibility_notes\n//\n// 如果返回所有字段名，长度会很大。\n// 因此请求头中设置 aceh__ 标记，告知服务器是否要返回所有字段名。\nlet mIsAcehOld = true\n\n// TODO:\nlet mConf\n\n\nexport function setConf(conf) {\n  mConf = conf\n  cdn.setConf(conf)\n}\n\n\nexport async function setDB(db) {\n  mDB = db\n  // clear expires\n}\n\n\n/**\n * @param {string} url \n */\nfunction getUrlCache(url) {\n  return mDB.get('url-cache', url)\n}\n\n\n/**\n * @param {string} url \n * @param {string} host \n * @param {string} info \n * @param {number} expires \n */\nasync function setUrlCache(url, host, info, expires) {\n  await mDB.put('url-cache', {url, host, info, expires})\n}\n\n\n/**\n * @param {string} url \n */\nasync function delUrlCache(url) {\n  await mDB.delete('url-cache', url)\n}\n\n\n/**\n * @param {URL} targetUrlObj \n * @param {URL} clientUrlObj \n * @param {Request} req \n */\nfunction getReqCookie(targetUrlObj, clientUrlObj, req) {\n  const cred = req.credentials\n  if (cred === 'omit') {\n    return ''\n  }\n  if (cred === 'same-origin') {\n    // TODO:\n    const targetTld = tld.getTld(targetUrlObj.hostname)\n    const clientTld = tld.getTld(clientUrlObj.hostname)\n    if (targetTld !== clientTld) {\n      return ''\n    }\n  }\n  return cookie.query(targetUrlObj)\n}\n\n\n/**\n * @param {Headers} header \n */\nfunction parseResCache(header) {\n  const cacheStr = header.get('cache-control')\n  if (cacheStr) {\n    if (/no-cache/i.test(cacheStr)) {\n      return -1\n    }\n    const m = cacheStr.match(/(?:^|,\\s*)max-age=[\"]?(\\d+)/i)\n    if (m) {\n      const sec = +m[1]\n      if (sec > 0) {\n        return sec\n      }\n    }\n  }\n  const expires = header.get('expires')\n  if (expires) {\n    const ts = Date.parse(expires)\n    if (ts > 0) {\n      return (ts - Date.now()) / 1000 | 0\n    }\n  }\n  return 0\n}\n\n\n/**\n * @param {string[]} cookieStrArr \n * @param {URL} urlObj \n * @param {URL} cliUrlObj\n */\nfunction procResCookie(cookieStrArr, urlObj, cliUrlObj) {\n  if (!ENABLE_3RD_COOKIE) {\n    const urlTld = tld.getTld(urlObj.hostname)\n    const cliTld = tld.getTld(cliUrlObj.hostname)\n    if (cliTld !== urlTld) {\n      return\n    }\n  }\n\n  const ret = []\n  const now = Date.now()\n\n  for (const str of cookieStrArr) {\n    const item = cookie.parse(str, urlObj, now)\n    if (!item) {\n      continue\n    }\n    cookie.set(item)\n    if (!item.httpOnly) {\n      ret.push(item)\n    }\n  }\n  return ret\n}\n\n\n/**\n * @param {Response} res \n */\nfunction getResInfo(res) {\n  const rawHeaders = res.headers\n  let status = res.status\n\n  /** @type {string[]} */\n  const cookieStrArr = []\n  const headers = new Headers()\n\n  rawHeaders.forEach((val, key) => {\n    if (key === 'access-control-allow-origin' ||\n        key === 'access-control-expose-headers') {\n      return\n    }\n    if (key === '--s') {\n      status = +val\n      return\n    }\n    if (key === '--t') {\n      return\n    }\n    // 还原重名字段\n    //  0-key: v1\n    //  1-key: v2\n    // =>\n    //  key: v1, v2\n    //\n    // 对于 set-cookie 单独存储，因为合并会破坏 cookie 格式：\n    //  var h = new Headers()\n    //  h.append('set-cookie', 'hello')\n    //  h.append('set-cookie', 'world')\n    //  h.get('set-cookie')  // \"hello, world\"\n    //\n    const m = key.match(/^\\d+-(.+)/)\n    if (m) {\n      key = m[1]\n      if (key === 'set-cookie') {\n        cookieStrArr.push(val)\n      } else {\n        headers.append(key, val)\n      }\n      return\n    }\n\n    // 还原转义字段（`--key` => `key`）\n    if (key.startsWith('--')) {\n      key = key.substr(2)\n    }\n\n    // 单个 set-cookie 返回头\n    if (key === 'set-cookie') {\n      cookieStrArr.push(val)\n      return\n    }\n\n    headers.set(key, val)\n  })\n\n  return {status, headers, cookieStrArr}\n}\n\n\n// https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte\nconst R_UNSAFE_REQ_HDR_CHAR =\n  // eslint-disable-next-line no-control-regex\n  /[\\x00-\\x08\\x0a-\\x1f\\x22\\x28\\x29\\x3a\\x3c\\x3e\\x3f\\x40\\x5b\\x5c\\x5d\\x7b\\x7d\\x7f]/\n\n/**\n * @param {string} key \n * @param {string} val \n */\nfunction isSimpleReqHdr(key, val) {\n  if (key === 'content-type') {\n    return (\n      val === 'application/x-www-form-urlencoded' ||\n      val === 'multipart/form-data' ||\n      val === 'text/plain'\n    )\n  }\n  if (key === 'accept' ||\n      key === 'accept-language' ||\n      key === 'content-language'\n  ) {\n    // 标准是总和小于 1024，这里保守一些\n    return val.length < 256 &&\n      !R_UNSAFE_REQ_HDR_CHAR.test(val)\n  }\n}\n\n\n/**\n * @param {Request} req \n * @param {URL} urlObj \n * @param {URL} cliUrlObj \n */\nfunction initReqHdr(req, urlObj, cliUrlObj) {\n  const reqHdr = new Headers()\n  const reqMap = {\n    '--ver': mConf.ver,\n    '--mode': req.mode,\n    '--type': req.destination || '',\n    'origin': '',\n  }\n  if (mIsAcehOld) {\n    reqMap['--aceh'] = '1'\n  }\n\n  req.headers.forEach((val, key) => {\n    if (key === 'user-agent') {\n      return\n    }\n    if (isSimpleReqHdr(key, val)) {\n      reqHdr.set(key, val)\n    } else {\n      reqMap[key] = val\n    }\n  })\n\n  if (reqMap['origin']) {\n    reqMap['origin'] = cliUrlObj.origin\n  }\n\n  const referer = req.referrer\n  if (referer) {\n    // TODO: CSS 引用图片的 referer 不是页面 URL，而是 CSS URL\n    if (referer === REFER_ORIGIN) {\n      // Referrer Policy: origin\n      reqMap['referer'] = cliUrlObj.origin + '/'\n    } else {\n      reqMap['referer'] = urlx.decUrlStrAbs(referer)\n    }\n  }\n\n  reqMap['cookie'] = getReqCookie(urlObj, cliUrlObj, req)\n\n  return {reqHdr, reqMap}\n}\n\n/**\n * @param {RequestInit} reqOpt \n * @param {Object<string, string>} info \n */\nfunction updateReqHeaders(reqOpt, info) {\n  reqOpt.referrer = '/?' + new URLSearchParams(info)\n}\n\n\nconst MAX_RETRY = 5\n\n/**\n * @param {Request} req \n * @param {URL} urlObj \n * @param {URL} cliUrlObj \n */\nexport async function launch(req, urlObj, cliUrlObj) {\n  const {method} = req\n\n  /** @type {RequestInit} */\n  const reqOpt = {\n    mode: 'cors',\n    method,\n  }\n\n  if (method === 'POST' && !req.bodyUsed) {\n    if (req.body) {\n      reqOpt.body = req.body\n    } else {\n      const buf = await req.arrayBuffer()\n      if (buf.byteLength > 0) {\n        reqOpt.body = buf\n      }\n    }\n  }\n\n  if (req.signal) {\n    reqOpt.signal = req.signal\n  }\n\n  if (!urlx.isHttpProto(urlObj.protocol)) {\n    // 非 HTTP 协议的资源，直接访问\n    // 例如 youtube 引用了 chrome-extension: 协议的脚本\n    const res = await fetch(req)\n    return {res}\n  }\n\n  const url = urlObj.href\n  const urlHash = util.strHash(url)\n  let host = ''\n  let rawInfo = ''\n\n  const {reqHdr, reqMap} = initReqHdr(req, urlObj, cliUrlObj)\n  reqOpt.headers = reqHdr\n\n  while (method === 'GET') {\n    // 该资源是否加载过？\n    const r = await getUrlCache(url)\n    if (r && r.host) {\n      const now = util.getTimeSeconds()\n      if (now < r.expires) {\n        // 使用之前的节点，提高缓存命中率\n        host = r.host\n        rawInfo = r.info\n        break\n      }\n    }\n\n    // 支持 CORS 的站点，可直连\n    if (cdn.isDirectHost(urlObj.host)) {\n      console.log('direct hit:', url)\n      const res = await cdn.proxyDirect(url)\n      if (res) {\n        setUrlCache(url, '', '', 0)\n        return {res}\n      }\n    }\n\n    // 常用静态资源 CDN 加速\n    const ver = cdn.getFileVer(urlHash)\n    if (ver >= 0) {\n      console.log('cdn hit:', url)\n      const res = await cdn.proxyStatic(urlHash, ver)\n      if (res) {\n        setUrlCache(url, '', '', 0)\n        return {res}\n      }\n    }\n\n    break\n  }\n\n  // TODO: 此处逻辑需要优化\n  let level = 1\n\n  // 如果缓存未命中产生请求，服务器不做节点切换\n  if (host) {\n    level = 0\n  }\n\n  /** @type {Response} */\n  let res\n\n  /** @type {Headers} */\n  let resHdr\n\n\n  for (let i = 0; i < MAX_RETRY; i++) {\n    if (i === 0 && host) {\n      // 使用缓存的主机\n    } else {\n      host = route.getHost(urlHash, level)\n    }\n    \n    const rawUrl = urlx.delHash(urlObj.href)\n    let proxyUrl = route.genUrl(host, 'http') + '/' + rawUrl\n\n    // 即使未命中缓存，在请求“加速节点”时也能带上文件信息\n    if (rawInfo) {\n      reqMap['--raw-info'] = rawInfo\n    } else {\n      delete reqMap['--raw-info']\n    }\n\n    res = null\n    try {\n      reqMap['--level'] = level\n      updateReqHeaders(reqOpt, reqMap)\n      res = await fetch(proxyUrl, reqOpt)\n    } catch (err) {\n      console.warn('fetch fail:', proxyUrl)\n      break\n      // TODO: 重试其他线路\n      // route.setFailHost(host)\n    }\n    resHdr = res.headers\n\n    // 检测浏览器是否支持 aceh: *\n    if (mIsAcehOld && resHdr.has('--t')) {\n      mIsAcehOld = false\n      delete reqMap['--aceh']\n    }\n\n    // 是否切换节点\n    if (resHdr.has('--switched')) {\n      rawInfo = resHdr.get('--raw-info')\n      level++\n      continue\n    }\n\n    // 目前只有加速节点会返回该信息\n    const resErr = resHdr.get('--error')\n    if (resErr) {\n      console.warn('[jsproxy] cfworker fail:', resErr)\n      rawInfo = ''\n      level = 0\n      continue\n    }\n\n    break\n  }\n\n  if (!res) {\n    return\n  }\n\n  const {\n    status, headers, cookieStrArr\n  } = getResInfo(res)\n\n\n  if (method === 'GET' && status === 200) {\n    const cacheSec = parseResCache(headers)\n    if (cacheSec >= 0) {\n      const expires = util.getTimeSeconds() + cacheSec + 1000\n      setUrlCache(url, host, rawInfo, expires)\n    }\n  }\n\n  // 处理 HTTP 返回头的 refresh 字段\n  // http://www.otsukare.info/2015/03/26/refresh-http-header\n  const refresh = headers.get('refresh')\n  if (refresh) {\n    const newVal = urlx.replaceHttpRefresh(refresh, url)\n    if (newVal !== refresh) {\n      console.log('[jsproxy] http refresh:', refresh)\n      headers.set('refresh', newVal)\n    }\n  }\n\n  let cookies\n  if (cookieStrArr.length) {\n    const items = procResCookie(cookieStrArr, urlObj, cliUrlObj)\n    if (items.length) {\n      cookies = items\n    }\n  }\n\n  return {res, status, headers, cookies}\n}\n"
  },
  {
    "path": "src/proxy/src/page.js",
    "content": "import * as MSG from './msg.js'\nimport * as route from './route.js'\nimport * as util from './util.js'\nimport * as urlx from './urlx.js'\nimport * as hook from './hook.js'\nimport * as cookie from './cookie.js'\nimport * as jsfilter from './jsfilter.js'\nimport * as env from './env.js'\nimport * as client from './client.js'\n\n\nconst {\n  apply,\n} = Reflect\n\n\nfunction initDoc(win, domHook) {\n  const document = win.document\n\n  const headElem = document.head\n  const baseElemList = document.getElementsByTagName('base')\n  const baseElem = baseElemList[0]\n  \n  document.__baseElem = baseElem\n\n  //\n  // 监控元素创建和删除\n  //\n  const nodeSet = new WeakSet()\n\n  function onNodeAdd(node) {\n    if (nodeSet.has(node)) {\n      return\n    }\n    nodeSet.add(node)\n    \n    const nodes = node.childNodes\n    for (let i = 0, n = nodes.length; i < n; i++) {\n      onNodeAdd(nodes[i])\n    }\n    domHook.addNode(node)\n  }\n\n\n  function onNodeDel(node) {\n    nodeSet.delete(node)\n\n    const nodes = node.childNodes\n    for (let i = 0, n = nodes.length; i < n; i++) {\n      onNodeDel(nodes[i])\n    }\n    domHook.delNode(node)\n\n    // TODO: 逻辑优化\n    if (node === baseElem) {\n      // 默认的 <base> 元素可能会被删除，需要及时补上\n      headElem.insertBefore(baseElem, headElem.firstChild)\n      console.warn('[jsproxy] base elem restored')\n    }\n  }\n\n  /**\n   * @param {MutationRecord[]} mutations \n   */\n  function parseMutations(mutations) {\n    mutations.forEach(mutation => {\n      mutation.addedNodes.forEach(onNodeAdd)\n      mutation.removedNodes.forEach(onNodeDel)\n    })\n  }\n\n  const observer = new win.MutationObserver(parseMutations)\n  observer.observe(document, {\n    childList: true,\n    subtree: true,\n  })\n}\n\n\n/**\n * Hook 页面 API\n * \n * @param {Window} win \n */\nexport function init(win) {\n  if (!win) {\n    return\n  }\n  try {\n    win['x']\n  } catch (err) {\n    // TODO: 不应该出现\n    console.warn('not same origin')\n    return\n  }\n\n  const document = win.document\n\n  // 该 window 之前已初始化过，现在只需更新 document。\n  // 例如 iframe 加载完成之前，读取 contentWindow 得到的是空白页，\n  // 加载完成后，document 对象会变化，但 window 上的属性仍保留。\n  const info = env.get(win['Math'])\n  if (info) {\n    const {doc, domHook} = info\n    if (doc !== document) {\n      // 加载完成后，初始化实际页面的 document\n      initDoc(win, domHook)\n      info[1] = document\n    }\n    return\n  }\n\n\n  const {\n    location,\n    navigator,\n  } = win\n\n\n  // 源路径（空白页继承上级页面）\n  const oriUrlObj = new URL(document.baseURI)\n\n  const domHook = hook.createDomHook(win)\n\n  // 关联当前页面上下文信息\n  env.add(win, {\n    loc: location,\n    doc: document,\n    ori: oriUrlObj,\n    domHook,\n  })\n\n  // hook 页面和 Worker 相同的 API\n  client.init(win, oriUrlObj.origin)\n\n  // 首次安装 document\n  // 如果访问加载中的页面，返回 about:blank 空白页\n  initDoc(win, domHook)\n\n\n  const sw = navigator.serviceWorker\n  const swCtl = sw.controller\n\n  function sendMsgToSw(cmd, val) {\n    swCtl && swCtl.postMessage([cmd, val])\n  }\n\n\n  // TODO: 这部分逻辑需要优化\n  let readyCallback\n\n  function pageAsyncInit() {\n    const curScript = document.currentScript\n    if (!curScript) {\n      return\n    }\n    // curScript.remove()\n\n    const pageId = +curScript.dataset['id']\n    // console.log('PAGE wait id:', pageId)\n\n    if (!pageId) {\n      console.warn('[jsproxy] missing page id')\n      return\n    }\n\n    readyCallback = function() {\n      sendMsgToSw(MSG.PAGE_INIT_END, pageId)\n    }\n\n    sendMsgToSw(MSG.PAGE_INIT_BEG, pageId)\n\n    // do async init\n    // if (win === top) {\n      sendMsgToSw(MSG.PAGE_INFO_PULL)\n    // } else {\n    //   readyCallback()\n    // }\n  }\n  pageAsyncInit()\n\n\n  sw.addEventListener('message', e => {\n    const [cmd, val] = e.data\n    switch (cmd) {\n    case MSG.SW_COOKIE_PUSH:\n      // console.log('PAGE MSG.SW_COOKIE_PUSH:', val)\n      val.forEach(cookie.set)\n      break\n\n    case MSG.SW_INFO_PUSH:\n      // console.log('PAGE MSG.SW_INFO_PUSH:', val)\n      val.cookies.forEach(cookie.set)\n      route.setConf(val.conf)\n      readyCallback()\n      break\n\n    case MSG.SW_CONF_CHANGE:\n      route.setConf(val)\n      break\n    }\n    e.stopImmediatePropagation()\n  }, true)\n\n  sw.startMessages && sw.startMessages()\n\n  //\n  // hook ServiceWorker\n  //\n  const swProto = win['ServiceWorkerContainer'].prototype\n  if (swProto) {\n    hook.func(swProto, 'register', oldFn => function() {\n      console.warn('access serviceWorker.register blocked')\n      return new Promise(function() {})\n    })\n    hook.func(swProto, 'getRegistration', oldFn => function() {\n      console.warn('access serviceWorker.getRegistration blocked')\n      return new Promise(function() {})\n    })\n    hook.func(swProto, 'getRegistrations', oldFn => function() {\n      console.warn('access serviceWorker.getRegistrations blocked')\n      return new Promise(function() {})\n    })\n  }\n\n  /**\n   * History API\n   * @param {string} name \n   */\n  function hookHistory(name) {\n    const proto = win['History'].prototype\n\n    hook.func(proto, name, oldFn =>\n    /**\n     * @param {*} data \n     * @param {string} title \n     * @param {string} url 相对或绝对路径\n     */\n    function(data, title, url) {\n      console.log('[jsproxy] history.%s: %s', name, url)\n\n      const {loc, doc} = env.get(this)\n      if (doc && url) {\n        const dstUrlObj = urlx.newUrl(url, doc.baseURI)\n        if (dstUrlObj) {\n          // 当前页面 URL\n          const srcUrlStr = urlx.decUrlObj(loc)\n          const srcUrlObj = new URL(srcUrlStr)\n\n          if (srcUrlObj.origin !== dstUrlObj.origin) {\n            throw Error(`\\\nFailed to execute '${name}' on 'History': \\\nA history state object with URL '${url}' \\\ncannot be created in a document with \\\norigin '${srcUrlObj.origin}' and URL '${srcUrlStr}'.`\n            )\n          }\n          arguments[2] = urlx.encUrlObj(dstUrlObj)\n        }\n      }\n      return apply(oldFn, this, arguments)\n    })\n  }\n  hookHistory('pushState')\n  hookHistory('replaceState')\n\n  //\n  // hook window.open()\n  //\n  hook.func(win, 'open', oldFn => function(url) {\n    if (url) {\n      arguments[0] = urlx.encUrlStrRel(url, url)\n    }\n    return apply(oldFn, this, arguments)\n  })\n\n  //\n  // hook window.frames[...]\n  //\n  const frames = win.frames\n\n  // @ts-ignore\n  win.frames = new Proxy(frames, {\n    get(_, key) {\n      if (typeof key === 'number') {\n        console.log('get frames index:', key)\n        const win = frames[key]\n        init(win)\n        return win\n      } else {\n        return frames[key]\n      }\n    }\n  })\n\n  //\n  hook.func(navigator, 'registerProtocolHandler', oldFn => function(_0, url, _1) {\n    console.log('registerProtocolHandler:', arguments)\n    return apply(oldFn, this, arguments)\n  })\n\n\n  //\n  // hook document.domain\n  //\n  const docProto = win['Document'].prototype\n  let domain = oriUrlObj.hostname\n\n  hook.prop(docProto, 'domain',\n    getter => function() {\n      return domain\n    },\n    setter => function(val) {\n      console.log('[jsproxy] set document.domain:', val)\n      domain = val\n      // TODO:\n      setter.call(this, location.hostname)\n    }\n  )\n\n  //\n  // hook document.cookie\n  //\n  hook.prop(docProto, 'cookie',\n    getter => function() {\n      // console.log('[jsproxy] get document.cookie')\n      const {ori} = env.get(this)\n      return cookie.query(ori)\n    },\n    setter => function(val) {\n      // console.log('[jsproxy] set document.cookie:', val)\n      const {ori} = env.get(this)\n      const item = cookie.parse(val, ori, Date.now())\n      if (item) {\n        cookie.set(item)\n        sendMsgToSw(MSG.PAGE_COOKIE_PUSH, item)\n      }\n    }\n  )\n\n  // hook uri api\n  function getUriHook(getter) {\n    return function() {\n      const val = getter.call(this)\n      return val && urlx.decUrlStrAbs(val)\n    }\n  }\n\n  hook.prop(docProto, 'referrer', getUriHook)\n  hook.prop(docProto, 'URL', getUriHook)\n  hook.prop(docProto, 'documentURI', getUriHook)\n\n  const nodeProto = win['Node'].prototype\n  hook.prop(nodeProto, 'baseURI', getUriHook)\n\n\n  // hook Message API\n  const msgEventProto = win['MessageEvent'].prototype\n  hook.prop(msgEventProto, 'origin',\n    getter => function() {\n      const {ori} = env.get(this)\n      return ori.origin\n    }\n  )\n\n\n  hook.func(win, 'postMessage', oldFn => function(msg, origin) {\n    const srcWin = top['__get_srcWin']() || this\n    // console.log(srcWin)\n    if (origin && origin !== '*') {\n      arguments[1] = '*'\n    }\n    return apply(oldFn, srcWin, arguments)\n  })\n\n\n  //\n  // hook <meta>\n  //\n  const metaProto = win['HTMLMetaElement'].prototype\n\n  domHook.attr('META', metaProto,\n  {\n    name: 'http-equiv',\n    onget(val) {\n      // TODO: \n      return val\n    },\n    onset(val) {\n      let newVal\n\n      switch (val.toLowerCase()) {\n      case 'refresh':\n        newVal = urlx.replaceHttpRefresh(this.content, this)\n        if (newVal !== val) {\n          console.warn('[jsproxy] meta redir')\n          this.content = newVal\n        }\n        break\n      case 'content-security-policy':\n        console.warn('[jsproxy] meta csp removed')\n        this.remove()\n        break\n      case 'content-type':\n        this.remove()\n        break\n      }\n      return val\n    }\n  },\n  {\n    name: 'charset',\n    onget(val) {\n      return val\n    },\n    onset(val) {\n      return 'utf-8'\n    }\n  }\n  )\n\n  //\n  // hook 元素的 URL 属性，JS 读取时伪装成原始值\n  //\n  function hookAttr(tag, proto, name) {\n    domHook.attr(tag, proto, {\n      name,\n      onget(val) {\n        if (val === null) {\n          return ''\n        }\n        return urlx.decUrlStrRel(val, this)\n      },\n      onset(val) {\n        if (val === '') {\n          return val\n        }\n        return urlx.encUrlStrRel(val, this)\n      }\n    })\n  }\n\n  const anchorProto = win['HTMLAnchorElement'].prototype\n  hookAttr('A', anchorProto, 'href')\n\n  const areaProto = win['HTMLAreaElement'].prototype\n  hookAttr('AREA', areaProto, 'href')\n\n  const formProto = win['HTMLFormElement'].prototype\n  hookAttr('FORM', formProto, 'action')\n\n  const scriptProto = win['HTMLScriptElement'].prototype\n  const linkProto = win['HTMLLinkElement'].prototype\n\n  // 防止混合内容\n  if (oriUrlObj.protocol === 'http:') {\n    hookAttr('SCRIPT', scriptProto, 'src')\n    hookAttr('LINK', linkProto, 'href')\n  }\n\n  // const imgProto = win.HTMLImageElement.prototype\n  // hookAttr('IMG', imgProto, 'src')\n\n  const embedProto = win['HTMLEmbedElement'].prototype\n  hookAttr('EMBED', embedProto, 'src')\n\n  const objectProto = win['HTMLObjectElement'].prototype\n  hookAttr('OBJECT', objectProto, 'data')\n\n  const iframeProto = win['HTMLIFrameElement'].prototype\n  hookAttr('IFRAME', iframeProto, 'src')\n\n  const frameProto = win['HTMLFrameElement'].prototype\n  hookAttr('FRAME', frameProto, 'src')\n\n\n  // 更新默认的 baseURI\n  // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base#Usage_notes\n  const baseProto = win['HTMLBaseElement'].prototype\n  domHook.attr('BASE', baseProto,\n  {\n    name: 'href',\n    onget(val) {\n      return this.__href || val\n    },\n    onset(val) {\n      // TODO: 逻辑优化\n      const baseElem = this.ownerDocument.__baseElem\n      if (!baseElem || baseElem === this) {\n        return val\n      }\n      console.log('[jsproxy] baseURI updated:', val)\n      const urlObj = urlx.newUrl(val, baseElem.href)\n      baseElem.href = urlObj.href\n      this.__href = val\n      return ''\n    }\n  })\n\n\n  //\n  // hook frame\n  //\n  hook.prop(iframeProto, 'contentWindow',\n    getter => function() {\n      // TODO: origin check\n      const win = getter.call(this)\n      init(win)\n      return win\n    }\n  )\n\n  hook.prop(iframeProto, 'contentDocument',\n    getter => function() {\n      // TODO: origin check\n      const doc = getter.call(this)\n      if (doc) {\n        init(doc.defaultView)\n      }\n      return doc\n    }\n  )\n\n  //\n  // hook 超链接的 host、pathname 等属性\n  // 这类属性只有 property 没有 attribute\n  //\n  function hookAnchorUrlProp(proto) {\n    /**\n     * @param {string} key \n     */\n    function setupProp(key) {\n      hook.prop(proto, key,\n        getter => function() {\n          // 读取 href 时会经过 hook 处理，得到的已是原始 URL\n          const urlObj = new URL(this.href)\n          return urlObj[key]\n        },\n        setter => function(val) {\n          // console.log('[jsproxy] set link %s: %s', key, val)\n          const urlObj = new URL(this.href)\n          urlObj[key] = val\n          this.href = urlObj.href\n        }\n      )\n    }\n    setupProp('protocol')\n    setupProp('hostname')\n    setupProp('host')\n    setupProp('port')\n    setupProp('pathname')\n    setupProp('origin')\n  }\n  hookAnchorUrlProp(anchorProto)\n  hookAnchorUrlProp(areaProto)\n\n\n  // 该 form 可能没有经过 MutationObserver 处理\n  hook.func(formProto, 'submit', oldFn => function() {\n    this.action = this.action\n    return apply(oldFn, this, arguments)\n  })\n  \n\n  //\n  // 监控 离屏元素.click() 方式打开页面\n  // 例如：\n  //  var s = document.createElement('div')\n  //  s.innerHTML = '<a href=\"https://google.com\"><img></a>'\n  //  s.getElementsByTagName('img')[0].click()\n  //\n  const htmlProto = win['HTMLElement'].prototype\n\n  hook.func(htmlProto, 'click', oldFn => function() {\n    /** @type {HTMLAnchorElement} */\n    let el = this\n\n    // 添加到文档时已经过 MutationObserver 处理\n    // 无需调整 href 属性\n    if (el.isConnected) {\n      return\n    }\n    while (el) {\n      const tag = el.tagName\n      if (tag === 'A' || tag === 'AREA') {\n        // eslint-disable-next-line no-self-assign\n        el.href = el.href\n        break\n      }\n      // @ts-ignore\n      el = el.parentNode\n    }\n    return apply(oldFn, this, arguments)\n  })\n\n\n  //\n  // 脚本元素处理\n  //\n  /** @type {WeakMap<HTMLElement, string>} */\n  const integrityMap = new WeakMap()\n\n  /** @type {WeakMap<HTMLElement, string>} */\n  const charsetMap = new WeakMap()\n\n\n  domHook.attr('SCRIPT', scriptProto,\n  // 统一使用 UTF-8 编码\n  // JS 未提供 UTF-8 转非 UTF-8 的 API，导致编码转换比较麻烦，\n  // 因此 SW 将所有 JS 资源都转换成 UTF-8 编码。\n  {\n    name: 'charset',\n    onget(val) {\n      return charsetMap.get(this) || val\n    },\n    onset(val) {\n      if (!util.isUtf8(val)) {\n        val = 'utf-8'\n      }\n      charsetMap.set(this, val)\n      return val\n    }\n  },\n  // 禁止设置内容校验\n  //（调整静态 HTML 时控制台会有告警，但不会阻止运行）\n  {\n    name: 'integrity',\n    onget(val) {\n      return integrityMap.get(this) || ''\n    },\n    onset(val) {\n      integrityMap.set(this, val)\n      return ''\n    }\n  },\n  // 监控动态创建的脚本\n  //（设置 innerHTML 时同样会触发）\n  {\n    name: 'innerText',\n    onget(val) {\n      return val\n    },\n    onset(val, isInit) {\n      const ret = updateScriptText(this, val)\n      if (ret === null) {\n        return isInit ? hook.DROP : val\n      }\n      return ret\n    }\n  })\n\n  // text 属性只有 prop 没有 attr\n  hook.prop(scriptProto, 'text',\n    getter => function() {\n      return getter.call(this)\n    },\n    setter => function(val) {\n      const ret = updateScriptText(this, val)\n      if (ret === null) {\n        setter.call(this, val)\n      }\n      setter.call(this, ret)\n    }\n  )\n\n  \n  /** @type {WeakSet<HTMLScriptElement>} */\n  const parsedSet = new WeakSet()\n\n  /**\n   * @param {HTMLScriptElement} elem \n   */\n  function updateScriptText(elem, code) {\n    // 有些脚本仅用于存储数据（例如模块字符串），无需处理\n    const type = elem.type\n    if (type && !util.isJsMime(type)) {\n      return null\n    }\n    if (parsedSet.has(elem)) {\n      return null\n    }\n    parsedSet.add(elem)\n\n    return jsfilter.parseStr(code)\n  }\n\n  \n  /**\n   * 处理 <tag onevent=\"\"> 形式的脚本\n   * @param {string} eventName \n   */\n  function hookEvent(eventName) {\n    const scanedSet = new WeakSet()\n\n    function scanElement(el) {\n      if (scanedSet.has(el)) {\n        return\n      }\n      scanedSet.add(el)\n\n      // 非元素节点\n      if (el.nodeType != 1 /*Node.ELEMENT_NODE*/) {\n        return\n      }\n      // 扫描内联代码\n      if (el[eventName]) {\n        const code = el.getAttribute(eventName)\n        if (code) {\n          const ret = jsfilter.parseStr(code)\n          if (ret) {\n            el[eventName] = ret\n            console.log('[jsproxy] jsfilter onevent:', eventName)\n          }\n        }\n      }\n      // 扫描上级元素\n      scanElement(el.parentNode)\n    }\n\n    document.addEventListener(eventName.substr(2), e => {\n      scanElement(e.target)\n    }, true)\n  }\n\n  hookEvent('onerror')\n  hookEvent('onload')\n  hookEvent('onclick')\n  // Object.keys(htmlProto).forEach(v => {\n  //   if (v.startsWith('on')) {\n  //     hookEvent(v)\n  //   }\n  // })\n}\n"
  },
  {
    "path": "src/proxy/src/path.js",
    "content": "\nexport const ROOT = getRootPath() \nexport const HOME = ROOT + 'index.html'\nexport const CONF = ROOT + 'conf.js'\nexport const ICON = ROOT + 'favicon.ico'\nexport const HELPER = ROOT + '__sys__/helper.js'\nexport const ASSETS = ROOT + '__sys__/assets/'\nexport const PREFIX = ROOT + '-----'\n\n\nfunction getRootPath() {\n  //\n  // 如果运行在代理页面，当前路径：\n  //   https://example.com/path/to/-----url\n  // 如果运行在 SW，当前路径：\n  //   https://example.com/path/to/sw.js\n  // 如果运行在 Worker，当前路径：\n  //   __PATH__\n  // 返回：\n  //   https://example.com/path/to/\n  //\n  /** @type {string} */\n  const envPath = self['__PATH__']\n  if (envPath) {\n    return envPath\n  }\n  let url = location.href\n  const pos = url.indexOf('/-----http')\n  if (pos === -1) {\n    // sw\n    url = url.replace(/[^/]+$/, '')\n  } else {\n    // page\n    url = url.substr(0, pos)\n  }\n  return url.replace(/\\/*$/, '/')\n}"
  },
  {
    "path": "src/proxy/src/route.js",
    "content": "import * as urlx from './urlx.js'\nimport * as util from './util'\n\n\nlet mConf\nlet mNodeLinesMap\n\n/**\n * @param {number} urlHash \n * @param {string} id \n * @returns {string}\n */\nfunction getHostByNodeId(urlHash, id) {\n  let a = 0\n  for (const {weight, host} of mNodeLinesMap[id]) {\n    if ((a += weight) > urlHash) {\n      return host\n    }\n  }\n}\n\n\n/**\n * @param {string} host \n */\nfunction isLocalhost(host) {\n  return /^(localhost|127\\.\\d+\\.\\d+\\.\\d+)([:/]|$)/.test(host)\n}\n\n\n/**\n * @param {string} host \n * @param {string} scheme \n */\nexport function genUrl(host, scheme) {\n  const s = isLocalhost(host) ? '' : 's'\n  return `${scheme}${s}://${host}/${scheme}`\n}\n\n\n/**\n * @param {number} urlHash \n * @param {number} level \n */\nexport function getHost(urlHash, level) {\n  let node = mConf.node_default\n\n  // 实验中...\n  if (level === 2) {\n    node = mConf.node_acc\n  }\n\n  return getHostByNodeId(urlHash, node)\n}\n\n\n// export function setFailHost(host) {\n\n// }\n\n\n/**\n * @param {URL} urlObj \n * @param {Object<string, string>} args \n */\nexport function genWsUrl(urlObj, args) {\n  let scheme = 'https'\n\n  switch (urlObj.protocol) {\n  case 'wss:':\n    break\n  case 'ws:':\n    scheme = 'http'\n    break\n  default:\n    return null\n  }\n\n  const t = urlx.delScheme(urlx.delHash(urlObj.href))\n\n  args['url__'] = scheme + '://' + t\n  args['ver__'] = mConf.ver\n\n  const urlHash = util.strHash(urlObj.href)\n  const host = getHostByNodeId(urlHash, mConf.node_default)\n  return genUrl(host, 'ws') + '?' + new URLSearchParams(args)\n}\n\n\n/**\n * @param {object} conf \n */\nexport function setConf(conf) {\n  mConf = conf\n  mNodeLinesMap = {}\n\n  for (const [id, info] of Object.entries(conf.node_map)) {\n    const lines = []\n    let weightSum = 0\n\n    for (const [host, weight] of Object.entries(info.lines)) { \n      weightSum += weight\n      lines.push({host, weight})\n    }\n\n    // 权重值按比例转换成 0 ~ 2^32 之间的整数，方便后续计算\n    for (const v of lines) {\n      v.weight = (v.weight / weightSum * 0xFFFFFFFF) >>> 0\n    }\n    lines.sort((a, b) => b.weight - a.weight)\n\n    mNodeLinesMap[id] = lines\n  }\n}"
  },
  {
    "path": "src/proxy/src/signal.js",
    "content": "/**\n * Promise 简单封装\n * \n * 封装前\n * ```\n * function get(...) {\n *   return new Promise(function(resolve, reject) {\n *     ...\n *     function callback(err, result) {\n *       if (err) {\n *         reject(err)\n *       } else {\n *         resolve(result)\n *       }\n *     }\n *     ...\n *   }\n * }\n * ...\n * await get(...)\n * ```\n * \n * \n * 封装后\n * ```\n * function get(...) {\n *   ...\n *   const s = new Signal()\n *   function callback(err, result) {\n *     if (err) {\n *       s.abort(err)\n *     } else {\n *       s.notify(result)\n *     }\n *   }\n *   ...\n *   return s.wait()\n * }\n * ...\n * await get(...)\n * ```\n */\nexport class Signal {\n  constructor() {\n    this._promise = new Promise((resolve, reject) => {\n      this._resolve = resolve\n      this._reject = reject\n    })\n  }\n\n  wait() {\n    return this._promise\n  }\n\n  notify(arg) {\n    this._resolve(arg)\n  }\n\n  abort(arg) {\n    this._reject(arg)\n  }\n}\n"
  },
  {
    "path": "src/proxy/src/storage.js",
    "content": "import * as hook from './hook.js'\nimport * as urlx from './urlx.js'\n\n\nconst {\n  apply,\n  defineProperty,\n  ownKeys,\n  getOwnPropertyDescriptor,\n} = Reflect\n\nconst undefined = void 0\n\n\n/**\n * @param {WindowOrWorkerGlobalScope} win \n * @param {string} name \n * @param {string} prefix \n */\nfunction setup(win, name, prefix) {\n  /** @type {Storage} */\n  const raw = win[name]\n  if (!raw) {\n    return\n  }\n  const prefixLen = prefix.length\n\n  const nativeMap = {\n    getItem,\n    setItem,\n    removeItem,\n    clear,\n    key,\n    constructor: raw.constructor,\n    toString: () => raw.toString(),\n    [Symbol.toStringTag]: 'Storage',\n    get length() {\n      return getAllKeys().length\n    },\n  }\n  \n  /**\n   * @param {*} key \n   */\n  function getItem(key) {\n    return raw.getItem(prefix + key)\n  }\n\n  /**\n   * @param {*} key \n   * @param {string} val \n   */\n  function setItem(key, val) {\n    // TODO: 同步到 indexedDB\n    raw.setItem(prefix + key, val)\n  }\n\n  /**\n   * @param {*} key \n   */\n  function removeItem(key) {\n    return raw.removeItem(prefix + key)\n  }\n\n  function clear() {\n    getAllKeys().forEach(removeItem)\n  }\n\n  /**\n   * @param {*} val\n   */\n  function key(val) {\n    // TODO: 无需遍历所有\n    const arr = getAllKeys()\n    const ret = arr[val | 0]\n    if (ret === undefined) {\n      return null\n    }\n    return ret\n  }\n\n\n  /**\n   * @returns {string[]}\n   */\n  function getAllKeys() {\n    const ret = []\n    const keys = ownKeys(raw)\n    for (let i = 0; i < keys.length; i++) {\n      const key = keys[i]\n      if (typeof key !== 'string') {\n        continue\n      }\n      if (!key.startsWith(prefix)) {\n        continue\n      }\n      ret.push(key.substr(prefixLen))\n    }\n    return ret\n  }\n\n  const storage = new Proxy(raw, {\n    get(obj, key) {\n      const val = nativeMap[key]\n      if (val !== undefined) {\n        return val\n      }\n      console.log('[jsproxy] %s get: %s', name, key)\n      const ret = getItem(key)\n      if (ret === null) {\n        return undefined\n      }\n      return ret\n    },\n    set(obj, key, val) {\n      if (key in nativeMap) {\n        nativeMap[key] = val\n        return\n      }\n      console.log('[jsproxy] %s set: %s = %s', name, key, val)\n      setItem(key, val)\n      return true\n    },\n    deleteProperty(obj, key) {\n      console.log('[jsproxy] %s del: %s', name, key)\n      removeItem(key)\n      return true\n    },\n    has(obj, key) {\n      console.log('[jsproxy] %s has: %s', name, key)\n      if (typeof key === 'string') {\n        return (prefix + key) in obj\n      }\n      return false\n    },\n    // enumerate(obj) {\n    //   console.log('[jsproxy] %s enumerate: %s', name)\n    //   // TODO:\n    // },\n    ownKeys(obj) {\n      // console.log('[jsproxy] %s ownKeys', name)\n      return getAllKeys()\n    },\n    // defineProperty(obj, key, desc) {\n    //   // console.log('[jsproxy] %s defineProperty: %s', name, key)\n    //   // TODO:\n    // },\n    getOwnPropertyDescriptor(obj, key) {\n      // console.log('[jsproxy] %s getOwnPropertyDescriptor: %s', name, key)\n      if (typeof key === 'string') {\n        return getOwnPropertyDescriptor(raw, prefix + key)\n      }\n    }\n  })\n\n  defineProperty(win, name, {value: storage})\n}\n\n\n/**\n * @param {WindowOrWorkerGlobalScope} global \n * @param {string} origin \n */\nexport function createStorage(global, origin) {\n  const prefixStr = origin + '$'\n  const prefixLen = prefixStr.length\n\n\n  function delPrefix(str) {\n    return str.substr(prefixLen)\n  }\n\n  function delPrefixGetter(oldFn) {\n    return function() {\n      const val = oldFn.call(this)\n      return val && delPrefix(val)\n    }\n  }\n\n  //\n  // Web Storage\n  //\n  setup(global, 'localStorage', prefixStr)\n  setup(global, 'sessionStorage', prefixStr)\n\n  const StorageEventProto = global['StorageEvent'].prototype\n\n  hook.prop(StorageEventProto, 'key', delPrefixGetter)\n  hook.prop(StorageEventProto, 'url',\n    getter => function() {\n      const val = getter.call(this)\n      return urlx.decUrlStrAbs(val)\n    }\n  )\n  // TODO: StorageEventProto.storageArea\n\n  //\n  // Storage API\n  //\n  function addPrefixHook(oldFn) {\n    return function(name) {\n      if (arguments.length > 0) {\n        arguments[0] = prefixStr + name\n      }\n      return apply(oldFn, this, arguments)\n    }\n  }\n\n  // indexedDB\n  const IDBFactoryProto = global['IDBFactory'].prototype\n  hook.func(IDBFactoryProto, 'open', addPrefixHook)\n\n  hook.func(IDBFactoryProto, 'databases', oldFn => async function() {\n    /** @type { {name: string, version: number}[] } */\n    const arr = await apply(oldFn, this, arguments)\n    const ret = []\n    for (const v of arr) {\n      if (v.name[0] !== '.') {\n        v.name = delPrefix(v.name)\n        ret.push(v)\n      }\n    }\n    return ret\n  })\n\n  // delete\n  hook.func(IDBFactoryProto, 'deleteDatabase', addPrefixHook)\n\n  const IDBDatabaseProto = global['IDBDatabase'].prototype\n  hook.prop(IDBDatabaseProto, 'name', delPrefixGetter)\n\n\n  // Cache Storage\n  const cacheStorageProto = global['CacheStorage'].prototype\n  hook.func(cacheStorageProto, 'open', addPrefixHook)\n\n  hook.func(cacheStorageProto, 'keys', oldFn => async function() {\n    /** @type {string[]} */\n    const arr = await apply(oldFn, this, arguments)\n    const ret = []\n    for (const v of arr) {\n      if (v[0] !== '.') {\n        ret.push(delPrefix(v))\n      }\n    }\n    return ret\n  })\n\n  hook.func(cacheStorageProto, 'delete', addPrefixHook)\n\n  // WebSQL\n  hook.func(global, 'openDatabase', addPrefixHook)\n}"
  },
  {
    "path": "src/proxy/src/sw.js",
    "content": "import * as path from './path.js'\nimport * as route from './route.js'\nimport * as urlx from './urlx.js'\nimport * as util from './util.js'\nimport * as cookie from './cookie.js'\nimport * as network from './network.js'\nimport * as MSG from './msg.js'\nimport * as jsfilter from './jsfilter.js'\nimport * as inject from './inject.js'\nimport {Signal} from './signal.js'\nimport {Database} from './database.js'\n\n\nconst CONF_UPDATE_TIMER = 1000 * 60 * 5\n\nlet mConf\nconst MAX_REDIR = 5\n\n/** @type {ServiceWorkerGlobalScope} */\n// @ts-ignore\nconst global = self\nconst clients = global.clients\n\nlet mUrlHandler\n\n\n/**\n * @param {*} target \n * @param {number} cmd \n * @param {*=} val \n */\nfunction sendMsg(target, cmd, val) {\n  if (target) {\n    target.postMessage([cmd, val])\n  } else {\n    console.warn('invalid target', cmd, val)\n  }\n}\n\n\n// 也可以用 clientId 关联，但兼容性不高\nlet pageCounter = 0\n\n/** @type {Map<number, [Signal, number]>} */\nconst pageWaitMap = new Map()\n\nfunction genPageId() {\n  return ++pageCounter\n}\n\n/**\n * @param {number} pageId \n */\nfunction pageWait(pageId) {\n  const s = new Signal()\n  // 设置最大等待时间\n  // 有些页面不会执行 JS（例如查看源文件），导致永久等待\n  const timer = setTimeout(_ => {\n    pageWaitMap.delete(pageId)\n    s.notify(false)\n  }, 2000)\n\n  pageWaitMap.set(pageId, [s, timer])\n  return s.wait()\n}\n\n/**\n * @param {number} id \n * @param {boolean} isDone \n */\nfunction pageNotify(id, isDone) {\n  const arr = pageWaitMap.get(id)\n  if (!arr) {\n    console.warn('[jsproxy] unknown page id:', id)\n    return\n  }\n  const [s, timer] = arr\n  if (isDone) {\n    pageWaitMap.delete(id)\n    s.notify(true)\n  } else {\n    // 页面已开始初始化，关闭定时器\n    clearTimeout(timer)\n  }\n}\n\n\nfunction makeHtmlRes(body, status = 200) {\n  return new Response(body, {\n    status,\n    headers: {\n      'content-type': 'text/html; charset=utf-8',\n    }\n  })\n}\n\n\n/**\n * @param {Response} res \n * @param {ResponseInit} resOpt \n * @param {URL} urlObj \n */\nfunction processHtml(res, resOpt, urlObj) {\n  const reader = res.body.getReader()\n  let injected = false\n\n  const stream = new ReadableStream({\n    async pull(controller) {\n      if (!injected) {\n        injected = true\n\n        // 注入页面顶部的代码\n        const pageId = genPageId()\n        const buf = inject.getHtmlCode(urlObj, pageId)\n        controller.enqueue(buf)\n\n        // 留一些时间给页面做异步初始化\n        const done = await pageWait(pageId)\n        if (!done) {\n          console.warn('[jsproxy] page wait timeout. id: %d url: %s',\n            pageId, urlObj.href)\n        }\n      }\n      const r = await reader.read()\n      if (r.done) {\n        controller.close()\n      } else {\n        controller.enqueue(r.value)\n      }\n    }\n  })\n  return new Response(stream, resOpt)\n}\n\n\n/**\n * @param {ArrayBuffer} buf \n * @param {string} charset \n */\nfunction processJs(buf, charset) {\n  const u8 = new Uint8Array(buf)\n  const ret = jsfilter.parseBin(u8, charset) || u8\n  return util.concatBufs([inject.getWorkerCode(), ret])\n}\n\n\n/**\n * @param {*} cmd \n * @param {*} msg \n * @param {string=} srcId\n */\nasync function sendMsgToPages(cmd, msg, srcId) {\n  // 通知页面更新 Cookie\n  const pages = await clients.matchAll({type: 'window'})\n\n  for (const page of pages) {\n    if (page.frameType !== 'top-level') {\n      continue\n    }\n    if (srcId && page.id === srcId) {\n      continue\n    }\n    sendMsg(page, cmd, msg)\n  }\n}\n\n\n/** @type Map<string, string> */\nconst mIdUrlMap = new Map()\n\n/**\n * @param {string} id \n */\nasync function getUrlByClientId(id) {\n  const client = await clients.get(id)\n  if (!client) {\n    return\n  }\n  const urlStr = urlx.decUrlStrAbs(client.url)\n  mIdUrlMap.set(id, urlStr)\n  return urlStr\n}\n\n\n/**\n * @param {string} jsonStr \n * @param {number} status \n * @param {URL} urlObj \n */\nfunction parseGatewayError(jsonStr, status, urlObj) {\n  let ret = ''\n  const {\n    msg, addr, url\n  } = JSON.parse(jsonStr)\n\n  switch (status) {\n  case 204:\n    switch (msg) {\n    case 'ORIGIN_NOT_ALLOWED':\n      ret = '当前域名不在服务器外链白名单'\n      break\n    case 'CIRCULAR_DEPENDENCY':\n      ret = '当前请求出现循环代理'\n      break\n    case 'SITE_MOVE':\n      ret = `当前站点移动到: <a href=\"${url}\">${url}</a>`\n      break\n    }\n    break\n  case 500:\n    ret = '代理服务器内部错误'\n    break\n  case 502:\n    if (addr) {\n      ret = `代理服务器无法连接网站 ${urlObj.origin} (${addr})`\n    } else {\n      ret = `代理服务器无法解析域名 ${urlObj.host}`\n    }\n    break\n  case 504:\n    ret = `代理服务器连接网站超时 ${urlObj.origin}`\n    if (addr) {\n      ret += ` (${addr})`\n    }\n    break\n  }\n  return makeHtmlRes(ret)\n}\n\n\n/**\n * @param {Request} req \n * @param {URL} urlObj\n * @param {URL} cliUrlObj \n * @param {number} redirNum\n * @returns {Promise<Response>}\n */\nasync function forward(req, urlObj, cliUrlObj, redirNum) {\n  const r = await network.launch(req, urlObj, cliUrlObj)\n  if (!r) {\n    return makeHtmlRes('load fail')\n  }\n  let {\n    res, status, headers, cookies\n  } = r\n\n  if (cookies) {\n    sendMsgToPages(MSG.SW_COOKIE_PUSH, cookies)\n  }\n\n  if (!status) {\n    status = res.status || 200\n  }\n\n  let headersMutable = true\n  if (!headers) {\n    headers = res.headers\n    headersMutable = false\n  }\n\n  /**\n   * @param {string} k \n   * @param {string} v \n   */\n  const setHeader = (k, v) => {\n    if (!headersMutable) {\n      headers = new Headers(headers)\n      headersMutable = true\n    }\n    headers.set(k, v)\n  }\n\n  // 网关错误\n  const gwErr = headers.get('gateway-err--')\n  if (gwErr) {\n    return parseGatewayError(gwErr, status, urlObj)\n  }\n\n  /** @type {ResponseInit} */\n  const resOpt = {status, headers}\n\n  // 空响应\n  // https://fetch.spec.whatwg.org/#statuses\n  if (status === 101 ||\n      status === 204 ||\n      status === 205 ||\n      status === 304\n  ) {\n    return new Response(null, resOpt)\n  }\n\n  // 处理重定向\n  if (status === 301 ||\n      status === 302 ||\n      status === 303 ||\n      status === 307 ||\n      status === 308\n  ) {\n    const locStr = headers.get('location')\n    const locObj = locStr && urlx.newUrl(locStr, urlObj)\n    if (locObj) {\n      // 跟随模式，返回最终数据\n      if (req.redirect === 'follow') {\n        if (++redirNum === MAX_REDIR) {\n          return makeHtmlRes('重定向过多', 500)\n        }\n        return forward(req, locObj, cliUrlObj, redirNum)\n      }\n      // 不跟随模式（例如页面跳转），返回 30X 状态\n      setHeader('location', urlx.encUrlObj(locObj))\n    }\n\n    // firefox, safari 保留内容会提示页面损坏\n    return new Response(null, resOpt)\n  }\n\n  //\n  // 提取 mime 和 charset（不存在则为 undefined）\n  // 可能存在多个段，并且值可能包含引号。例如：\n  // content-type: text/html; ...; charset=\"gbk\"\n  //\n  const ctVal = headers.get('content-type') || ''\n  const [, mime, charset] = ctVal\n    .toLocaleLowerCase()\n    .match(/([^;]*)(?:.*?charset=['\"]?([^'\"]+))?/)\n\n\n  const type = req.destination\n  if (type === 'script' ||\n      type === 'worker' ||\n      type === 'sharedworker'\n  ) {\n    const buf = await res.arrayBuffer()\n    const ret = processJs(buf, charset)\n\n    setHeader('content-type', 'text/javascript')\n    return new Response(ret, resOpt)\n  }\n\n  if (req.mode === 'navigate' && mime === 'text/html') {\n    return processHtml(res, resOpt, urlObj)\n  }\n\n  return new Response(res.body, resOpt)\n}\n\n\nasync function proxy(e, urlObj) {\n  // 使用 e.resultingClientId 有问题\n  const id = e.clientId\n  let cliUrlStr\n  if (id) {\n    cliUrlStr = mIdUrlMap.get(id) || await getUrlByClientId(id)\n  }\n  if (!cliUrlStr) {\n    cliUrlStr = urlObj.href\n  }\n  const cliUrlObj = new URL(cliUrlStr)\n\n  try {\n    return await forward(e.request, urlObj, cliUrlObj, 0)\n  } catch (err) {\n    console.error(err)\n    return makeHtmlRes('前端脚本错误<br><pre>' + err.stack + '</pre>', 500)\n  }\n}\n\n/** @type {Database} */\nlet mDB\n\nasync function initDB() {\n  mDB = new Database('.sys')\n  await mDB.open({\n    'url-cache': {\n      keyPath: 'url'\n    },\n    'cookie': {\n      keyPath: 'id'\n    }\n  })\n\n  await network.setDB(mDB)\n  await cookie.setDB(mDB)\n}\n\n\n/**\n * @param {FetchEvent} e \n */\nasync function onFetch(e) {\n  if (!mConf) {\n    await initConf()\n  }\n  // TODO: 逻辑优化\n  if (!mDB) {\n    await initDB()\n  }\n  const req = e.request\n  const urlStr = urlx.delHash(req.url)\n\n  // 首页（例如 https://zjcqoo.github.io/）\n  if (urlStr === path.ROOT || urlStr === path.HOME) {\n    let indexPath = mConf.assets_cdn + mConf.index_path\n    if (!mConf.index_path) {\n      // 临时代码。防止配置文件未更新的情况下首页无法加载\n      indexPath = mConf.assets_cdn + 'index_v3.html'\n    }\n    const res = await fetch(indexPath)\n    return makeHtmlRes(res.body)\n  }\n\n  // 图标、配置（例如 https://zjcqoo.github.io/conf.js）\n  if (urlStr === path.CONF || urlStr === path.ICON) {\n    return fetch(urlStr)\n  }\n\n  // 注入页面的脚本（例如 https://zjcqoo.github.io/__sys__/helper.js）\n  if (urlStr === path.HELPER) {\n    return fetch(self['__FILE__'])\n  }\n\n  // 静态资源（例如 https://zjcqoo.github.io/__sys__/assets/ico/google.png）\n  if (urlStr.startsWith(path.ASSETS)) {\n    const filePath = urlStr.substr(path.ASSETS.length)\n    return fetch(mConf.assets_cdn + filePath)\n  }\n\n  if (req.mode === 'navigate') {\n    const newUrl = urlx.adjustNav(urlStr)\n    if (newUrl) {\n      return Response.redirect(newUrl, 301)\n    }\n  }\n\n  let targetUrlStr = urlx.decUrlStrAbs(urlStr)\n  \n  const handler = mUrlHandler[targetUrlStr]\n  if (handler) {\n    const {\n      redir,\n      content,\n      replace,\n    } = handler\n\n    if (redir) {\n      return Response.redirect('/-----' + redir)\n    }\n    if (content) {\n      return makeHtmlRes(content)\n    }\n    if (replace) {\n      targetUrlStr = replace\n    }\n  }\n\n  const targetUrlObj = urlx.newUrl(targetUrlStr)\n\n  if (targetUrlObj) {\n    return proxy(e, targetUrlObj)\n  }\n  return makeHtmlRes('invalid url: ' + targetUrlStr, 500)\n}\n\n\nfunction parseUrlHandler(handler) {\n  const map = {}\n  if (!handler) {\n    return map\n  }\n  for (const [match, rule] of Object.entries(handler)) {\n    // TODO: 支持通配符和正则\n    map[match] = rule\n  }\n  return map\n}\n\n// TODO: 逻辑优化\nfunction updateConf(conf, force) {\n  if (!force && mConf) {\n    if (conf.ver <= mConf.ver) {\n      return\n    }\n    if (conf.node_map[mConf.node_default]) {\n      conf.node_default = mConf.node_default\n    } else {\n      console.warn('default node %s -> %s',\n        mConf.node_default, conf.node_default)\n    }\n    sendMsgToPages(MSG.SW_CONF_CHANGE, mConf)\n  }\n  inject.setConf(conf)\n  route.setConf(conf)\n  network.setConf(conf)\n\n  mUrlHandler = parseUrlHandler(conf.url_handler)\n  /*await*/ saveConf(conf)\n\n  mConf = conf\n}\n\n\nasync function readConf() {\n  const cache = await caches.open('.sys')\n  const req = new Request('/conf.json')\n  const res = await cache.match(req)\n  if (res) {\n    return res.json()\n  }\n}\n\nasync function saveConf(conf) {\n  const json = JSON.stringify(conf)\n  const cache = await caches.open('.sys')\n  const req = new Request('/conf.json')\n  const res = new Response(json);\n  return cache.put(req, res)\n}\n\nasync function loadConf() {\n  const res = await fetch('conf.js')\n  const txt = await res.text()\n  self['jsproxy_config'] = updateConf\n  Function(txt)()\n}\n\n\n/** @type {Signal[]} */\nlet mConfInitQueue\n\nasync function initConf() {\n  if (mConfInitQueue) {\n    const s = new Signal()\n    mConfInitQueue.push(s)\n    return s.wait()\n  }\n  mConfInitQueue = []\n\n  let conf\n  try {\n    conf = await readConf()\n  } catch (err) {\n    console.warn('load conf fail:', err)\n  }\n  if (!conf) {\n    conf = self['__CONF__']\n  }\n  if (conf) {\n    updateConf(conf)\n  } else {\n    conf = await loadConf()\n  }\n\n  // 定期更新配置\n  setInterval(loadConf, CONF_UPDATE_TIMER)\n\n  mConfInitQueue.forEach(s => s.notify())\n  mConfInitQueue = null\n}\n\n\nglobal.addEventListener('fetch', e => {\n  e.respondWith(onFetch(e))\n})\n\n\nglobal.addEventListener('message', e => {\n  // console.log('sw msg:', e.data)\n  const [cmd, val] = e.data\n  const src = e.source\n\n  switch (cmd) {\n  case MSG.PAGE_COOKIE_PUSH:\n    cookie.set(val)\n    // @ts-ignore\n    sendMsgToPages(MSG.SW_COOKIE_PUSH, [val], src.id)\n    break\n\n  case MSG.PAGE_INFO_PULL:\n    // console.log('SW MSG.COOKIE_PULL:', src.id)\n    sendMsg(src, MSG.SW_INFO_PUSH, {\n      cookies: cookie.getNonHttpOnlyItems(),\n      conf: mConf,\n    })\n    break\n\n  case MSG.PAGE_INIT_BEG:\n    // console.log('SW MSG.PAGE_INIT_BEG:', val)\n    pageNotify(val, false)\n    break\n\n  case MSG.PAGE_INIT_END:\n    // console.log('SW MSG.PAGE_INIT_END:', val)\n    pageNotify(val, true)\n    break\n\n  case MSG.PAGE_CONF_GET:\n    if (mConf) {\n      sendMsg(src, MSG.SW_CONF_RETURN, mConf)\n    } else {\n      initConf().then(_ => {\n        sendMsg(src, MSG.SW_CONF_RETURN, mConf)\n      })\n    }\n    break\n\n  case MSG.PAGE_CONF_SET:\n    updateConf(val, true)\n    sendMsgToPages(MSG.SW_CONF_CHANGE, mConf)\n    break\n\n  case MSG.PAGE_RELOAD_CONF:\n    /*await*/ loadConf()\n    break\n\n  case MSG.PAGE_READY_CHECK:\n    sendMsg(src, MSG.SW_READY)\n    /*await*/ loadConf()\n    break\n  }\n})\n\n\nglobal.addEventListener('install', e => {\n  console.log('oninstall:', e)\n  e.waitUntil(global.skipWaiting())\n})\n\n\nglobal.addEventListener('activate', e => {\n  console.log('onactivate:', e)\n  sendMsgToPages(MSG.SW_READY, 1)\n\n  e.waitUntil(clients.claim())\n})\n\n\nconsole.log('[jsproxy] sw inited')\n"
  },
  {
    "path": "src/proxy/src/tld-data.js",
    "content": "// THIS FILE WAS GENERATED BY './tools/tld/gen.js'\nexport default '0.bg,001www.com,0emm.com,1.bg,12hp.at,12hp.ch,12hp.de,1337.pictures,16-b.it,1kapp.com,2.bg,2000.hu,2038.io,2ix.at,2ix.ch,2ix.de,3.bg,32-b.it,3utilities.com,4.bg,4lima.at,4lima.ch,4lima.de,4u.com,5.bg,6.bg,64-b.it,7.bg,8.bg,9.bg,9guacu.br,a.bg,a.prod.fastly.net,a.run.app,a.se,a.ssl.fastly.net,aa.no,aaa,aaa.pro,aarborte.no,aarp,ab.ca,abarth,abashiri.hokkaido.jp,abb,abbott,abbvie,abc,abc.br,abeno.osaka.jp,abiko.chiba.jp,abira.hokkaido.jp,abkhazia.su,able,abo.pa,abogado,abr.it,abruzzo.it,abu.yamaguchi.jp,abudhabi,ac,ac.ae,ac.at,ac.be,ac.ci,ac.cn,ac.cr,ac.cy,ac.gn,ac.gov.br,ac.id,ac.il,ac.im,ac.in,ac.ir,ac.jp,ac.ke,ac.kr,ac.leg.br,ac.lk,ac.ls,ac.ma,ac.me,ac.mu,ac.mw,ac.mz,ac.ni,ac.nz,ac.pa,ac.pr,ac.rs,ac.ru,ac.rw,ac.se,ac.sz,ac.th,ac.tj,ac.tz,ac.ug,ac.uk,ac.vn,ac.za,ac.zm,ac.zw,aca.pro,academia.bo,academy,academy.museum,accenture,accesscam.org,accident-investigation.aero,accident-prevention.aero,accountant,accountants,acct.pro,achi.nagano.jp,aco,act.au,act.edu.au,actor,ad,ad.jp,adac,adachi.tokyo.jp,adm.br,ads,adult,adult.ht,adv.br,adv.mz,advisor.ws,adygeya.ru,adygeya.su,ae,ae.org,aeg,aejrie.no,aero,aero.mv,aero.tt,aerobatic.aero,aeroclub.aero,aerodrome.aero,aeroport.fr,aetna,af,afamilycompany,afjord.no,afl,africa,africa.com,ag,ag.it,aga.niigata.jp,agakhan,agano.niigata.jp,agdenes.no,agematsu.nagano.jp,agency,agents.aero,agr.br,agrar.hu,agric.za,agriculture.museum,agrigento.it,agrinet.tn,agro.bo,agro.pl,aguni.okinawa.jp,ah.cn,ah.no,ai,aibetsu.hokkaido.jp,aichi.jp,aid.pl,aig,aigo,aikawa.kanagawa.jp,ainan.ehime.jp,aioi.hyogo.jp,aip.ee,air-surveillance.aero,air-traffic-control.aero,air.museum,airbus,aircraft.aero,airforce,airguard.museum,airline.aero,airport.aero,airtel,airtraffic.aero,aisai.aichi.jp,aisho.shiga.jp,aizubange.fukushima.jp,aizumi.tokushima.jp,aizumisato.fukushima.jp,aizuwakamatsu.fukushima.jp,aju.br,ak.us,akabira.hokkaido.jp,akagi.shimane.jp,akaiwa.okayama.jp,akashi.hyogo.jp,akdn,aki.kochi.jp,akiruno.tokyo.jp,akishima.tokyo.jp,akita.akita.jp,akita.jp,akkeshi.hokkaido.jp,aknoluokta.no,ako.hyogo.jp,akrehamn.no,aktyubinsk.su,akune.kagoshima.jp,al,al.eu.org,al.gov.br,al.it,al.leg.br,al.no,al.us,alabama.museum,alaheadju.no,aland.fi,alaska.museum,alces.network,alessandria.it,alesund.no,alfaromeo,algard.no,alibaba,alipay,allfinanz,allstate,ally,alpha-myqnapcloud.com,alpha.bounty-full.com,alsace,alstahaug.no,alstom,alt.za,alta.no,alto-adige.it,altoadige.it,alvdal.no,alwaysdata.net,am,am.br,am.gov.br,am.leg.br,ama.aichi.jp,ama.shimane.jp,amagasaki.hyogo.jp,amakusa.kumamoto.jp,amami.kagoshima.jp,amber.museum,ambulance.aero,ambulance.museum,american.museum,americana.museum,americanantiques.museum,americanart.museum,americanexpress,americanfamily,amex,amfam,ami.ibaraki.jp,amica,amli.no,amot.no,amsterdam,amsterdam.museum,amusement.aero,an.it,analytics,anamizu.ishikawa.jp,anan.nagano.jp,anan.tokushima.jp,anani.br,ancona.it,and.mom,and.museum,andasuolo.no,andebu.no,ando.nara.jp,andoy.no,andria-barletta-trani.it,andria-trani-barletta.it,andriabarlettatrani.it,andriatranibarletta.it,android,andøy.no,anjo.aichi.jp,ann-arbor.mi.us,annaka.gunma.jp,annefrank.museum,anpachi.gifu.jp,anquan,anthro.museum,anthropology.museum,antiques.museum,anz,ao,ao.it,aogaki.hyogo.jp,aogashima.tokyo.jp,aoki.nagano.jp,aol,aomori.aomori.jp,aomori.jp,aosta-valley.it,aosta.it,aostavalley.it,aoste.it,ap-northeast-1.elasticbeanstalk.com,ap-northeast-2.elasticbeanstalk.com,ap-northeast-3.elasticbeanstalk.com,ap-south-1.elasticbeanstalk.com,ap-southeast-1.elasticbeanstalk.com,ap-southeast-2.elasticbeanstalk.com,ap.gov.br,ap.gov.pl,ap.it,ap.leg.br,aparecida.br,apartments,api.stdlib.com,apigee.io,app,app.banzaicloud.io,app.lmpm.com,app.os.fedoraproject.org,app.os.stg.fedoraproject.org,app.render.com,appchizi.com,apple,applicationcloud.io,applinzi.com,apps.fbsbx.com,apps.lair.io,appspot.com,aq,aq.it,aquarelle,aquarium.museum,aquila.it,ar,ar.com,ar.it,ar.us,arab,arai.shizuoka.jp,arakawa.saitama.jp,arakawa.tokyo.jp,aramco,arao.kumamoto.jp,arboretum.museum,archaeological.museum,archaeology.museum,archi,architecture.museum,ardal.no,aremark.no,arendal.no,arezzo.it,ariake.saga.jp,arida.wakayama.jp,aridagawa.wakayama.jp,arita.saga.jp,arkhangelsk.su,armenia.su,army,arna.no,arpa,arq.br,art,art.br,art.do,art.dz,art.ht,art.museum,art.pl,art.sn,artanddesign.museum,artcenter.museum,artdeco.museum,arte,arte.bo,arteducation.museum,artgallery.museum,arts.co,arts.museum,arts.nf,arts.ro,arts.ve,artsandcrafts.museum,arvo.network,as,as.us,asago.hyogo.jp,asahi.chiba.jp,asahi.ibaraki.jp,asahi.mie.jp,asahi.nagano.jp,asahi.toyama.jp,asahi.yamagata.jp,asahikawa.hokkaido.jp,asaka.saitama.jp,asakawa.fukushima.jp,asakuchi.okayama.jp,asaminami.hiroshima.jp,ascoli-piceno.it,ascolipiceno.it,asda,aseral.no,ashgabad.su,ashibetsu.hokkaido.jp,ashikaga.tochigi.jp,ashiya.fukuoka.jp,ashiya.hyogo.jp,ashoro.hokkaido.jp,asia,asker.no,askim.no,askoy.no,askvoll.no,askøy.no,asmatart.museum,asn.au,asn.lv,asnes.no,aso.kumamoto.jp,ass.km,assabu.hokkaido.jp,assassination.museum,assisi.museum,assn.lk,asso.bj,asso.ci,asso.dz,asso.eu.org,asso.fr,asso.gp,asso.ht,asso.km,asso.mc,asso.nc,asso.re,associates,association.aero,association.museum,asti.it,astronomy.museum,asuke.aichi.jp,at,at-band-camp.net,at.eu.org,at.it,atami.shizuoka.jp,ath.cx,athleta,atlanta.museum,atm.pl,ato.br,atsugi.kanagawa.jp,atsuma.hokkaido.jp,attorney,au,au.eu.org,auction,audi,audible,audio,audnedaln.no,augustow.pl,aukra.no,aure.no,aurland.no,aurskog-holand.no,aurskog-høland.no,auspost,austevoll.no,austin.museum,australia.museum,austrheim.no,author,author.aero,auto,auto.pl,automotive.museum,autos,av.it,av.tr,avellino.it,averoy.no,averøy.no,avianca,aviation.museum,avocat.fr,avocat.pro,avoues.fr,aw,awaji.hyogo.jp,awdev.ca,aws,ax,axa,axis.museum,aya.miyazaki.jp,ayabe.kyoto.jp,ayagawa.kagawa.jp,ayase.kanagawa.jp,az,az.us,azerbaijan.su,azimuth.network,azumino.nagano.jp,azure,azure-mobile.net,azurecontainer.io,azurewebsites.net,aéroport.ci,b-data.io,b.bg,b.br,b.se,b.ssl.fastly.net,ba,ba.gov.br,ba.it,ba.leg.br,babia-gora.pl,baby,backplaneapp.io,badaddja.no,badajoz.museum,baghdad.museum,bahcavuotna.no,bahccavuotna.no,bahn.museum,baidar.no,baidu,bajddar.no,balashov.su,balat.no,bale.museum,balena-devices.com,balestrand.no,ballangen.no,ballooning.aero,balsan-sudtirol.it,balsan-suedtirol.it,balsan-südtirol.it,balsan.it,balsfjord.no,baltimore.museum,bamble.no,banamex,bananarepublic,band,bandai.fukushima.jp,bando.ibaraki.jp,bank,bar,bar.pro,barcelona,barcelona.museum,barclaycard,barclays,bardu.no,barefoot,bargains,bari.it,barletta-trani-andria.it,barlettatraniandria.it,barreau.bj,barrel-of-knowledge.info,barrell-of-knowledge.info,barsy.bg,barsy.ca,barsy.club,barsy.co.uk,barsy.de,barsy.eu,barsy.in,barsy.info,barsy.io,barsy.me,barsy.menu,barsy.mobi,barsy.net,barsy.online,barsy.org,barsy.pro,barsy.pub,barsy.shop,barsy.site,barsy.support,barsy.uk,barsycenter.com,barsyonline.co.uk,barsyonline.com,barueri.br,barum.no,bas.it,baseball,baseball.museum,basel.museum,bashkiria.ru,bashkiria.su,basicserver.io,basilicata.it,basketball,baths.museum,bato.tochigi.jp,batsfjord.no,bauern.museum,bauhaus,bayern,bb,bbc,bbs.tr,bbt,bbva,bc.ca,bcg,bci.dnstrace.pro,bcn,bd,bd.se,be,be.eu.org,bearalvahki.no,bearalváhki.no,beardu.no,beats,beauty,beauxarts.museum,bedzin.pl,beeldengeluid.museum,beep.pl,beer,beiarn.no,bel.tr,belau.pw,belem.br,bellevue.museum,belluno.it,benevento.it,bentley,beppu.oita.jp,berg.no,bergamo.it,bergbau.museum,bergen.no,berkeley.museum,berlevag.no,berlevåg.no,berlin,berlin.museum,bern.museum,beskidy.pl,best,bestbuy,bet,beta.bounty-full.com,betainabox.com,better-than.tv,bf,bg,bg.eu.org,bg.it,bh,bharti,bhz.br,bi,bi.it,bialowieza.pl,bialystok.pl,bibai.hokkaido.jp,bible,bible.museum,bid,biei.hokkaido.jp,bielawa.pl,biella.it,bieszczady.pl,bievat.no,bievát.no,bifuka.hokkaido.jp,bihoro.hokkaido.jp,bike,bilbao.museum,bill.museum,bindal.no,bing,bingo,bio,bio.br,bir.ru,biratori.hokkaido.jp,birdart.museum,birkenes.no,birthplace.museum,bitballoon.com,biz,biz.at,biz.az,biz.bb,biz.cy,biz.dk,biz.et,biz.gl,biz.id,biz.ki,biz.ls,biz.mv,biz.mw,biz.ni,biz.nr,biz.pk,biz.pl,biz.pr,biz.tj,biz.tr,biz.tt,biz.ua,biz.vn,biz.zm,bizen.okayama.jp,bj,bj.cn,bjarkoy.no,bjarkøy.no,bjerkreim.no,bjugn.no,bl.it,black,blackbaudcdn.net,blackfriday,blockbuster,blog,blog.bo,blog.br,blogdns.com,blogdns.net,blogdns.org,blogsite.org,blogsite.xyz,blogspot.ae,blogspot.al,blogspot.am,blogspot.ba,blogspot.be,blogspot.bg,blogspot.bj,blogspot.ca,blogspot.cf,blogspot.ch,blogspot.cl,blogspot.co.at,blogspot.co.id,blogspot.co.il,blogspot.co.ke,blogspot.co.nz,blogspot.co.uk,blogspot.co.za,blogspot.com,blogspot.com.ar,blogspot.com.au,blogspot.com.br,blogspot.com.by,blogspot.com.co,blogspot.com.cy,blogspot.com.ee,blogspot.com.eg,blogspot.com.es,blogspot.com.mt,blogspot.com.ng,blogspot.com.tr,blogspot.com.uy,blogspot.cv,blogspot.cz,blogspot.de,blogspot.dk,blogspot.fi,blogspot.fr,blogspot.gr,blogspot.hk,blogspot.hr,blogspot.hu,blogspot.ie,blogspot.in,blogspot.is,blogspot.it,blogspot.jp,blogspot.kr,blogspot.li,blogspot.lt,blogspot.lu,blogspot.md,blogspot.mk,blogspot.mr,blogspot.mx,blogspot.my,blogspot.nl,blogspot.no,blogspot.pe,blogspot.pt,blogspot.qa,blogspot.re,blogspot.ro,blogspot.rs,blogspot.ru,blogspot.se,blogspot.sg,blogspot.si,blogspot.sk,blogspot.sn,blogspot.td,blogspot.tw,blogspot.ug,blogspot.vn,blogsyte.com,bloomberg,bloxcms.com,blue,bm,bmd.br,bmoattachments.org,bms,bmw,bn,bn.it,bnl,bnpparibas,bnr.la,bo,bo.it,bo.nordland.no,bo.telemark.no,boats,boavista.br,bodo.no,bodø.no,boehringer,bofa,bokn.no,boldlygoingnowhere.org,boleslawiec.pl,bolivia.bo,bologna.it,bolt.hu,bolzano-altoadige.it,bolzano.it,bom,bomlo.no,bond,bonn.museum,boo,book,booking,boomla.net,bosch,bostik,boston,boston.museum,bot,botanical.museum,botanicalgarden.museum,botanicgarden.museum,botany.museum,bounceme.net,bounty-full.com,boutique,box,boxfuse.io,bozen-sudtirol.it,bozen-suedtirol.it,bozen-südtirol.it,bozen.it,bpl.biz,bplaced.com,bplaced.de,bplaced.net,br,br.com,br.it,bradesco,brand.se,brandywinevalley.museum,brasil.museum,brasilia.me,bremanger.no,brescia.it,bridgestone,brindisi.it,bristol.museum,british.museum,britishcolumbia.museum,broadcast.museum,broadway,broke-it.net,broker,broker.aero,bronnoy.no,bronnoysund.no,brother,browsersafetymark.io,brumunddal.no,brunel.museum,brussel.museum,brussels,brussels.museum,bruxelles.museum,bryansk.su,bryne.no,brønnøy.no,brønnøysund.no,bs,bs.it,bsb.br,bss.design,bt,bt.it,bu.no,budapest,budejju.no,bugatti,build,builders,building.museum,bukhara.su,bulsan-sudtirol.it,bulsan-suedtirol.it,bulsan-südtirol.it,bulsan.it,bungoono.oita.jp,bungotakada.oita.jp,bunkyo.tokyo.jp,burghof.museum,bus.museum,busan.kr,bushey.museum,business,buy,buyshouses.net,buzen.fukuoka.jp,buzz,bv,bw,by,bydgoszcz.pl,byen.site,bygland.no,bykle.no,bytom.pl,bz,bz.it,bzh,bzz.dapps.earth,báhcavuotna.no,báhccavuotna.no,báidár.no,bájddar.no,bálát.no,bådåddjå.no,båtsfjord.no,bærum.no,bø.nordland.no,bø.telemark.no,bømlo.no,c.bg,c.cdn77.org,c.la,c.se,c66.me,ca,ca-central-1.elasticbeanstalk.com,ca.eu.org,ca.it,ca.na,ca.us,caa.aero,caa.li,cab,cable-modem.org,cadaques.museum,cafe,cagliari.it,cahcesuolo.no,cal,cal.it,calabria.it,california.museum,call,caltanissetta.it,calvinklein,cam,cam.it,cambridge.museum,camdvr.org,camera,camp,campania.it,campidano-medio.it,campidanomedio.it,campinagrande.br,campinas.br,campobasso.it,can.museum,canada.museum,cancerresearch,canon,capebreton.museum,capetown,capital,capitalone,car,caravan,carbonia-iglesias.it,carboniaiglesias.it,cards,care,career,careers,cargo.aero,carrara-massa.it,carraramassa.it,carrd.co,carrier.museum,cars,cartier,cartoonart.museum,casa,casacam.net,casadelamoneda.museum,case,caseih,caserta.it,cash,casino,casino.hu,castle.museum,castres.museum,cat,catania.it,catanzaro.it,catering,catering.aero,catholic,caxias.br,cb.it,cba,cbg.ru,cbn,cbre,cbs,cc,cc.ak.us,cc.al.us,cc.ar.us,cc.as.us,cc.az.us,cc.ca.us,cc.co.us,cc.ct.us,cc.dc.us,cc.de.us,cc.fl.us,cc.ga.us,cc.gu.us,cc.hi.us,cc.ia.us,cc.id.us,cc.il.us,cc.in.us,cc.ks.us,cc.ky.us,cc.la.us,cc.ma.us,cc.md.us,cc.me.us,cc.mi.us,cc.mn.us,cc.mo.us,cc.ms.us,cc.mt.us,cc.na,cc.nc.us,cc.nd.us,cc.ne.us,cc.nh.us,cc.nj.us,cc.nm.us,cc.nv.us,cc.ny.us,cc.oh.us,cc.ok.us,cc.or.us,cc.pa.us,cc.pr.us,cc.ri.us,cc.sc.us,cc.sd.us,cc.tn.us,cc.tx.us,cc.ua,cc.ut.us,cc.va.us,cc.vi.us,cc.vt.us,cc.wa.us,cc.wi.us,cc.wv.us,cc.wy.us,cci.fr,cd,cd.eu.org,cdn77-ssl.net,ce.gov.br,ce.it,ce.leg.br,ceb,cechire.com,celtic.museum,center,center.museum,ceo,cern,certification.aero,certmgr.org,cesena-forli.it,cesena-forlì.it,cesenaforli.it,cesenaforlì.it,cf,cfa,cfd,cg,ch,ch.eu.org,ch.it,chambagri.fr,championship.aero,chanel,channel,channelsdvr.net,charity,charter.aero,chase,chat,chattanooga.museum,cheap,cheltenham.museum,cherkassy.ua,cherkasy.ua,chernigov.ua,chernihiv.ua,chernivtsi.ua,chernovtsy.ua,chesapeakebay.museum,chiba.jp,chicago.museum,chichibu.saitama.jp,chieti.it,chigasaki.kanagawa.jp,chihayaakasaka.osaka.jp,chijiwa.nagasaki.jp,chikugo.fukuoka.jp,chikuho.fukuoka.jp,chikuhoku.nagano.jp,chikujo.fukuoka.jp,chikuma.nagano.jp,chikusei.ibaraki.jp,chikushino.fukuoka.jp,chikuzen.fukuoka.jp,children.museum,childrens.museum,childrensgarden.museum,chimkent.su,chino.nagano.jp,chintai,chippubetsu.hokkaido.jp,chiropractic.museum,chirurgiens-dentistes-en-france.fr,chirurgiens-dentistes.fr,chiryu.aichi.jp,chita.aichi.jp,chitose.hokkaido.jp,chiyoda.gunma.jp,chiyoda.tokyo.jp,chizu.tottori.jp,chocolate.museum,chofu.tokyo.jp,chonan.chiba.jp,chosei.chiba.jp,choshi.chiba.jp,choyo.kumamoto.jp,christiansburg.museum,christmas,chrome,chrysler,chtr.k12.ma.us,chungbuk.kr,chungnam.kr,chuo.chiba.jp,chuo.fukuoka.jp,chuo.osaka.jp,chuo.tokyo.jp,chuo.yamanashi.jp,church,ci,ci.it,ciencia.bo,cieszyn.pl,cim.br,cincinnati.museum,cinema.museum,cipriani,circle,circus.museum,cisco,ciscofreak.com,cistron.nl,citadel,citi,citic,city,city.hu,cityeats,civilaviation.aero,civilisation.museum,civilization.museum,civilwar.museum,ck,ck.ua,cl,cl.it,claims,clan.rip,cleaning,cleverapps.io,click,clinic,clinique,clinton.museum,clock.museum,clothing,cloud,cloud.fedoraproject.org,cloud.goog,cloud.metacentrum.cz,cloud66.ws,cloud66.zone,cloudaccess.host,cloudaccess.net,cloudapp.net,cloudapps.digital,cloudcontrolapp.com,cloudcontrolled.com,cloudeity.net,cloudera.site,cloudfront.net,cloudfunctions.net,cloudns.asia,cloudns.biz,cloudns.cc,cloudns.club,cloudns.eu,cloudns.in,cloudns.info,cloudns.org,cloudns.pro,cloudns.pw,cloudns.us,cloudycluster.net,club,club.aero,club.tw,clubmed,cm,cn,cn-north-1.eb.amazonaws.com.cn,cn-northwest-1.eb.amazonaws.com.cn,cn.com,cn.eu.org,cn.it,cn.ua,cng.br,cnpy.gdn,cns.joyent.com,cnt.br,co,co.ae,co.ag,co.am,co.ao,co.at,co.bb,co.bi,co.bn,co.business,co.bw,co.ca,co.ci,co.cl,co.cm,co.com,co.cr,co.cz,co.dk,co.education,co.events,co.financial,co.gg,co.gl,co.gy,co.hu,co.id,co.il,co.im,co.in,co.ir,co.it,co.je,co.jp,co.ke,co.kr,co.krd,co.lc,co.ls,co.ma,co.me,co.mg,co.mu,co.mw,co.mz,co.na,co.network,co.ni,co.nl,co.no,co.nz,co.om,co.pl,co.place,co.pn,co.pw,co.rs,co.rw,co.st,co.sz,co.technology,co.th,co.tj,co.tm,co.tt,co.tz,co.ua,co.ug,co.uk,co.us,co.uz,co.ve,co.vi,co.za,co.zm,co.zw,coach,coal.museum,coastaldefence.museum,codes,codespot.com,cody.museum,coffee,cog.mi.us,col.ng,coldwar.museum,collection.museum,college,collegefan.org,cologne,colonialwilliamsburg.museum,coloradoplateau.museum,columbia.museum,columbus.museum,com,com.ac,com.af,com.ag,com.ai,com.al,com.am,com.ar,com.au,com.aw,com.az,com.ba,com.bb,com.bh,com.bi,com.bm,com.bn,com.bo,com.br,com.bs,com.bt,com.by,com.bz,com.ci,com.cm,com.cn,com.co,com.cu,com.cw,com.cy,com.de,com.dm,com.do,com.dz,com.ec,com.ee,com.eg,com.es,com.et,com.fr,com.ge,com.gh,com.gi,com.gl,com.gn,com.gp,com.gr,com.gt,com.gu,com.gy,com.hk,com.hn,com.hr,com.ht,com.im,com.io,com.iq,com.is,com.jo,com.kg,com.ki,com.km,com.kp,com.kw,com.ky,com.kz,com.la,com.lb,com.lc,com.lk,com.lr,com.lv,com.ly,com.mg,com.mk,com.ml,com.mo,com.ms,com.mt,com.mu,com.mv,com.mw,com.mx,com.my,com.na,com.nf,com.ng,com.ni,com.nr,com.om,com.pa,com.pe,com.pf,com.ph,com.pk,com.pl,com.pr,com.ps,com.pt,com.py,com.qa,com.re,com.ro,com.ru,com.sa,com.sb,com.sc,com.sd,com.se,com.sg,com.sh,com.sl,com.sn,com.so,com.st,com.sv,com.sy,com.tj,com.tm,com.tn,com.to,com.tr,com.tt,com.tw,com.ua,com.ug,com.uy,com.uz,com.vc,com.ve,com.vi,com.vn,com.vu,com.ws,com.zm,comcast,commbank,commune.am,communication.museum,communications.museum,community,community.museum,como.it,company,compare,compute-1.amazonaws.com,compute.amazonaws.com,compute.amazonaws.com.cn,compute.estate,computer,computer.museum,computerhistory.museum,comsec,comunicações.museum,condos,conf.au,conf.lv,conf.se,conference.aero,construction,consulado.st,consultant.aero,consulting,consulting.aero,contact,contagem.br,contemporary.museum,contemporaryart.museum,contractors,control.aero,convent.museum,cooking,cookingchannel,cool,coop,coop.br,coop.ht,coop.km,coop.mv,coop.mw,coop.py,coop.rw,coop.tt,cooperativa.bo,copenhagen.museum,corporation.museum,correios-e-telecomunicações.museum,corsica,corvette.museum,cosenza.it,costume.museum,couchpotatofries.org,council.aero,country,countryestate.museum,county.museum,coupon,coupons,courses,cpa,cpa.pro,cq.cn,cr,cr.it,cr.ua,crafting.xyz,crafts.museum,cranbrook.museum,crd.co,creation.museum,credit,creditcard,creditunion,cremona.it,crew.aero,cri.br,cri.nz,cricket,crimea.ua,crotone.it,crown,crs,cruise,cruises,cryptonomic.net,cs.it,csc,ct.it,ct.us,cu,cuiaba.br,cuisinella,cultural.museum,culturalcenter.museum,culture.museum,cuneo.it,cupcake.is,curitiba.br,cust.dev.thingdust.io,cust.disrec.thingdust.io,cust.prod.thingdust.io,cust.testing.thingdust.io,custom.metacentrum.cz,customer.enonic.io,customer.speedpartner.de,cv,cv.ua,cw,cx,cy,cy.eu.org,cya.gg,cyber.museum,cymru,cymru.museum,cyon.link,cyon.site,cyou,cz,cz.eu.org,cz.it,czeladz.pl,czest.pl,d.bg,d.gv.vc,d.se,dabur,dad,daegu.kr,daejeon.kr,dagestan.ru,dagestan.su,daigo.ibaraki.jp,daisen.akita.jp,daito.osaka.jp,daiwa.hiroshima.jp,dali.museum,dallas.museum,damnserver.com,dance,daplie.me,dapps.earth,data,database.museum,date,date.fukushima.jp,date.hokkaido.jp,dating,datsun,dattolocal.com,dattolocal.net,dattorelay.com,dattoweb.com,davvenjarga.no,davvenjárga.no,davvesiida.no,day,dazaifu.fukuoka.jp,dc.us,dclk,dd-dns.de,ddns.me,ddns.net,ddnsfree.com,ddnsgeek.com,ddnsking.com,ddnslive.com,ddnss.de,ddnss.org,ddr.museum,dds,de,de.com,de.cool,de.eu.org,de.us,deal,dealer,deals,deatnu.no,debian.net,decorativearts.museum,dedyn.io,def.br,defense.tn,definima.io,definima.net,degree,delaware.museum,delivery,dell,dell-ogliastra.it,dellogliastra.it,delmenhorst.museum,deloitte,delta,democracia.bo,democrat,demon.nl,denmark.museum,dental,dentist,dep.no,deporte.bo,depot.museum,desa.id,desi,design,design.aero,design.museum,detroit.museum,dev,dev-myqnapcloud.com,dev.static.land,development.run,devices.resinstaging.io,df.gov.br,df.leg.br,dgca.aero,dh.bytemark.co.uk,dhl,diamonds,dielddanuorri.no,diet,digital,dinosaur.museum,direct,directory,discount,discourse.group,discover,discovery.museum,dish,diskstation.eu,diskstation.me,diskstation.org,ditchyourip.com,divtasvuodna.no,divttasvuotna.no,diy,dj,dk,dk.eu.org,dlugoleka.pl,dm,dn.ua,dnepropetrovsk.ua,dni.us,dnipropetrovsk.ua,dnp,dnsalias.com,dnsalias.net,dnsalias.org,dnsdojo.com,dnsdojo.net,dnsdojo.org,dnsfor.me,dnshome.de,dnsiskinky.com,dnsking.ch,dnsup.net,dnsupdater.de,do,docs,doctor,dodge,does-it.net,doesntexist.com,doesntexist.org,dog,dolls.museum,domains,dominic.ua,donetsk.ua,donna.no,donostia.museum,dontexist.com,dontexist.net,dontexist.org,doomdns.com,doomdns.org,doshi.yamanashi.jp,dot,dovre.no,download,dp.ua,dr.na,dr.tr,drammen.no,drangedal.no,dray-dns.de,drayddns.com,draydns.de,dreamhosters.com,drive,drobak.no,drud.io,drud.us,drøbak.no,dscloud.biz,dscloud.me,dscloud.mobi,dsmynas.com,dsmynas.net,dsmynas.org,dst.mi.us,dtv,dubai,duck,duckdns.org,dunlop,duns,dupont,durban,durham.museum,dvag,dvr,dvrcam.info,dvrdns.org,dweb.link,dy.fi,dyn-berlin.de,dyn-ip24.de,dyn-o-saur.com,dyn-vpn.de,dyn.cosidns.de,dyn.ddnss.de,dyn.home-webserver.de,dyn53.io,dynalias.com,dynalias.net,dynalias.org,dynamic-dns.info,dynamisches-dns.de,dynathome.net,dyndns-at-home.com,dyndns-at-work.com,dyndns-blog.com,dyndns-free.com,dyndns-home.com,dyndns-ip.com,dyndns-mail.com,dyndns-office.com,dyndns-pics.com,dyndns-remote.com,dyndns-server.com,dyndns-web.com,dyndns-wiki.com,dyndns-work.com,dyndns.biz,dyndns.ddnss.de,dyndns.info,dyndns.org,dyndns.tv,dyndns.ws,dyndns1.de,dynns.com,dynserv.org,dynu.net,dynv6.net,dynvpn.de,dyroy.no,dyrøy.no,dz,dønna.no,e.bg,e.se,e12.ve,e164.arpa,e4.cz,earth,east-kazakhstan.su,eastafrica.museum,eastcoast.museum,eat,eating-organic.net,eaton.mi.us,ebetsu.hokkaido.jp,ebina.kanagawa.jp,ebino.miyazaki.jp,ebiz.tw,ec,echizen.fukui.jp,ecn.br,eco,eco.br,ecologia.bo,economia.bo,ed.ao,ed.ci,ed.cr,ed.jp,ed.pw,edeka,edogawa.tokyo.jp,edu,edu.ac,edu.af,edu.al,edu.ar,edu.au,edu.az,edu.ba,edu.bb,edu.bh,edu.bi,edu.bm,edu.bn,edu.bo,edu.br,edu.bs,edu.bt,edu.bz,edu.ci,edu.cn,edu.co,edu.cu,edu.cw,edu.dm,edu.do,edu.dz,edu.ec,edu.ee,edu.eg,edu.es,edu.et,edu.eu.org,edu.ge,edu.gh,edu.gi,edu.gl,edu.gn,edu.gp,edu.gr,edu.gt,edu.gu,edu.gy,edu.hk,edu.hn,edu.ht,edu.in,edu.iq,edu.is,edu.it,edu.jo,edu.kg,edu.ki,edu.km,edu.kn,edu.kp,edu.krd,edu.kw,edu.ky,edu.kz,edu.la,edu.lb,edu.lc,edu.lk,edu.lr,edu.ls,edu.lv,edu.ly,edu.me,edu.mg,edu.mk,edu.ml,edu.mn,edu.mo,edu.ms,edu.mt,edu.mv,edu.mw,edu.mx,edu.my,edu.mz,edu.ng,edu.ni,edu.nr,edu.om,edu.pa,edu.pe,edu.pf,edu.ph,edu.pk,edu.pl,edu.pn,edu.pr,edu.ps,edu.pt,edu.py,edu.qa,edu.rs,edu.ru,edu.sa,edu.sb,edu.sc,edu.sd,edu.sg,edu.sl,edu.sn,edu.st,edu.sv,edu.sy,edu.tj,edu.tm,edu.to,edu.tr,edu.tt,edu.tw,edu.ua,edu.uy,edu.vc,edu.ve,edu.vn,edu.vu,edu.ws,edu.za,edu.zm,education,education.museum,educational.museum,educator.aero,edugit.org,edunet.tn,ee,ee.eu.org,eg,egersund.no,egyptian.museum,ehime.jp,eid.no,eidfjord.no,eidsberg.no,eidskog.no,eidsvoll.no,eigersund.no,eiheiji.fukui.jp,eisenbahn.museum,ekloges.cy,elasticbeanstalk.com,elb.amazonaws.com,elb.amazonaws.com.cn,elblag.pl,elburg.museum,elk.pl,elvendrell.museum,elverum.no,email,emb.kw,embaixada.st,embetsu.hokkaido.jp,embroidery.museum,emerck,emergency.aero,emilia-romagna.it,emiliaromagna.it,emp.br,empresa.bo,emr.it,en.it,ena.gifu.jp,encyclopedic.museum,endofinternet.net,endofinternet.org,endoftheinternet.org,enebakk.no,energy,eng.br,eng.pro,engerdal.no,engine.aero,engineer,engineer.aero,engineering,england.museum,eniwa.hokkaido.jp,enna.it,enonic.io,ens.tn,enterprisecloud.nu,enterprises,entertainment.aero,entomology.museum,environment.museum,environmentalconservation.museum,epilepsy.museum,epson,equipment,equipment.aero,er,ericsson,erimo.hokkaido.jp,erni,erotica.hu,erotika.hu,es,es.eu.org,es.gov.br,es.kr,es.leg.br,esan.hokkaido.jp,esashi.hokkaido.jp,esp.br,esq,essex.museum,est-a-la-maison.com,est-a-la-masion.com,est-le-patron.com,est-mon-blogueur.com,est.pr,estate,estate.museum,esurance,et,etajima.hiroshima.jp,etc.br,ethnology.museum,eti.br,etisalat,etne.no,etnedal.no,eu,eu-1.evennode.com,eu-2.evennode.com,eu-3.evennode.com,eu-4.evennode.com,eu-central-1.elasticbeanstalk.com,eu-west-1.elasticbeanstalk.com,eu-west-2.elasticbeanstalk.com,eu-west-3.elasticbeanstalk.com,eu.com,eu.int,eu.meteorapp.com,eu.org,eun.eg,eurovision,eus,evenassi.no,evenes.no,events,evenášši.no,everbank,evje-og-hornnes.no,ex.futurecms.at,ex.ortsinfo.at,exchange,exchange.aero,exeter.museum,exhibition.museum,exnet.su,expert,experts-comptables.fr,exposed,express,express.aero,extraspace,f.bg,f.se,fage,fail,fairwinds,faith,fam.pk,family,family.museum,familyds.com,familyds.net,familyds.org,fan,fans,fantasyleague.cc,far.br,farm,farm.museum,farmequipment.museum,farmers,farmers.museum,farmstead.museum,farsund.no,fashion,fast,fastly-terrarium.com,fastlylb.net,fastpanel.direct,fastvps-server.com,fauske.no,fbx-os.fr,fbxos.fr,fc.it,fe.it,fed.us,federation.aero,fedex,fedje.no,fedorainfracloud.org,fedorapeople.org,feedback,feira.br,fermo.it,ferrara.it,ferrari,ferrero,feste-ip.net,fet.no,fetsund.no,fg.it,fh.se,fhapp.xyz,fhs.no,fhsk.se,fhv.se,fi,fi.cr,fi.eu.org,fi.it,fiat,fidelity,fido,fie.ee,field.museum,figueres.museum,filatelia.museum,filegear-au.me,filegear-de.me,filegear-gb.me,filegear-ie.me,filegear-jp.me,filegear-sg.me,filegear.me,film,film.hu,film.museum,fin.ci,fin.ec,fin.tn,final,finance,financial,fineart.museum,finearts.museum,finland.museum,finnoy.no,finnøy.no,fire,firebaseapp.com,firenze.it,firestone,firewall-gateway.com,firewall-gateway.de,firewall-gateway.net,firm.co,firm.dk,firm.ht,firm.in,firm.nf,firm.ng,firm.ro,firm.ve,firmdale,fish,fishing,fit,fitjar.no,fitness,fj,fj.cn,fjaler.no,fjell.no,fk,fl.us,fla.no,flakstad.no,flanders.museum,flatanger.no,flekkefjord.no,flesberg.no,flickr,flight.aero,flights,flir,flog.br,flora.no,florence.it,florida.museum,floripa.br,florist,floro.no,florø.no,flowers,flt.cloud.muni.cz,fly,flynnhosting.net,flynnhub.com,flå.no,fm,fm.br,fm.it,fm.no,fnd.br,fo,foggia.it,folkebibl.no,folldal.no,foo,food,foodnetwork,football,for-better.biz,for-more.biz,for-our.info,for-some.biz,for-the.biz,for.men,for.mom,for.one,for.sale,force.museum,ford,forde.no,forex,forgot.her.name,forgot.his.name,forli-cesena.it,forlicesena.it,forlì-cesena.it,forlìcesena.it,forsale,forsand.no,fortal.br,fortmissoula.museum,fortworth.museum,forum,forum.hu,forumz.info,fosnes.no,fot.br,foundation,foundation.museum,fox,foz.br,fr,fr.eu.org,fr.it,frana.no,francaise.museum,frankfurt.museum,franziskaner.museum,fredrikstad.no,free,free.hr,freebox-os.com,freebox-os.fr,freeboxos.com,freeboxos.fr,freeddns.org,freeddns.us,freedesktop.org,freemasonry.museum,freesite.host,freetls.fastly.net,frei.no,freiburg.museum,freight.aero,fresenius,fribourg.museum,friuli-v-giulia.it,friuli-ve-giulia.it,friuli-vegiulia.it,friuli-venezia-giulia.it,friuli-veneziagiulia.it,friuli-vgiulia.it,friuliv-giulia.it,friulive-giulia.it,friulivegiulia.it,friulivenezia-giulia.it,friuliveneziagiulia.it,friulivgiulia.it,frl,frog.museum,frogans,frogn.no,froland.no,from-ak.com,from-al.com,from-ar.com,from-az.net,from-ca.com,from-co.net,from-ct.com,from-dc.com,from-de.com,from-fl.com,from-ga.com,from-hi.com,from-ia.com,from-id.com,from-il.com,from-in.com,from-ks.com,from-ky.com,from-la.net,from-ma.com,from-md.com,from-me.org,from-mi.com,from-mn.com,from-mo.com,from-ms.com,from-mt.com,from-nc.com,from-nd.com,from-ne.com,from-nh.com,from-nj.com,from-nm.com,from-nv.com,from-ny.net,from-oh.com,from-ok.com,from-or.com,from-pa.com,from-pr.com,from-ri.com,from-sc.com,from-sd.com,from-tn.com,from-tx.com,from-ut.com,from-va.com,from-vt.com,from-wa.com,from-wi.com,from-wv.com,from-wy.com,from.hr,frontdoor,frontier,frosinone.it,frosta.no,froya.no,fræna.no,frøya.no,fst.br,ftpaccess.cc,ftr,fuchu.hiroshima.jp,fuchu.tokyo.jp,fuchu.toyama.jp,fudai.iwate.jp,fuefuki.yamanashi.jp,fuel.aero,fuettertdasnetz.de,fuji.shizuoka.jp,fujieda.shizuoka.jp,fujiidera.osaka.jp,fujikawa.shizuoka.jp,fujikawa.yamanashi.jp,fujikawaguchiko.yamanashi.jp,fujimi.nagano.jp,fujimi.saitama.jp,fujimino.saitama.jp,fujinomiya.shizuoka.jp,fujioka.gunma.jp,fujisato.akita.jp,fujisawa.iwate.jp,fujisawa.kanagawa.jp,fujishiro.ibaraki.jp,fujitsu,fujixerox,fujiyoshida.yamanashi.jp,fukagawa.hokkaido.jp,fukaya.saitama.jp,fukuchi.fukuoka.jp,fukuchiyama.kyoto.jp,fukudomi.saga.jp,fukui.fukui.jp,fukui.jp,fukumitsu.toyama.jp,fukuoka.jp,fukuroi.shizuoka.jp,fukusaki.hyogo.jp,fukushima.fukushima.jp,fukushima.hokkaido.jp,fukushima.jp,fukuyama.hiroshima.jp,fun,funabashi.chiba.jp,funagata.yamagata.jp,funahashi.toyama.jp,fund,fundacio.museum,fuoisku.no,fuossko.no,furano.hokkaido.jp,furniture,furniture.museum,furubira.hokkaido.jp,furudono.fukushima.jp,furukawa.miyagi.jp,fusa.no,fuso.aichi.jp,fussa.tokyo.jp,futaba.fukushima.jp,futbol,futsu.nagasaki.jp,futtsu.chiba.jp,futurecms.at,futurehosting.at,futuremailing.at,fvg.it,fyi,fylkesbibl.no,fyresdal.no,førde.no,g.bg,g.se,g12.br,ga,ga.us,gaivuotna.no,gal,gallery,gallery.museum,gallo,gallup,galsa.no,gamagori.aichi.jp,game,game-host.org,game-server.cc,game.tw,games,games.hu,gamo.shiga.jp,gamvik.no,gangaviika.no,gangwon.kr,gap,garden,garden.museum,gateway.museum,gaular.no,gausdal.no,gay,gb,gb.com,gb.net,gbiz,gc.ca,gd,gd.cn,gda.pl,gdansk.pl,gdn,gdynia.pl,ge,ge.it,gea,geek.nz,geekgalaxy.com,geelvinck.museum,gehirn.ne.jp,geisei.kochi.jp,gemological.museum,gen.in,gen.mi.us,gen.ng,gen.nz,gen.tr,genkai.saga.jp,genoa.it,genova.it,gent,genting,geology.museum,geometre-expert.fr,george,georgia.museum,georgia.su,getmyip.com,gets-it.net,gf,gg,ggee,ggf.br,gh,gi,giehtavuoatna.no,giessen.museum,gift,gifts,gifu.gifu.jp,gifu.jp,giize.com,gildeskal.no,gildeskål.no,ginan.gifu.jp,ginowan.okinawa.jp,ginoza.okinawa.jp,giske.no,git-pages.rit.edu,git-repos.de,github.io,githubusercontent.com,gitlab.io,gives,giving,gjemnes.no,gjerdrum.no,gjerstad.no,gjesdal.no,gjovik.no,gjøvik.no,gl,glade,glas.museum,glass,glass.museum,gle,gleeze.com,gliding.aero,glitch.me,gliwice.pl,global,global.prod.fastly.net,global.ssl.fastly.net,globo,glogow.pl,gloppen.no,glug.org.uk,gm,gmail,gmbh,gmina.pl,gmo,gmx,gn,gniezno.pl,go-vip.co,go-vip.net,go.ci,go.cr,go.dyndns.org,go.gov.br,go.id,go.it,go.jp,go.ke,go.kr,go.leg.br,go.pw,go.th,go.tj,go.tz,go.ug,gob.ar,gob.bo,gob.cl,gob.do,gob.ec,gob.es,gob.gt,gob.hn,gob.mx,gob.ni,gob.pa,gob.pe,gob.pk,gob.sv,gob.ve,gobo.wakayama.jp,godaddy,godo.gifu.jp,goiania.br,goip.de,gojome.akita.jp,gok.pk,gokase.miyazaki.jp,gol.no,gold,goldpoint,golf,golffan.us,gon.pk,gonohe.aomori.jp,goo,goodyear,goog,google,googleapis.com,googlecode.com,gop,gop.pk,gorge.museum,gorizia.it,gorlice.pl,gos.pk,gose.nara.jp,gosen.niigata.jp,goshiki.hyogo.jp,got,gotdns.ch,gotdns.com,gotdns.org,gotemba.shizuoka.jp,goto.nagasaki.jp,gotpantheon.com,gotsu.shimane.jp,gouv.bj,gouv.ci,gouv.fr,gouv.ht,gouv.km,gouv.ml,gouv.sn,gov,gov.ac,gov.ae,gov.af,gov.al,gov.ar,gov.as,gov.au,gov.az,gov.ba,gov.bb,gov.bf,gov.bh,gov.bm,gov.bn,gov.br,gov.bs,gov.bt,gov.by,gov.bz,gov.cd,gov.cl,gov.cm,gov.cn,gov.co,gov.cu,gov.cx,gov.cy,gov.dm,gov.do,gov.dz,gov.ec,gov.ee,gov.eg,gov.et,gov.ge,gov.gh,gov.gi,gov.gn,gov.gr,gov.gu,gov.gy,gov.hk,gov.ie,gov.il,gov.in,gov.iq,gov.ir,gov.is,gov.it,gov.jo,gov.kg,gov.ki,gov.km,gov.kn,gov.kp,gov.kw,gov.ky,gov.kz,gov.la,gov.lb,gov.lc,gov.lk,gov.lr,gov.ls,gov.lt,gov.lv,gov.ly,gov.ma,gov.me,gov.mg,gov.mk,gov.ml,gov.mn,gov.mo,gov.mr,gov.ms,gov.mu,gov.mv,gov.mw,gov.my,gov.mz,gov.nc.tr,gov.ng,gov.nr,gov.om,gov.ph,gov.pk,gov.pl,gov.pn,gov.pr,gov.ps,gov.pt,gov.py,gov.qa,gov.rs,gov.ru,gov.rw,gov.sa,gov.sb,gov.sc,gov.sd,gov.sg,gov.sh,gov.sl,gov.st,gov.sx,gov.sy,gov.tj,gov.tl,gov.tm,gov.tn,gov.to,gov.tr,gov.tt,gov.tw,gov.ua,gov.uk,gov.vc,gov.ve,gov.vn,gov.ws,gov.za,gov.zm,gov.zw,government.aero,govt.nz,gp,gq,gr,gr.com,gr.eu.org,gr.it,gr.jp,grainger,grajewo.pl,gran.no,grandrapids.museum,grane.no,granvin.no,graphics,gratangen.no,gratis,graz.museum,green,greta.fr,grimstad.no,gripe,griw.gov.pl,grocery,groks-the.info,groks-this.info,grondar.za,grong.no,grosseto.it,groundhandling.aero,group,group.aero,grozny.ru,grozny.su,grp.lk,gru.br,grue.no,gs,gs.aa.no,gs.ah.no,gs.bu.no,gs.cn,gs.fm.no,gs.hl.no,gs.hm.no,gs.jan-mayen.no,gs.mr.no,gs.nl.no,gs.nt.no,gs.of.no,gs.ol.no,gs.oslo.no,gs.rl.no,gs.sf.no,gs.st.no,gs.svalbard.no,gs.tm.no,gs.tr.no,gs.va.no,gs.vf.no,gsm.pl,gt,gu,gu.us,guam.gu,guardian,gub.uy,gucci,guernsey.museum,guge,guide,guitars,gujo.gifu.jp,gulen.no,gunma.jp,guovdageaidnu.no,guru,gushikami.okinawa.jp,gv.ao,gv.at,gv.vc,gw,gwangju.kr,gwiddle.co.uk,gx.cn,gy,gyeongbuk.kr,gyeonggi.kr,gyeongnam.kr,gyokuto.kumamoto.jp,gz.cn,gáivuotna.no,gálsá.no,gáŋgaviika.no,h.bg,h.se,ha.cn,ha.no,habikino.osaka.jp,habmer.no,haboro.hokkaido.jp,hachijo.tokyo.jp,hachinohe.aomori.jp,hachioji.tokyo.jp,hachirogata.akita.jp,hadano.kanagawa.jp,hadsel.no,haebaru.okinawa.jp,haga.tochigi.jp,hagebostad.no,hagi.yamaguchi.jp,haibara.shizuoka.jp,hair,hakata.fukuoka.jp,hakodate.hokkaido.jp,hakone.kanagawa.jp,hakuba.nagano.jp,hakui.ishikawa.jp,hakusan.ishikawa.jp,halden.no,half.host,halloffame.museum,halsa.no,ham-radio-op.net,hamada.shimane.jp,hamamatsu.shizuoka.jp,hamar.no,hamaroy.no,hamatama.saga.jp,hamatonbetsu.hokkaido.jp,hamburg,hamburg.museum,hammarfeasta.no,hammerfest.no,hamura.tokyo.jp,hanamaki.iwate.jp,hanamigawa.chiba.jp,hanawa.fukushima.jp,handa.aichi.jp,handson.museum,hanggliding.aero,hangout,hannan.osaka.jp,hanno.saitama.jp,hanyu.saitama.jp,hapmir.no,happou.akita.jp,hara.nagano.jp,haram.no,hareid.no,harima.hyogo.jp,harstad.no,harvestcelebration.museum,hasama.oita.jp,hasami.nagasaki.jp,hashbang.sh,hashikami.aomori.jp,hashima.gifu.jp,hashimoto.wakayama.jp,hasuda.saitama.jp,hasura-app.io,hasura.app,hasvik.no,hatogaya.saitama.jp,hatoyama.saitama.jp,hatsukaichi.hiroshima.jp,hattfjelldal.no,haugesund.no,haus,hawaii.museum,hayakawa.yamanashi.jp,hayashima.okayama.jp,hazu.aichi.jp,hb.cldmail.ru,hb.cn,hbo,hdfc,hdfcbank,he.cn,health,health-carereform.com,health.museum,health.nz,health.vn,healthcare,heguri.nara.jp,heimatunduhren.museum,hekinan.aichi.jp,hellas.museum,help,helsinki,helsinki.museum,hembygdsforbund.museum,hemne.no,hemnes.no,hemsedal.no,hepforge.org,herad.no,here,here-for-more.info,heritage.museum,hermes,herokuapp.com,herokussl.com,heroy.more-og-romsdal.no,heroy.nordland.no,herøy.møre-og-romsdal.no,herøy.nordland.no,hgtv,hi.cn,hi.us,hicam.net,hichiso.gifu.jp,hida.gifu.jp,hidaka.hokkaido.jp,hidaka.kochi.jp,hidaka.saitama.jp,hidaka.wakayama.jp,higashi.fukuoka.jp,higashi.fukushima.jp,higashi.okinawa.jp,higashiagatsuma.gunma.jp,higashichichibu.saitama.jp,higashihiroshima.hiroshima.jp,higashiizu.shizuoka.jp,higashiizumo.shimane.jp,higashikagawa.kagawa.jp,higashikagura.hokkaido.jp,higashikawa.hokkaido.jp,higashikurume.tokyo.jp,higashimatsushima.miyagi.jp,higashimatsuyama.saitama.jp,higashimurayama.tokyo.jp,higashinaruse.akita.jp,higashine.yamagata.jp,higashiomi.shiga.jp,higashiosaka.osaka.jp,higashishirakawa.gifu.jp,higashisumiyoshi.osaka.jp,higashitsuno.kochi.jp,higashiura.aichi.jp,higashiyama.kyoto.jp,higashiyamato.tokyo.jp,higashiyodogawa.osaka.jp,higashiyoshino.nara.jp,hiji.oita.jp,hikari.yamaguchi.jp,hikawa.shimane.jp,hikimi.shimane.jp,hikone.shiga.jp,himeji.hyogo.jp,himeshima.oita.jp,himi.toyama.jp,hino.tokyo.jp,hino.tottori.jp,hinode.tokyo.jp,hinohara.tokyo.jp,hioki.kagoshima.jp,hiphop,hirado.nagasaki.jp,hiraizumi.iwate.jp,hirakata.osaka.jp,hiranai.aomori.jp,hirara.okinawa.jp,hirata.fukushima.jp,hiratsuka.kanagawa.jp,hiraya.nagano.jp,hirogawa.wakayama.jp,hirokawa.fukuoka.jp,hirono.fukushima.jp,hirono.iwate.jp,hiroo.hokkaido.jp,hirosaki.aomori.jp,hiroshima.jp,hisamitsu,hisayama.fukuoka.jp,histoire.museum,historical.museum,historicalsociety.museum,historichouses.museum,historisch.museum,historisches.museum,history.museum,historyofscience.museum,hita.oita.jp,hitachi,hitachi.ibaraki.jp,hitachinaka.ibaraki.jp,hitachiomiya.ibaraki.jp,hitachiota.ibaraki.jp,hitra.no,hiv,hizen.saga.jp,hjartdal.no,hjelmeland.no,hk,hk.cn,hk.com,hk.org,hkt,hl.cn,hl.no,hm,hm.no,hn,hn.cn,hobby-site.com,hobby-site.org,hobol.no,hobøl.no,hockey,hof.no,hofu.yamaguchi.jp,hokkaido.jp,hokksund.no,hokuryu.hokkaido.jp,hokuto.hokkaido.jp,hokuto.yamanashi.jp,hol.no,holdings,hole.no,holiday,holmestrand.no,holtalen.no,holtålen.no,home-webserver.de,home.dyndns.org,homebuilt.aero,homedepot,homedns.org,homeftp.net,homeftp.org,homegoods,homeip.net,homelink.one,homelinux.com,homelinux.net,homelinux.org,homeoffice.gov.uk,homes,homesecuritymac.com,homesecuritypc.com,homesense,homeunix.com,homeunix.net,homeunix.org,honai.ehime.jp,honbetsu.hokkaido.jp,honda,honefoss.no,honeywell,hongo.hiroshima.jp,honjo.akita.jp,honjo.saitama.jp,honjyo.akita.jp,hopto.me,hopto.org,hornindal.no,horokanai.hokkaido.jp,horology.museum,horonobe.hokkaido.jp,horse,horten.no,hospital,host,hosting,hosting-cluster.nl,hosting.myjino.ru,hot,hotel.hu,hotel.lk,hotel.tz,hoteles,hotels,hotmail,house,house.museum,how,hoyanger.no,hoylandet.no,hr,hr.eu.org,hs.kr,hs.run,hs.zone,hsbc,ht,hu,hu.com,hu.eu.org,hu.net,hughes,huissier-justice.fr,humanities.museum,hurdal.no,hurum.no,hvaler.no,hyatt,hyllestad.no,hyogo.jp,hyuga.miyazaki.jp,hyundai,hzc.io,hábmer.no,hámmárfeasta.no,hápmir.no,häkkinen.fi,hå.no,hægebostad.no,hønefoss.no,høyanger.no,høylandet.no,i.bg,i.ng,i.ph,i.se,i234.me,ia.us,iamallama.com,ibara.okayama.jp,ibaraki.ibaraki.jp,ibaraki.jp,ibaraki.osaka.jp,ibestad.no,ibigawa.gifu.jp,ibm,ic.gov.pl,icbc,ice,ichiba.tokushima.jp,ichihara.chiba.jp,ichikai.tochigi.jp,ichikawa.chiba.jp,ichikawa.hyogo.jp,ichikawamisato.yamanashi.jp,ichinohe.iwate.jp,ichinomiya.aichi.jp,ichinomiya.chiba.jp,ichinoseki.iwate.jp,icu,id,id.au,id.ir,id.lv,id.ly,id.us,ide.kyoto.jp,idf.il,idrett.no,idv.hk,idv.tw,ie,ie.eu.org,ieee,if.ua,ifm,iglesias-carbonia.it,iglesiascarbonia.it,iheya.okinawa.jp,iida.nagano.jp,iide.yamagata.jp,iijima.nagano.jp,iitate.fukushima.jp,iiyama.nagano.jp,iizuka.fukuoka.jp,iizuna.nagano.jp,ikano,ikaruga.nara.jp,ikata.ehime.jp,ikawa.akita.jp,ikeda.fukui.jp,ikeda.gifu.jp,ikeda.hokkaido.jp,ikeda.nagano.jp,ikeda.osaka.jp,iki.fi,iki.nagasaki.jp,ikoma.nara.jp,ikusaka.nagano.jp,il,il.eu.org,il.us,ilawa.pl,illustration.museum,ilovecollege.info,im,im.it,imabari.ehime.jp,imageandsound.museum,imakane.hokkaido.jp,imamat,imari.saga.jp,imb.br,imdb,imizu.toyama.jp,immo,immobilien,imperia.it,in,in-addr.arpa,in-berlin.de,in-brb.de,in-butter.de,in-dsl.de,in-dsl.net,in-dsl.org,in-the-band.net,in-vpn.de,in-vpn.net,in-vpn.org,in.eu.org,in.futurecms.at,in.london,in.na,in.net,in.ni,in.rs,in.th,in.ua,in.us,ina.ibaraki.jp,ina.nagano.jp,ina.saitama.jp,inabe.mie.jp,inagawa.hyogo.jp,inagi.tokyo.jp,inami.toyama.jp,inami.wakayama.jp,inashiki.ibaraki.jp,inatsuki.fukuoka.jp,inawashiro.fukushima.jp,inazawa.aichi.jp,inc,inc.hk,incheon.kr,ind.br,ind.gt,ind.in,ind.kw,ind.tn,inderoy.no,inderøy.no,indian.museum,indiana.museum,indianapolis.museum,indianmarket.museum,indigena.bo,industria.bo,industries,ine.kyoto.jp,inf.br,inf.cu,inf.mk,inf.ua,infiniti,info,info.at,info.au,info.az,info.bb,info.bo,info.co,info.cx,info.ec,info.et,info.gu,info.ht,info.hu,info.ke,info.ki,info.la,info.ls,info.mv,info.na,info.nf,info.ni,info.nr,info.pk,info.pl,info.pr,info.ro,info.sd,info.tn,info.tr,info.tt,info.tz,info.ve,info.vn,info.zm,ing,ing.pa,ingatlan.hu,ink,ino.kochi.jp,instantcloud.cn,institute,insurance,insurance.aero,insure,int,int.ar,int.az,int.bo,int.ci,int.co,int.eu.org,int.is,int.la,int.lk,int.mv,int.mw,int.ni,int.pt,int.ru,int.tj,int.tt,int.ve,int.vn,intel,intelligence.museum,interactive.museum,international,internet-dns.de,intl.tn,intuit,inuyama.aichi.jp,investments,inzai.chiba.jp,io,iobb.net,ip6.arpa,ipifony.net,ipiranga,iq,ir,iraq.museum,iris.arpa,irish,iron.museum,iruma.saitama.jp,is,is-a-anarchist.com,is-a-blogger.com,is-a-bookkeeper.com,is-a-bruinsfan.org,is-a-bulls-fan.com,is-a-candidate.org,is-a-caterer.com,is-a-celticsfan.org,is-a-chef.com,is-a-chef.net,is-a-chef.org,is-a-conservative.com,is-a-cpa.com,is-a-cubicle-slave.com,is-a-democrat.com,is-a-designer.com,is-a-doctor.com,is-a-financialadvisor.com,is-a-geek.com,is-a-geek.net,is-a-geek.org,is-a-green.com,is-a-guru.com,is-a-hard-worker.com,is-a-hunter.com,is-a-knight.org,is-a-landscaper.com,is-a-lawyer.com,is-a-liberal.com,is-a-libertarian.com,is-a-linux-user.org,is-a-llama.com,is-a-musician.com,is-a-nascarfan.com,is-a-nurse.com,is-a-painter.com,is-a-patsfan.org,is-a-personaltrainer.com,is-a-photographer.com,is-a-player.com,is-a-republican.com,is-a-rockstar.com,is-a-socialist.com,is-a-soxfan.org,is-a-student.com,is-a-teacher.com,is-a-techie.com,is-a-therapist.com,is-an-accountant.com,is-an-actor.com,is-an-actress.com,is-an-anarchist.com,is-an-artist.com,is-an-engineer.com,is-an-entertainer.com,is-by.us,is-certified.com,is-found.org,is-gone.com,is-into-anime.com,is-into-cars.com,is-into-cartoons.com,is-into-games.com,is-leet.com,is-lost.org,is-not-certified.com,is-saved.org,is-slick.com,is-uberleet.com,is-very-bad.org,is-very-evil.org,is-very-good.org,is-very-nice.org,is-very-sweet.org,is-with-theband.com,is.eu.org,is.gov.pl,is.it,isa-geek.com,isa-geek.net,isa-geek.org,isa-hockeynut.com,isa.kagoshima.jp,isa.us,isahaya.nagasaki.jp,ise.mie.jp,isehara.kanagawa.jp,iselect,isen.kagoshima.jp,isernia.it,iserv.dev,isesaki.gunma.jp,ishigaki.okinawa.jp,ishikari.hokkaido.jp,ishikawa.fukushima.jp,ishikawa.jp,ishikawa.okinawa.jp,ishinomaki.miyagi.jp,isla.pr,isleofman.museum,ismaili,isshiki.aichi.jp,issmarterthanyou.com,ist,istanbul,isteingeek.de,istmein.de,isumi.chiba.jp,it,it.ao,it.eu.org,itabashi.tokyo.jp,itako.ibaraki.jp,itakura.gunma.jp,itami.hyogo.jp,itano.tokushima.jp,itau,itayanagi.aomori.jp,ito.shizuoka.jp,itoigawa.niigata.jp,itoman.okinawa.jp,its.me,itv,ivano-frankivsk.ua,ivanovo.su,iveco,iveland.no,ivgu.no,iwade.wakayama.jp,iwafune.tochigi.jp,iwaizumi.iwate.jp,iwaki.fukushima.jp,iwakuni.yamaguchi.jp,iwakura.aichi.jp,iwama.ibaraki.jp,iwamizawa.hokkaido.jp,iwanai.hokkaido.jp,iwanuma.miyagi.jp,iwata.shizuoka.jp,iwate.iwate.jp,iwate.jp,iwatsuki.saitama.jp,iwi.nz,iyo.ehime.jp,iz.hr,izena.okinawa.jp,izu.shizuoka.jp,izumi.kagoshima.jp,izumi.osaka.jp,izumiotsu.osaka.jp,izumisano.osaka.jp,izumizaki.fukushima.jp,izumo.shimane.jp,izumozaki.niigata.jp,izunokuni.shizuoka.jp,j.bg,jab.br,jaguar,jambyl.su,jamison.museum,jampa.br,jan-mayen.no,java,jaworzno.pl,jcb,jcp,jdevcloud.com,jdf.br,je,jeep,jefferson.museum,jeju.kr,jelenia-gora.pl,jeonbuk.kr,jeonnam.kr,jerusalem.museum,jessheim.no,jetzt,jevnaker.no,jewelry,jewelry.museum,jewish.museum,jewishart.museum,jfk.museum,jgora.pl,jinsekikogen.hiroshima.jp,jio,jl.cn,jll,jm,jmp,jnj,jo,joboji.iwate.jp,jobs,jobs.tt,joburg,joetsu.niigata.jp,jogasz.hu,johana.toyama.jp,joinville.br,jolster.no,jondal.no,jor.br,jorpeland.no,joso.ibaraki.jp,jot,journal.aero,journalism.museum,journalist.aero,joy,joyo.kyoto.jp,jp,jp.eu.org,jp.net,jpmorgan,jpn.com,jprs,js.cn,js.org,judaica.museum,judygarland.museum,juedisches.museum,juegos,juif.museum,juniper,jur.pro,jus.br,jx.cn,jølster.no,jørpeland.no,k.bg,k.se,k12.ak.us,k12.al.us,k12.ar.us,k12.as.us,k12.az.us,k12.ca.us,k12.co.us,k12.ct.us,k12.dc.us,k12.de.us,k12.ec,k12.fl.us,k12.ga.us,k12.gu.us,k12.ia.us,k12.id.us,k12.il,k12.il.us,k12.in.us,k12.ks.us,k12.ky.us,k12.la.us,k12.ma.us,k12.md.us,k12.me.us,k12.mi.us,k12.mn.us,k12.mo.us,k12.ms.us,k12.mt.us,k12.nc.us,k12.ne.us,k12.nh.us,k12.nj.us,k12.nm.us,k12.nv.us,k12.ny.us,k12.oh.us,k12.ok.us,k12.or.us,k12.pa.us,k12.pr.us,k12.ri.us,k12.sc.us,k12.tn.us,k12.tr,k12.tx.us,k12.ut.us,k12.va.us,k12.vi,k12.vi.us,k12.vt.us,k12.wa.us,k12.wi.us,k12.wy.us,kaas.gg,kadena.okinawa.jp,kadogawa.miyazaki.jp,kadoma.osaka.jp,kafjord.no,kaga.ishikawa.jp,kagami.kochi.jp,kagamiishi.fukushima.jp,kagamino.okayama.jp,kagawa.jp,kagoshima.jp,kagoshima.kagoshima.jp,kaho.fukuoka.jp,kahoku.ishikawa.jp,kahoku.yamagata.jp,kai.yamanashi.jp,kainan.tokushima.jp,kainan.wakayama.jp,kaisei.kanagawa.jp,kaita.hiroshima.jp,kaizuka.osaka.jp,kakamigahara.gifu.jp,kakegawa.shizuoka.jp,kakinoki.shimane.jp,kakogawa.hyogo.jp,kakuda.miyagi.jp,kalisz.pl,kalmykia.ru,kalmykia.su,kaluga.su,kamagaya.chiba.jp,kamaishi.iwate.jp,kamakura.kanagawa.jp,kameoka.kyoto.jp,kameyama.mie.jp,kami.kochi.jp,kami.miyagi.jp,kamiamakusa.kumamoto.jp,kamifurano.hokkaido.jp,kamigori.hyogo.jp,kamiichi.toyama.jp,kamiizumi.saitama.jp,kamijima.ehime.jp,kamikawa.hokkaido.jp,kamikawa.hyogo.jp,kamikawa.saitama.jp,kamikitayama.nara.jp,kamikoani.akita.jp,kamimine.saga.jp,kaminokawa.tochigi.jp,kaminoyama.yamagata.jp,kamioka.akita.jp,kamisato.saitama.jp,kamishihoro.hokkaido.jp,kamisu.ibaraki.jp,kamisunagawa.hokkaido.jp,kamitonda.wakayama.jp,kamitsue.oita.jp,kamo.kyoto.jp,kamo.niigata.jp,kamoenai.hokkaido.jp,kamogawa.chiba.jp,kanagawa.jp,kanan.osaka.jp,kanazawa.ishikawa.jp,kanegasaki.iwate.jp,kaneyama.fukushima.jp,kaneyama.yamagata.jp,kani.gifu.jp,kanie.aichi.jp,kanmaki.nara.jp,kanna.gunma.jp,kannami.shizuoka.jp,kanonji.kagawa.jp,kanoya.kagoshima.jp,kanra.gunma.jp,kanuma.tochigi.jp,kanzaki.saga.jp,karacol.su,karaganda.su,karasjohka.no,karasjok.no,karasuyama.tochigi.jp,karate.museum,karatsu.saga.jp,karelia.su,karikatur.museum,kariwa.niigata.jp,kariya.aichi.jp,karlsoy.no,karmoy.no,karmøy.no,karpacz.pl,kartuzy.pl,karuizawa.nagano.jp,karumai.iwate.jp,kasahara.gifu.jp,kasai.hyogo.jp,kasama.ibaraki.jp,kasamatsu.gifu.jp,kasaoka.okayama.jp,kashiba.nara.jp,kashihara.nara.jp,kashima.ibaraki.jp,kashima.saga.jp,kashiwa.chiba.jp,kashiwara.osaka.jp,kashiwazaki.niigata.jp,kasuga.fukuoka.jp,kasuga.hyogo.jp,kasugai.aichi.jp,kasukabe.saitama.jp,kasumigaura.ibaraki.jp,kasuya.fukuoka.jp,kaszuby.pl,katagami.akita.jp,katano.osaka.jp,katashina.gunma.jp,katori.chiba.jp,katowice.pl,katsuragi.nara.jp,katsuragi.wakayama.jp,katsushika.tokyo.jp,katsuura.chiba.jp,katsuyama.fukui.jp,kaufen,kautokeino.no,kawaba.gunma.jp,kawachinagano.osaka.jp,kawagoe.mie.jp,kawagoe.saitama.jp,kawaguchi.saitama.jp,kawahara.tottori.jp,kawai.iwate.jp,kawai.nara.jp,kawajima.saitama.jp,kawakami.nagano.jp,kawakami.nara.jp,kawakita.ishikawa.jp,kawamata.fukushima.jp,kawaminami.miyazaki.jp,kawanabe.kagoshima.jp,kawanehon.shizuoka.jp,kawanishi.hyogo.jp,kawanishi.nara.jp,kawanishi.yamagata.jp,kawara.fukuoka.jp,kawasaki.jp,kawasaki.miyagi.jp,kawatana.nagasaki.jp,kawaue.gifu.jp,kawazu.shizuoka.jp,kayabe.hokkaido.jp,kazimierz-dolny.pl,kazo.saitama.jp,kazuno.akita.jp,kddi,ke,keisen.fukuoka.jp,kembuchi.hokkaido.jp,kep.tr,kepno.pl,kerryhotels,kerrylogistics,kerryproperties,ketrzyn.pl,keymachine.de,kfh,kg,kg.kr,kh,kh.ua,khakassia.su,kharkiv.ua,kharkov.ua,kherson.ua,khmelnitskiy.ua,khmelnytskyi.ua,khplay.nl,ki,kia,kibichuo.okayama.jp,kicks-ass.net,kicks-ass.org,kids.museum,kids.us,kiev.ua,kiho.mie.jp,kihoku.ehime.jp,kijo.miyazaki.jp,kikonai.hokkaido.jp,kikuchi.kumamoto.jp,kikugawa.shizuoka.jp,kim,kimino.wakayama.jp,kimitsu.chiba.jp,kimobetsu.hokkaido.jp,kin.okinawa.jp,kinder,kindle,kinghost.net,kinko.kagoshima.jp,kinokawa.wakayama.jp,kira.aichi.jp,kirkenes.no,kirovograd.ua,kiryu.gunma.jp,kisarazu.chiba.jp,kishiwada.osaka.jp,kiso.nagano.jp,kisofukushima.nagano.jp,kisosaki.mie.jp,kita.kyoto.jp,kita.osaka.jp,kita.tokyo.jp,kitaaiki.nagano.jp,kitaakita.akita.jp,kitadaito.okinawa.jp,kitagata.gifu.jp,kitagata.saga.jp,kitagawa.kochi.jp,kitagawa.miyazaki.jp,kitahata.saga.jp,kitahiroshima.hokkaido.jp,kitakami.iwate.jp,kitakata.fukushima.jp,kitakata.miyazaki.jp,kitakyushu.jp,kitami.hokkaido.jp,kitamoto.saitama.jp,kitanakagusuku.okinawa.jp,kitashiobara.fukushima.jp,kitaura.miyazaki.jp,kitayama.wakayama.jp,kitchen,kiwa.mie.jp,kiwi,kiwi.nz,kiyama.saga.jp,kiyokawa.kanagawa.jp,kiyosato.hokkaido.jp,kiyose.tokyo.jp,kiyosu.aichi.jp,kizu.kyoto.jp,klabu.no,klepp.no,klodzko.pl,klæbu.no,km,km.ua,kmpsp.gov.pl,kn,knightpoint.systems,knowsitall.info,knx-server.net,kobayashi.miyazaki.jp,kobe.jp,kobierzyce.pl,kochi.jp,kochi.kochi.jp,kodaira.tokyo.jp,koebenhavn.museum,koeln,koeln.museum,kofu.yamanashi.jp,koga.fukuoka.jp,koga.ibaraki.jp,koganei.tokyo.jp,koge.tottori.jp,koka.shiga.jp,kokonoe.oita.jp,kokubunji.tokyo.jp,kolobrzeg.pl,komae.tokyo.jp,komagane.nagano.jp,komaki.aichi.jp,komatsu,komatsu.ishikawa.jp,komatsushima.tokushima.jp,komforb.se,kommunalforbund.se,kommune.no,komono.mie.jp,komoro.nagano.jp,komvux.se,konan.aichi.jp,konan.shiga.jp,kongsberg.no,kongsvinger.no,konin.pl,konskowola.pl,konsulat.gov.pl,konyvelo.hu,koori.fukushima.jp,kopervik.no,koriyama.fukushima.jp,koryo.nara.jp,kosai.shizuoka.jp,kosaka.akita.jp,kosei.shiga.jp,kosher,koshigaya.saitama.jp,koshimizu.hokkaido.jp,koshu.yamanashi.jp,kosuge.yamanashi.jp,kota.aichi.jp,koto.shiga.jp,koto.tokyo.jp,kotohira.kagawa.jp,kotoura.tottori.jp,kouhoku.saga.jp,kounosu.saitama.jp,kouyama.kagoshima.jp,kouzushima.tokyo.jp,koya.wakayama.jp,koza.wakayama.jp,kozagawa.wakayama.jp,kozaki.chiba.jp,kozow.com,kp,kpmg,kpn,kppsp.gov.pl,kr,kr.com,kr.eu.org,kr.it,kr.ua,kraanghke.no,kragero.no,kragerø.no,krakow.pl,krasnik.pl,krasnodar.su,krd,kred,kristiansand.no,kristiansund.no,krodsherad.no,krokstadelva.no,krym.ua,kråanghke.no,krødsherad.no,ks.ua,ks.us,kuchinotsu.nagasaki.jp,kudamatsu.yamaguchi.jp,kudoyama.wakayama.jp,kui.hiroshima.jp,kuji.iwate.jp,kuju.oita.jp,kujukuri.chiba.jp,kuki.saitama.jp,kumagaya.saitama.jp,kumakogen.ehime.jp,kumamoto.jp,kumamoto.kumamoto.jp,kumano.hiroshima.jp,kumano.mie.jp,kumatori.osaka.jp,kumejima.okinawa.jp,kumenan.okayama.jp,kumiyama.kyoto.jp,kunden.ortsinfo.at,kunigami.okinawa.jp,kunimi.fukushima.jp,kunisaki.oita.jp,kunitachi.tokyo.jp,kunitomi.miyazaki.jp,kunneppu.hokkaido.jp,kunohe.iwate.jp,kunst.museum,kunstsammlung.museum,kunstunddesign.museum,kuokgroup,kurashiki.okayama.jp,kurate.fukuoka.jp,kure.hiroshima.jp,kurgan.su,kuriyama.hokkaido.jp,kurobe.toyama.jp,kurogi.fukuoka.jp,kuroishi.aomori.jp,kuroiso.tochigi.jp,kuromatsunai.hokkaido.jp,kurotaki.nara.jp,kurume.fukuoka.jp,kusatsu.gunma.jp,kusatsu.shiga.jp,kushima.miyazaki.jp,kushimoto.wakayama.jp,kushiro.hokkaido.jp,kustanai.ru,kustanai.su,kusu.oita.jp,kutchan.hokkaido.jp,kutno.pl,kuwana.mie.jp,kuzumaki.iwate.jp,kv.ua,kvafjord.no,kvalsund.no,kvam.no,kvanangen.no,kvinesdal.no,kvinnherad.no,kviteseid.no,kvitsoy.no,kvitsøy.no,kvæfjord.no,kvænangen.no,kw,kwp.gov.pl,kwpsp.gov.pl,ky,ky.us,kyiv.ua,kyonan.chiba.jp,kyotamba.kyoto.jp,kyotanabe.kyoto.jp,kyotango.kyoto.jp,kyoto,kyoto.jp,kyowa.akita.jp,kyowa.hokkaido.jp,kyuragi.saga.jp,kz,kárášjohka.no,kåfjord.no,l-o-g-i-n.de,l.bg,l.se,la,la-spezia.it,la.us,laakesvuemie.no,lab.ms,labor.museum,labour.museum,lacaixa,ladbrokes,lahppi.no,lajolla.museum,lakas.hu,lamborghini,lamer,lanbib.se,lancashire.museum,lancaster,lancia,lancome,land,land-4-sale.us,landes.museum,landing.myjino.ru,landrover,langevag.no,langevåg.no,lans.museum,lanxess,lapy.pl,laquila.it,lardal.no,larsson.museum,larvik.no,lasalle,laspezia.it,lat,latina.it,latino,latrobe,lavagis.no,lavangen.no,law,law.pro,law.za,lawyer,laz.it,lazio.it,lb,lc,lc.it,lcl.dev,lcube-server.de,lds,le.it,leadpages.co,leangaviika.no,lease,leasing.aero,leaŋgaviika.no,lebesby.no,lebork.pl,lebtimnetz.de,lecce.it,lecco.it,leclerc,leczna.pl,lefrak,leg.br,legal,legnica.pl,lego,leikanger.no,leirfjord.no,leirvik.no,leitungsen.de,leka.no,leksvik.no,lel.br,lelux.site,lenug.su,lenvik.no,lerdal.no,lesja.no,levanger.no,lewismiller.museum,lexus,lezajsk.pl,lg.jp,lg.ua,lgbt,li,li.it,liaison,lib.ak.us,lib.al.us,lib.ar.us,lib.as.us,lib.az.us,lib.ca.us,lib.co.us,lib.ct.us,lib.dc.us,lib.de.us,lib.ee,lib.fl.us,lib.ga.us,lib.gu.us,lib.hi.us,lib.ia.us,lib.id.us,lib.il.us,lib.in.us,lib.ks.us,lib.ky.us,lib.la.us,lib.ma.us,lib.md.us,lib.me.us,lib.mi.us,lib.mn.us,lib.mo.us,lib.ms.us,lib.mt.us,lib.nc.us,lib.nd.us,lib.ne.us,lib.nh.us,lib.nj.us,lib.nm.us,lib.nv.us,lib.ny.us,lib.oh.us,lib.ok.us,lib.or.us,lib.pa.us,lib.pr.us,lib.ri.us,lib.sc.us,lib.sd.us,lib.tn.us,lib.tx.us,lib.ut.us,lib.va.us,lib.vi.us,lib.vt.us,lib.wa.us,lib.wi.us,lib.wy.us,lidl,lier.no,lierne.no,life,lifeinsurance,lifestyle,lig.it,lighting,liguria.it,like,likes-pie.com,likescandy.com,lillehammer.no,lillesand.no,lilly,lima-city.at,lima-city.ch,lima-city.de,lima-city.rocks,lima.zone,limanowa.pl,limited,limo,lincoln,lincoln.museum,lindas.no,linde,lindesnes.no,lindås.no,link,linkitools.space,linkyard-cloud.ch,linkyard.cloud,linz.museum,lipsy,live,living,living.museum,livinghistory.museum,livorno.it,lixil,lk,llc,ln.cn,lo.it,loabat.no,loabát.no,loan,loans,localhistory.museum,localhost.daplie.me,locker,locus,lodi.it,lodingen.no,loft,loginline.app,loginline.dev,loginline.io,loginline.services,loginline.site,loginto.me,logistics.aero,logoip.com,logoip.de,lol,lom.it,lom.no,lombardia.it,lombardy.it,lomza.pl,london,london.cloudapps.digital,london.museum,londrina.br,loppa.no,lorenskog.no,losangeles.museum,loseyourip.com,loten.no,lotte,lotto,louvre.museum,love,lowicz.pl,loyalist.museum,lpages.co,lpl,lplfinancial,lpusercontent.com,lr,ls,lt,lt.eu.org,lt.it,lt.ua,ltd,ltd.co.im,ltd.cy,ltd.gi,ltd.hk,ltd.lk,ltd.ng,ltd.ua,ltd.uk,ltda,lu,lu.eu.org,lu.it,lubartow.pl,lubin.pl,lublin.pl,lucania.it,lucca.it,lucerne.museum,lug.org.uk,lugansk.ua,lugs.org.uk,lukow.pl,lund.no,lundbeck,lunner.no,lupin,luroy.no,lurøy.no,luster.no,lutsk.ua,luxe,luxembourg.museum,luxury,luzern.museum,lv,lv.eu.org,lv.ua,lviv.ua,ly,lyngdal.no,lyngen.no,láhppi.no,läns.museum,lærdal.no,lødingen.no,lørenskog.no,løten.no,m.bg,m.se,ma,ma.gov.br,ma.leg.br,ma.us,macapa.br,maceio.br,macerata.it,machida.tokyo.jp,macys,mad.museum,madrid,madrid.museum,maebashi.gunma.jp,magazine.aero,magentosite.cloud,maibara.shiga.jp,maif,mail.pl,maintenance.aero,maison,maizuru.kyoto.jp,makeup,makinohara.shizuoka.jp,makurazaki.kagoshima.jp,malatvuopmi.no,malbork.pl,mallorca.museum,malopolska.pl,malselv.no,malvik.no,mamurogawa.yamagata.jp,man,management,manaus.br,manchester.museum,mandal.no,mango,mangyshlak.su,maniwa.okayama.jp,manno.kagawa.jp,mansion.museum,mansions.museum,mantova.it,manx.museum,maori.nz,map,map.fastly.net,map.fastlylb.net,mar.it,marburg.museum,marche.it,marine.ru,maringa.br,maritime.museum,maritimo.museum,marker.no,market,marketing,markets,marnardal.no,marriott,marshalls,marugame.kagawa.jp,marumori.miyagi.jp,maryland.museum,marylhurst.museum,masaki.ehime.jp,maserati,masfjorden.no,mashike.hokkaido.jp,mashiki.kumamoto.jp,mashiko.tochigi.jp,masoy.no,massa-carrara.it,massacarrara.it,masuda.shimane.jp,mat.br,matera.it,matsubara.osaka.jp,matsubushi.saitama.jp,matsuda.kanagawa.jp,matsudo.chiba.jp,matsue.shimane.jp,matsukawa.nagano.jp,matsumae.hokkaido.jp,matsumoto.kagoshima.jp,matsumoto.nagano.jp,matsuno.ehime.jp,matsusaka.mie.jp,matsushige.tokushima.jp,matsushima.miyagi.jp,matsuura.nagasaki.jp,matsuyama.ehime.jp,matsuzaki.shizuoka.jp,matta-varjjat.no,mattel,mayfirst.info,mayfirst.org,mazowsze.pl,mazury.pl,mb.ca,mb.it,mba,mc,mc.eu.org,mc.it,mckinsey,md,md.ci,md.us,me,me.eu.org,me.it,me.ke,me.tz,me.uk,me.us,med,med.br,med.ec,med.ee,med.ht,med.ly,med.om,med.pa,med.pl,med.pro,med.sa,med.sd,medecin.fr,medecin.km,media,media.aero,media.hu,media.museum,media.pl,medical.museum,medicina.bo,medio-campidano.it,mediocampidano.it,medizinhistorisches.museum,meeres.museum,meet,meguro.tokyo.jp,mein-iserv.de,mein-vigor.de,meiwa.gunma.jp,meiwa.mie.jp,meland.no,melbourne,meldal.no,melhus.no,meloy.no,meløy.no,members.linode.com,meme,memorial,memorial.museum,memset.net,men,menu,meraker.no,merckmsd,merseine.nu,meråker.no,mesaverde.museum,messina.it,meteorapp.com,metlife,mex.com,mg,mg.gov.br,mg.leg.br,mh,mi.it,mi.th,mi.us,miami,miasa.nagano.jp,miasta.pl,mibu.tochigi.jp,michigan.museum,microlight.aero,microsoft,midatlantic.museum,midori.chiba.jp,midori.gunma.jp,midsund.no,midtre-gauldal.no,mie.jp,mielec.pl,mielno.pl,mifune.kumamoto.jp,mihama.aichi.jp,mihama.chiba.jp,mihama.fukui.jp,mihama.mie.jp,mihama.wakayama.jp,mihara.hiroshima.jp,mihara.kochi.jp,miharu.fukushima.jp,miho.ibaraki.jp,mikasa.hokkaido.jp,mikawa.yamagata.jp,miki.hyogo.jp,mil,mil.ac,mil.ae,mil.al,mil.ar,mil.az,mil.ba,mil.bo,mil.br,mil.by,mil.cl,mil.cn,mil.co,mil.do,mil.ec,mil.eg,mil.ge,mil.gh,mil.gt,mil.hn,mil.id,mil.in,mil.iq,mil.jo,mil.kg,mil.km,mil.kr,mil.kz,mil.lv,mil.mg,mil.mv,mil.my,mil.mz,mil.ng,mil.ni,mil.no,mil.nz,mil.pe,mil.ph,mil.pl,mil.py,mil.qa,mil.ru,mil.rw,mil.sh,mil.st,mil.sy,mil.tj,mil.tm,mil.to,mil.tr,mil.tw,mil.tz,mil.uy,mil.vc,mil.ve,mil.za,mil.zm,mil.zw,milan.it,milano.it,military.museum,mill.museum,mima.tokushima.jp,mimata.miyazaki.jp,minakami.gunma.jp,minamata.kumamoto.jp,minami-alps.yamanashi.jp,minami.fukuoka.jp,minami.kyoto.jp,minami.tokushima.jp,minamiaiki.nagano.jp,minamiashigara.kanagawa.jp,minamiawaji.hyogo.jp,minamiboso.chiba.jp,minamidaito.okinawa.jp,minamiechizen.fukui.jp,minamifurano.hokkaido.jp,minamiise.mie.jp,minamiizu.shizuoka.jp,minamimaki.nagano.jp,minamiminowa.nagano.jp,minamioguni.kumamoto.jp,minamisanriku.miyagi.jp,minamitane.kagoshima.jp,minamiuonuma.niigata.jp,minamiyamashiro.kyoto.jp,minano.saitama.jp,minato.osaka.jp,minato.tokyo.jp,mincom.tn,mine.nu,miners.museum,mini,mining.museum,miniserver.com,minnesota.museum,mino.gifu.jp,minobu.yamanashi.jp,minoh.osaka.jp,minokamo.gifu.jp,minowa.nagano.jp,mint,misaki.okayama.jp,misaki.osaka.jp,misasa.tottori.jp,misato.akita.jp,misato.miyagi.jp,misato.saitama.jp,misato.shimane.jp,misato.wakayama.jp,misawa.aomori.jp,misconfused.org,mishima.fukushima.jp,mishima.shizuoka.jp,missile.museum,missoula.museum,misugi.mie.jp,mit,mitaka.tokyo.jp,mitake.gifu.jp,mitane.akita.jp,mito.ibaraki.jp,mitou.yamaguchi.jp,mitoyo.kagawa.jp,mitsubishi,mitsue.nara.jp,mitsuke.niigata.jp,miura.kanagawa.jp,miyada.nagano.jp,miyagi.jp,miyake.nara.jp,miyako.fukuoka.jp,miyako.iwate.jp,miyakonojo.miyazaki.jp,miyama.fukuoka.jp,miyama.mie.jp,miyashiro.saitama.jp,miyawaka.fukuoka.jp,miyazaki.jp,miyazaki.miyazaki.jp,miyazu.kyoto.jp,miyoshi.aichi.jp,miyoshi.hiroshima.jp,miyoshi.saitama.jp,miyoshi.tokushima.jp,miyota.nagano.jp,mizuho.tokyo.jp,mizumaki.fukuoka.jp,mizunami.gifu.jp,mizusawa.iwate.jp,mjondalen.no,mjøndalen.no,mk,mk.eu.org,mk.ua,ml,mlb,mlbfan.org,mls,mm,mma,mmafan.biz,mn,mn.it,mn.us,mo,mo-i-rana.no,mo-siemens.io,mo.cn,mo.it,mo.us,moareke.no,mobara.chiba.jp,mobi,mobi.gp,mobi.ke,mobi.na,mobi.ng,mobi.tt,mobi.tz,mobile,mobily,mochizuki.nagano.jp,mod.gi,moda,modalen.no,modelling.aero,modena.it,modern.museum,modum.no,moe,moi,moka.tochigi.jp,mol.it,molde.no,molise.it,mom,moma.museum,mombetsu.hokkaido.jp,monash,money,money.museum,monmouth.museum,monster,monticello.museum,montreal.museum,monza-brianza.it,monza-e-della-brianza.it,monza.it,monzabrianza.it,monzaebrianza.it,monzaedellabrianza.it,moonscale.io,moonscale.net,mopar,mordovia.ru,mordovia.su,morena.br,moriguchi.osaka.jp,morimachi.shizuoka.jp,morioka.iwate.jp,moriya.ibaraki.jp,moriyama.shiga.jp,moriyoshi.akita.jp,mormon,morotsuka.miyazaki.jp,moroyama.saitama.jp,mortgage,moscow,moscow.museum,moseushi.hokkaido.jp,mosjoen.no,mosjøen.no,moskenes.no,moss.no,mosvik.no,motegi.tochigi.jp,moto,motobu.okinawa.jp,motorcycle.museum,motorcycles,motosu.gifu.jp,motoyama.kochi.jp,mov,movie,movimiento.bo,movistar,mozilla-iot.org,moåreke.no,mp,mp.br,mq,mr,mr.no,mragowo.pl,ms,ms.gov.br,ms.it,ms.kr,ms.leg.br,ms.us,msd,msk.ru,msk.su,mt,mt.eu.org,mt.gov.br,mt.it,mt.leg.br,mt.us,mtn,mtr,mu,muenchen.museum,muenster.museum,mugi.tokushima.jp,muika.niigata.jp,mukawa.hokkaido.jp,muko.kyoto.jp,mulhouse.museum,munakata.fukuoka.jp,muncie.museum,muni.il,muosat.no,muosát.no,mup.gov.pl,murakami.niigata.jp,murata.miyagi.jp,murayama.yamagata.jp,murmansk.su,muroran.hokkaido.jp,muroto.kochi.jp,mus.br,mus.mi.us,musashimurayama.tokyo.jp,musashino.tokyo.jp,museet.museum,museum,museum.mv,museum.mw,museum.no,museum.om,museum.tt,museumcenter.museum,museumvereniging.museum,music.museum,musica.ar,musica.bo,mutsu.aomori.jp,mutsuzawa.chiba.jp,mutual,mv,mw,mw.gov.pl,mx,mx.na,my,my-firewall.org,my-gateway.de,my-router.de,my-vigor.de,my-wan.de,my.eu.org,my.id,myactivedirectory.com,myasustor.com,mycd.eu,mydatto.com,mydatto.net,myddns.rocks,mydissent.net,mydobiss.com,mydrobo.com,myds.me,myeffect.net,myfirewall.org,myfritz.net,myftp.biz,myftp.org,myhome-server.de,myiphost.com,myjino.ru,mykolaiv.ua,mymailer.com.tw,mymediapc.net,myoko.niigata.jp,mypep.link,mypets.ws,myphotos.cc,mypi.co,mypsx.net,myqnapcloud.com,myravendb.com,mysecuritycamera.com,mysecuritycamera.net,mysecuritycamera.org,myshopblocks.com,mytis.ru,mytuleap.com,myvnc.com,mywire.org,mz,málatvuopmi.no,mátta-várjjat.no,målselv.no,måsøy.no,māori.nz,n.bg,n.se,n4t.co,na,na.it,naamesjevuemie.no,nab,nabari.mie.jp,nachikatsuura.wakayama.jp,nadex,nagahama.shiga.jp,nagai.yamagata.jp,nagano.jp,nagano.nagano.jp,naganohara.gunma.jp,nagaoka.niigata.jp,nagaokakyo.kyoto.jp,nagara.chiba.jp,nagareyama.chiba.jp,nagasaki.jp,nagasaki.nagasaki.jp,nagasu.kumamoto.jp,nagato.yamaguchi.jp,nagatoro.saitama.jp,nagawa.nagano.jp,nagi.okayama.jp,nagiso.nagano.jp,nago.okinawa.jp,nagoya,nagoya.jp,naha.okinawa.jp,nahari.kochi.jp,naie.hokkaido.jp,naka.hiroshima.jp,naka.ibaraki.jp,nakadomari.aomori.jp,nakagawa.fukuoka.jp,nakagawa.hokkaido.jp,nakagawa.nagano.jp,nakagawa.tokushima.jp,nakagusuku.okinawa.jp,nakagyo.kyoto.jp,nakai.kanagawa.jp,nakama.fukuoka.jp,nakamichi.yamanashi.jp,nakamura.kochi.jp,nakaniikawa.toyama.jp,nakano.nagano.jp,nakano.tokyo.jp,nakanojo.gunma.jp,nakanoto.ishikawa.jp,nakasatsunai.hokkaido.jp,nakatane.kagoshima.jp,nakatombetsu.hokkaido.jp,nakatsugawa.gifu.jp,nakayama.yamagata.jp,nakijin.okinawa.jp,naklo.pl,nalchik.ru,nalchik.su,namdalseid.no,name,name.az,name.cy,name.eg,name.et,name.hr,name.jo,name.mk,name.mv,name.my,name.na,name.ng,name.pr,name.qa,name.tj,name.tr,name.tt,name.vn,namegata.ibaraki.jp,namegawa.saitama.jp,namerikawa.toyama.jp,namie.fukushima.jp,namikata.ehime.jp,namsos.no,namsskogan.no,nanae.hokkaido.jp,nanao.ishikawa.jp,nanbu.tottori.jp,nanbu.yamanashi.jp,nango.fukushima.jp,nanjo.okinawa.jp,nankoku.kochi.jp,nanmoku.gunma.jp,nannestad.no,nanporo.hokkaido.jp,nantan.kyoto.jp,nanto.toyama.jp,nanyo.yamagata.jp,naoshima.kagawa.jp,naples.it,napoli.it,nara.jp,nara.nara.jp,narashino.chiba.jp,narita.chiba.jp,naroy.no,narusawa.yamanashi.jp,naruto.tokushima.jp,narviika.no,narvik.no,nasu.tochigi.jp,nasushiobara.tochigi.jp,nat.tn,natal.br,national.museum,nationalfirearms.museum,nationalheritage.museum,nationwide,nativeamerican.museum,natori.miyagi.jp,natura,natural.bo,naturalhistory.museum,naturalhistorymuseum.museum,naturalsciences.museum,naturbruksgymn.se,nature.museum,naturhistorisches.museum,natuurwetenschappen.museum,naumburg.museum,naustdal.no,naval.museum,navigation.aero,navoi.su,navuotna.no,navy,nayoro.hokkaido.jp,nb.ca,nba,nc,nc.tr,nc.us,nctu.me,nd.us,ne,ne.jp,ne.ke,ne.kr,ne.pw,ne.tz,ne.ug,ne.us,neat-url.com,nebraska.museum,nec,nedre-eiker.no,nemuro.hokkaido.jp,nerdpol.ovh,nerima.tokyo.jp,nes.akershus.no,nes.buskerud.no,nesna.no,nesodden.no,nesoddtangen.no,nesseby.no,nesset.no,net,net-freaks.com,net.ac,net.ae,net.af,net.ag,net.ai,net.al,net.am,net.ar,net.au,net.az,net.ba,net.bb,net.bh,net.bm,net.bn,net.bo,net.br,net.bs,net.bt,net.bz,net.ci,net.cm,net.cn,net.co,net.cu,net.cw,net.cy,net.dm,net.do,net.dz,net.ec,net.eg,net.et,net.eu.org,net.ge,net.gg,net.gl,net.gn,net.gp,net.gr,net.gt,net.gu,net.gy,net.hk,net.hn,net.ht,net.id,net.il,net.im,net.in,net.iq,net.ir,net.is,net.je,net.jo,net.kg,net.ki,net.kn,net.kw,net.ky,net.kz,net.la,net.lb,net.lc,net.lk,net.lr,net.ls,net.lv,net.ly,net.ma,net.me,net.mk,net.ml,net.mo,net.ms,net.mt,net.mu,net.mv,net.mw,net.mx,net.my,net.mz,net.nf,net.ng,net.ni,net.nr,net.nz,net.om,net.pa,net.pe,net.ph,net.pk,net.pl,net.pn,net.pr,net.ps,net.pt,net.py,net.qa,net.ru,net.rw,net.sa,net.sb,net.sc,net.sd,net.sg,net.sh,net.sl,net.so,net.st,net.sy,net.th,net.tj,net.tm,net.tn,net.to,net.tr,net.tt,net.tw,net.ua,net.uk,net.uy,net.uz,net.vc,net.ve,net.vi,net.vn,net.vu,net.ws,net.za,net.zm,netbank,netflix,netlify.com,network,neues.museum,neustar,new,newhampshire.museum,newholland,newjersey.museum,newmexico.museum,newport.museum,news,news.hu,newspaper.museum,newyork.museum,next,nextdirect,nexus,neyagawa.osaka.jp,nf,nf.ca,nfl,nflfan.org,nfshost.com,ng,ng.city,ng.eu.org,ng.ink,ng.school,ngo,ngo.lk,ngo.ph,ngo.za,ngrok.io,nh-serv.co.uk,nh.us,nhk,nhlfan.net,nhs.uk,ni,nic.in,nic.tj,nic.za,nichinan.miyazaki.jp,nichinan.tottori.jp,nico,nid.io,niepce.museum,nieruchomosci.pl,niigata.jp,niigata.niigata.jp,niihama.ehime.jp,niikappu.hokkaido.jp,niimi.okayama.jp,niiza.saitama.jp,nikaho.akita.jp,nike,niki.hokkaido.jp,nikko.tochigi.jp,nikolaev.ua,nikon,ninja,ninohe.iwate.jp,ninomiya.kanagawa.jp,nirasaki.yamanashi.jp,nis.za,nishi.fukuoka.jp,nishi.osaka.jp,nishiaizu.fukushima.jp,nishiarita.saga.jp,nishiawakura.okayama.jp,nishiazai.shiga.jp,nishigo.fukushima.jp,nishihara.kumamoto.jp,nishihara.okinawa.jp,nishiizu.shizuoka.jp,nishikata.tochigi.jp,nishikatsura.yamanashi.jp,nishikawa.yamagata.jp,nishimera.miyazaki.jp,nishinomiya.hyogo.jp,nishinoomote.kagoshima.jp,nishinoshima.shimane.jp,nishio.aichi.jp,nishiokoppe.hokkaido.jp,nishitosa.kochi.jp,nishiwaki.hyogo.jp,nissan,nissay,nissedal.no,nisshin.aichi.jp,niteroi.br,nittedal.no,niyodogawa.kochi.jp,nj.us,nl,nl.ca,nl.eu.org,nl.no,nm.cn,nm.us,no,no-ip.biz,no-ip.ca,no-ip.co.uk,no-ip.info,no-ip.net,no-ip.org,no.com,no.eu.org,no.it,nobeoka.miyazaki.jp,noboribetsu.hokkaido.jp,noda.chiba.jp,noda.iwate.jp,nodebalancer.linode.com,nodum.co,nodum.io,nogata.fukuoka.jp,nogi.tochigi.jp,noheji.aomori.jp,noho.st,nohost.me,noip.me,noip.us,nokia,nom.ad,nom.ae,nom.af,nom.ag,nom.ai,nom.al,nom.br,nom.cl,nom.co,nom.es,nom.fr,nom.gd,nom.ge,nom.gl,nom.gt,nom.hn,nom.im,nom.ke,nom.km,nom.li,nom.mg,nom.mk,nom.nc,nom.ni,nom.nu,nom.pa,nom.pe,nom.pl,nom.pw,nom.qa,nom.re,nom.ro,nom.rs,nom.si,nom.st,nom.tj,nom.tm,nom.ug,nom.uy,nom.vc,nom.vg,nom.za,nombre.bo,nome.pt,nomi.ishikawa.jp,nonoichi.ishikawa.jp,nord-aurdal.no,nord-fron.no,nord-odal.no,norddal.no,nordkapp.no,nordre-land.no,nordreisa.no,nore-og-uvdal.no,norfolk.museum,north-kazakhstan.su,north.museum,northwesternmutual,norton,nose.osaka.jp,nosegawa.nara.jp,noshiro.akita.jp,not.br,notaires.fr,notaires.km,noticias.bo,noto.ishikawa.jp,notodden.no,notogawa.shiga.jp,notteroy.no,nov.ru,nov.su,novara.it,now,now-dns.net,now-dns.org,now-dns.top,now.sh,nowaruda.pl,nowruz,nowtv,nozawaonsen.nagano.jp,np,nr,nra,nrw,nrw.museum,ns.ca,nsn.us,nsupdate.info,nsw.au,nsw.edu.au,nt.au,nt.ca,nt.edu.au,nt.no,nt.ro,ntdll.top,ntr.br,ntt,nu,nu.ca,nu.it,nuernberg.museum,numata.gunma.jp,numata.hokkaido.jp,numazu.shizuoka.jp,nuoro.it,nuremberg.museum,nv.us,nx.cn,ny.us,nyc,nyc.mn,nyc.museum,nym.by,nym.bz,nym.ec,nym.gr,nym.gy,nym.hk,nym.ie,nym.kz,nym.la,nym.lc,nym.li,nym.lt,nym.lu,nym.me,nym.mn,nym.mx,nym.nz,nym.pe,nym.pt,nym.ro,nym.sk,nym.su,nym.sx,nym.tw,nyny.museum,nysa.pl,nyuzen.toyama.jp,nz,nz.eu.org,návuotna.no,nååmesjevuemie.no,nærøy.no,nøtterøy.no,o.bg,o.se,oamishirasato.chiba.jp,oarai.ibaraki.jp,obama.fukui.jp,obama.nagasaki.jp,obanazawa.yamagata.jp,obi,obihiro.hokkaido.jp,obira.hokkaido.jp,obninsk.su,observer,obu.aichi.jp,obuse.nagano.jp,oceanographic.museum,oceanographique.museum,ochi.kochi.jp,od.ua,odate.akita.jp,odawara.kanagawa.jp,odda.no,odesa.ua,odessa.ua,odo.br,oe.yamagata.jp,of.by,of.fashion,of.football,of.london,of.no,of.work,off,off.ai,office,office-on-the.net,official.academy,ofunato.iwate.jp,og.ao,og.it,oga.akita.jp,ogaki.gifu.jp,ogano.saitama.jp,ogasawara.tokyo.jp,ogata.akita.jp,ogawa.ibaraki.jp,ogawa.nagano.jp,ogawa.saitama.jp,ogawara.miyagi.jp,ogi.saga.jp,ogimi.okinawa.jp,ogliastra.it,ogori.fukuoka.jp,ogose.saitama.jp,oguchi.aichi.jp,oguni.kumamoto.jp,oguni.yamagata.jp,oh.us,oharu.aichi.jp,ohda.shimane.jp,ohi.fukui.jp,ohira.miyagi.jp,ohira.tochigi.jp,ohkura.yamagata.jp,ohtawara.tochigi.jp,oi.kanagawa.jp,oirase.aomori.jp,oirm.gov.pl,oishida.yamagata.jp,oiso.kanagawa.jp,oita.jp,oita.oita.jp,oizumi.gunma.jp,oji.nara.jp,ojiya.niigata.jp,ok.us,okagaki.fukuoka.jp,okawa.fukuoka.jp,okawa.kochi.jp,okaya.nagano.jp,okayama.jp,okayama.okayama.jp,okazaki.aichi.jp,okegawa.saitama.jp,oketo.hokkaido.jp,oki.fukuoka.jp,okinawa,okinawa.jp,okinawa.okinawa.jp,okinoshima.shimane.jp,okoppe.hokkaido.jp,oksnes.no,okuizumo.shimane.jp,okuma.fukushima.jp,okutama.tokyo.jp,ol.no,olawa.pl,olayan,olayangroup,olbia-tempio.it,olbiatempio.it,oldnavy,olecko.pl,olkusz.pl,ollo,olsztyn.pl,om,omachi.nagano.jp,omachi.saga.jp,omaezaki.shizuoka.jp,omaha.museum,omasvuotna.no,ome.tokyo.jp,omega,omi.nagano.jp,omi.niigata.jp,omigawa.chiba.jp,omihachiman.shiga.jp,omitama.ibaraki.jp,omiya.saitama.jp,omotego.fukushima.jp,omura.nagasaki.jp,omuta.fukuoka.jp,on-aptible.com,on-rancher.cloud,on-rio.io,on-the-web.tv,on-web.fr,on.ca,on.fashion,onagawa.miyagi.jp,one,ong,ong.br,onga.fukuoka.jp,onion,onjuku.chiba.jp,onl,online,online.museum,online.th,onna.okinawa.jp,ono.fukui.jp,ono.fukushima.jp,ono.hyogo.jp,onojo.fukuoka.jp,onomichi.hiroshima.jp,onred.one,onrender.com,ontario.museum,onthewifi.com,onyourside,ooguy.com,ookuwa.nagano.jp,ooo,ooshika.nagano.jp,open,openair.museum,opencraft.hosting,operaunite.com,opoczno.pl,opole.pl,oppdal.no,oppegard.no,oppegård.no,or.at,or.bi,or.ci,or.cr,or.id,or.it,or.jp,or.ke,or.kr,or.mu,or.na,or.pw,or.th,or.tz,or.ug,or.us,ora.gunma.jp,oracle,orange,oregon.museum,oregontrail.museum,org,org.ac,org.ae,org.af,org.ag,org.ai,org.al,org.am,org.ar,org.au,org.az,org.ba,org.bb,org.bh,org.bi,org.bm,org.bn,org.bo,org.br,org.bs,org.bt,org.bw,org.bz,org.ci,org.cn,org.co,org.cu,org.cw,org.cy,org.dm,org.do,org.dz,org.ec,org.ee,org.eg,org.es,org.et,org.ge,org.gg,org.gh,org.gi,org.gl,org.gn,org.gp,org.gr,org.gt,org.gu,org.gy,org.hk,org.hn,org.ht,org.hu,org.il,org.im,org.in,org.iq,org.ir,org.is,org.je,org.jo,org.kg,org.ki,org.km,org.kn,org.kp,org.kw,org.ky,org.kz,org.la,org.lb,org.lc,org.lk,org.lr,org.ls,org.lv,org.ly,org.ma,org.me,org.mg,org.mk,org.ml,org.mn,org.mo,org.ms,org.mt,org.mu,org.mv,org.mw,org.mx,org.my,org.mz,org.na,org.ng,org.ni,org.nr,org.nz,org.om,org.pa,org.pe,org.pf,org.ph,org.pk,org.pl,org.pn,org.pr,org.ps,org.pt,org.py,org.qa,org.ro,org.rs,org.ru,org.rw,org.sa,org.sb,org.sc,org.sd,org.se,org.sg,org.sh,org.sl,org.sn,org.so,org.st,org.sv,org.sy,org.sz,org.tj,org.tm,org.tn,org.to,org.tr,org.tt,org.tw,org.ua,org.ug,org.uk,org.uy,org.uz,org.vc,org.ve,org.vi,org.vn,org.vu,org.ws,org.za,org.zm,org.zw,organic,origins,oristano.it,orkanger.no,orkdal.no,orland.no,orskog.no,orsta.no,orx.biz,os.hedmark.no,os.hordaland.no,osaka,osaka.jp,osakasayama.osaka.jp,osaki.miyagi.jp,osakikamijima.hiroshima.jp,osasco.br,osen.no,oseto.nagasaki.jp,oshima.tokyo.jp,oshima.yamaguchi.jp,oshino.yamanashi.jp,oshu.iwate.jp,oslo.no,osoyro.no,osteroy.no,osterøy.no,ostre-toten.no,ostroda.pl,ostroleka.pl,ostrowiec.pl,ostrowwlkp.pl,osøyro.no,ot.it,ota.gunma.jp,ota.tokyo.jp,otago.museum,otake.hiroshima.jp,otaki.chiba.jp,otaki.nagano.jp,otaki.saitama.jp,otama.fukushima.jp,otap.co,otari.nagano.jp,otaru.hokkaido.jp,other.nf,oto.fukuoka.jp,otobe.hokkaido.jp,otofuke.hokkaido.jp,otoineppu.hokkaido.jp,otoyo.kochi.jp,otsu.shiga.jp,otsuchi.iwate.jp,otsuka,otsuki.kochi.jp,otsuki.yamanashi.jp,ott,ouchi.saga.jp,ouda.nara.jp,oum.gov.pl,oumu.hokkaido.jp,outsystemscloud.com,overhalla.no,ovh,ovre-eiker.no,owani.aomori.jp,owariasahi.aichi.jp,own.pm,ownip.net,ownprovider.com,ox.rs,oxford.museum,oy.lc,oyabe.toyama.jp,oyama.tochigi.jp,oyamazaki.kyoto.jp,oyer.no,oygarden.no,oyodo.nara.jp,oystre-slidre.no,oz.au,ozora.hokkaido.jp,ozu.ehime.jp,ozu.kumamoto.jp,p.bg,p.se,pa,pa.gov.br,pa.gov.pl,pa.it,pa.leg.br,pa.us,pacific.museum,paderborn.museum,padova.it,padua.it,page,pagefrontapp.com,pagespeedmobilizer.com,palace.museum,paleo.museum,palermo.it,palmas.br,palmsprings.museum,panama.museum,panasonic,pantheonsite.io,parachuting.aero,paragliding.aero,paris,paris.eu.org,paris.museum,parliament.cy,parliament.nz,parma.it,paroch.k12.ma.us,pars,parti.se,partners,parts,party,pasadena.museum,passagens,passenger-association.aero,patria.bo,pavia.it,pay,pb.ao,pb.gov.br,pb.leg.br,pc.it,pc.pl,pccw,pcloud.host,pd.it,pe,pe.ca,pe.gov.br,pe.it,pe.kr,pe.leg.br,penza.su,per.la,per.nf,per.sg,perso.ht,perso.sn,perso.tn,perugia.it,pesaro-urbino.it,pesarourbino.it,pescara.it,pet,pf,pfizer,pg,pg.it,pgafan.net,pgfog.com,ph,pharmacien.fr,pharmaciens.km,pharmacy,pharmacy.museum,phd,philadelphia.museum,philadelphiaarea.museum,philately.museum,philips,phoenix.museum,phone,photo,photography,photography.museum,photos,physio,pi.gov.br,pi.it,pi.leg.br,piacenza.it,piaget,pics,pictet,pictures,pid,piedmont.it,piemonte.it,pila.pl,pilot.aero,pilots.museum,pimienta.org,pin,pinb.gov.pl,ping,pink,pioneer,pippu.hokkaido.jp,pisa.it,pistoia.it,pisz.pl,pittsburgh.museum,piw.gov.pl,pixolino.com,pizza,pk,pl,pl.eu.org,pl.ua,place,planetarium.museum,plantation.museum,plants.museum,platform.sh,platformsh.site,play,playstation,plaza.museum,plc.co.im,plc.ly,plc.uk,plo.ps,plumbing,plurinacional.bo,plus,pm,pmn.it,pn,pn.it,pnc,po.gov.pl,po.it,poa.br,podhale.pl,podlasie.pl,podzone.net,podzone.org,pohl,point2this.com,pointto.us,poivron.org,poker,pokrovsk.su,pol.dz,pol.ht,pol.tr,police.uk,politica.bo,politie,polkowice.pl,poltava.ua,pomorskie.pl,pomorze.pl,poniatowa.pl,ponpes.id,pony.club,pordenone.it,porn,porsanger.no,porsangu.no,porsgrunn.no,porsáŋgu.no,port.fr,portal.museum,portland.museum,portlligat.museum,post,posts-and-telecommunications.museum,potager.org,potenza.it,powiat.pl,poznan.pl,pp.az,pp.ru,pp.se,pp.ua,ppg.br,pr,pr.gov.br,pr.it,pr.leg.br,pr.us,pramerica,prato.it,praxi,prd.fr,prd.km,prd.mg,preservation.museum,presidio.museum,press,press.aero,press.cy,press.ma,press.museum,press.se,presse.ci,presse.km,presse.ml,pri.ee,prime,principe.st,priv.at,priv.hu,priv.me,priv.no,priv.pl,privatizehealthinsurance.net,pro,pro.az,pro.br,pro.cy,pro.ec,pro.ht,pro.mv,pro.na,pro.om,pro.pr,pro.tt,pro.vn,prochowice.pl,prod,production.aero,productions,prof,prof.pr,profesional.bo,progressive,project.museum,promo,properties,property,protection,protonet.io,pru,prudential,pruszkow.pl,prvcy.page,przeworsk.pl,ps,psc.br,psi.br,psp.gov.pl,psse.gov.pl,pt,pt.eu.org,pt.it,ptplus.fit,pu.it,pub,pub.sa,publ.pt,public.museum,publishproxy.com,pubol.museum,pubtls.org,pueblo.bo,pug.it,puglia.it,pulawy.pl,pup.gov.pl,pv.it,pvh.br,pvt.ge,pvt.k12.ma.us,pw,pwc,py,pyatigorsk.ru,pz.it,q-a.eu.org,q.bg,qa,qa2.com,qc.ca,qc.com,qh.cn,qld.au,qld.edu.au,qld.gov.au,qpon,qsl.br,qualifioapp.com,quebec,quebec.museum,quest,quicksytes.com,quipelements.com,qvc,r.bg,r.cdn77.net,r.se,ra.it,racing,rackmaze.com,rackmaze.net,rade.no,radio,radio.br,radom.pl,radoy.no,radøy.no,ragusa.it,rahkkeravju.no,raholt.no,raid,railroad.museum,railway.museum,raisa.no,rakkestad.no,ralingen.no,rana.no,randaberg.no,rankoshi.hokkaido.jp,ranzan.saitama.jp,ras.ru,rauma.no,ravendb.community,ravendb.me,ravendb.run,ravenna.it,rawa-maz.pl,rc.it,re,re.it,re.kr,read,read-books.org,readmyblog.org,readthedocs.io,realestate,realestate.pl,realm.cz,realtor,realty,rebun.hokkaido.jp,rec.br,rec.co,rec.nf,rec.ro,rec.ve,recht.pro,recife.br,recipes,recreation.aero,red,red.sv,redirectme.net,redstone,redumbrella,reg.dk,reggio-calabria.it,reggio-emilia.it,reggiocalabria.it,reggioemilia.it,rehab,reise,reisen,reit,reklam.hu,rel.ht,rel.pl,reliance,remotewd.com,ren,rendalen.no,rennebu.no,rennesoy.no,rennesøy.no,rent,rentals,rep.kp,repair,repbody.aero,repl.co,repl.run,report,republican,res.aero,res.in,research.aero,research.museum,resindevice.io,resistance.museum,rest,restaurant,review,reviews,revista.bo,rexroth,rg.it,rhcloud.com,ri.it,ri.us,ribeirao.br,rich,richardli,ricoh,rieti.it,rifu.miyagi.jp,rightathome,riik.ee,rikubetsu.hokkaido.jp,rikuzentakata.iwate.jp,ril,rimini.it,rindal.no,ringebu.no,ringerike.no,ringsaker.no,rio,rio.br,riobranco.br,riodejaneiro.museum,riopreto.br,rip,rishiri.hokkaido.jp,rishirifuji.hokkaido.jp,risor.no,rissa.no,risør.no,ritto.shiga.jp,rivne.ua,rj.gov.br,rj.leg.br,rl.no,rm.it,rmit,rn.gov.br,rn.it,rn.leg.br,rnrt.tn,rns.tn,rnu.tn,ro,ro.eu.org,ro.gov.br,ro.im,ro.it,ro.leg.br,roan.no,rocher,rochester.museum,rockart.museum,rocks,rodeo,rodoy.no,rogers,rokunohe.aomori.jp,rollag.no,roma.it,roma.museum,rome.it,romsa.no,romskog.no,room,roros.no,rost.no,rotorcraft.aero,router.management,rovigo.it,rovno.ua,royken.no,royrvik.no,rr.gov.br,rr.leg.br,rs,rs.gov.br,rs.leg.br,rsc.cdn77.org,rsvp,ru,ru.com,ru.eu.org,ru.net,rugby,ruhr,run,run.app,ruovat.no,russia.museum,rv.ua,rw,rwe,rybnik.pl,rygge.no,ryokami.saitama.jp,ryugasaki.ibaraki.jp,ryukyu,ryuoh.shiga.jp,rzeszow.pl,rzgw.gov.pl,ráhkkerávju.no,ráisa.no,råde.no,råholt.no,rælingen.no,rødøy.no,rømskog.no,røros.no,røst.no,røyken.no,røyrvik.no,s.bg,s.se,s3-ap-northeast-1.amazonaws.com,s3-ap-northeast-2.amazonaws.com,s3-ap-south-1.amazonaws.com,s3-ap-southeast-1.amazonaws.com,s3-ap-southeast-2.amazonaws.com,s3-ca-central-1.amazonaws.com,s3-eu-central-1.amazonaws.com,s3-eu-west-1.amazonaws.com,s3-eu-west-2.amazonaws.com,s3-eu-west-3.amazonaws.com,s3-external-1.amazonaws.com,s3-fips-us-gov-west-1.amazonaws.com,s3-sa-east-1.amazonaws.com,s3-us-east-2.amazonaws.com,s3-us-gov-west-1.amazonaws.com,s3-us-west-1.amazonaws.com,s3-us-west-2.amazonaws.com,s3-website-ap-northeast-1.amazonaws.com,s3-website-ap-southeast-1.amazonaws.com,s3-website-ap-southeast-2.amazonaws.com,s3-website-eu-west-1.amazonaws.com,s3-website-sa-east-1.amazonaws.com,s3-website-us-east-1.amazonaws.com,s3-website-us-west-1.amazonaws.com,s3-website-us-west-2.amazonaws.com,s3-website.ap-northeast-2.amazonaws.com,s3-website.ap-south-1.amazonaws.com,s3-website.ca-central-1.amazonaws.com,s3-website.eu-central-1.amazonaws.com,s3-website.eu-west-2.amazonaws.com,s3-website.eu-west-3.amazonaws.com,s3-website.us-east-2.amazonaws.com,s3.amazonaws.com,s3.ap-northeast-2.amazonaws.com,s3.ap-south-1.amazonaws.com,s3.ca-central-1.amazonaws.com,s3.cn-north-1.amazonaws.com.cn,s3.dualstack.ap-northeast-1.amazonaws.com,s3.dualstack.ap-northeast-2.amazonaws.com,s3.dualstack.ap-south-1.amazonaws.com,s3.dualstack.ap-southeast-1.amazonaws.com,s3.dualstack.ap-southeast-2.amazonaws.com,s3.dualstack.ca-central-1.amazonaws.com,s3.dualstack.eu-central-1.amazonaws.com,s3.dualstack.eu-west-1.amazonaws.com,s3.dualstack.eu-west-2.amazonaws.com,s3.dualstack.eu-west-3.amazonaws.com,s3.dualstack.sa-east-1.amazonaws.com,s3.dualstack.us-east-1.amazonaws.com,s3.dualstack.us-east-2.amazonaws.com,s3.eu-central-1.amazonaws.com,s3.eu-west-2.amazonaws.com,s3.eu-west-3.amazonaws.com,s3.us-east-2.amazonaws.com,s5y.io,sa,sa-east-1.elasticbeanstalk.com,sa.au,sa.com,sa.cr,sa.edu.au,sa.gov.au,sa.gov.pl,sa.it,saarland,sabae.fukui.jp,sado.niigata.jp,safe,safety,safety.aero,saga.jp,saga.saga.jp,sagae.yamagata.jp,sagamihara.kanagawa.jp,saigawa.fukuoka.jp,saijo.ehime.jp,saikai.nagasaki.jp,saiki.oita.jp,saintlouis.museum,saitama.jp,saitama.saitama.jp,saito.miyazaki.jp,saka.hiroshima.jp,sakado.saitama.jp,sakae.chiba.jp,sakae.nagano.jp,sakahogi.gifu.jp,sakai.fukui.jp,sakai.ibaraki.jp,sakai.osaka.jp,sakaiminato.tottori.jp,sakaki.nagano.jp,sakata.yamagata.jp,sakawa.kochi.jp,sakegawa.yamagata.jp,saku.nagano.jp,sakuho.nagano.jp,sakura,sakura.chiba.jp,sakura.tochigi.jp,sakuragawa.ibaraki.jp,sakurai.nara.jp,sakyo.kyoto.jp,salangen.no,salat.no,sale,salem.museum,salerno.it,salon,saltdal.no,salud.bo,salvador.br,salvadordali.museum,salzburg.museum,samegawa.fukushima.jp,samnanger.no,sampa.br,samsclub,samsung,samukawa.kanagawa.jp,sanagochi.tokushima.jp,sanda.hyogo.jp,sandcats.io,sande.more-og-romsdal.no,sande.møre-og-romsdal.no,sande.vestfold.no,sandefjord.no,sandiego.museum,sandnes.no,sandnessjoen.no,sandnessjøen.no,sandoy.no,sandvik,sandvikcoromant,sandøy.no,sanfrancisco.museum,sango.nara.jp,sanjo.niigata.jp,sannan.hyogo.jp,sannohe.aomori.jp,sano.tochigi.jp,sanofi,sanok.pl,santabarbara.museum,santacruz.museum,santafe.museum,santamaria.br,santoandre.br,sanuki.kagawa.jp,saobernardo.br,saogonca.br,saotome.st,sap,sapporo.jp,sar.it,sardegna.it,sardinia.it,sarl,saroma.hokkaido.jp,sarpsborg.no,sarufutsu.hokkaido.jp,sas,sasaguri.fukuoka.jp,sasayama.hyogo.jp,sasebo.nagasaki.jp,saskatchewan.museum,sassari.it,satosho.okayama.jp,satsumasendai.kagoshima.jp,satte.saitama.jp,satx.museum,sauda.no,sauherad.no,savannahga.museum,save,saves-the-whales.com,savona.it,saxo,sayama.osaka.jp,sayama.saitama.jp,sayo.hyogo.jp,sb,sb.ua,sbi,sbs,sc,sc.cn,sc.gov.br,sc.ke,sc.kr,sc.leg.br,sc.ls,sc.tz,sc.ug,sc.us,sca,scapp.io,scb,sch.ae,sch.id,sch.ir,sch.jo,sch.lk,sch.ly,sch.ng,sch.qa,sch.sa,sch.so,sch.uk,sch.zm,schaeffler,schlesisches.museum,schmidt,schoenbrunn.museum,schokokeks.net,schokoladen.museum,scholarships,school,school.museum,school.na,school.nz,school.za,schule,schwarz,schweiz.museum,sci.eg,science,science-fiction.museum,science.museum,scienceandhistory.museum,scienceandindustry.museum,sciencecenter.museum,sciencecenters.museum,sciencehistory.museum,sciences.museum,sciencesnaturelles.museum,scientist.aero,scjohnson,scor,scot,scotland.museum,scrapper-site.net,scrapping.cc,scrysec.com,sd,sd.cn,sd.us,sdn.gov.pl,se,se.eu.org,se.gov.br,se.leg.br,se.net,seaport.museum,search,seat,sebastopol.ua,sec.ps,secure,security,securitytactics.com,seek,seihi.nagasaki.jp,seika.kyoto.jp,seiro.niigata.jp,seirou.niigata.jp,seiyo.ehime.jp,sejny.pl,seki.gifu.jp,sekigahara.gifu.jp,sekikawa.niigata.jp,sel.no,selbu.no,select,selfip.biz,selfip.com,selfip.info,selfip.net,selfip.org,selje.no,seljord.no,sells-for-less.com,sells-for-u.com,sells-it.net,sellsyourhome.org,semboku.akita.jp,semine.miyagi.jp,sendai.jp,sener,sennan.osaka.jp,sensiosite.cloud,seoul.kr,sera.hiroshima.jp,seranishi.hiroshima.jp,servebbs.com,servebbs.net,servebbs.org,servebeer.com,serveblog.net,servecounterstrike.com,serveexchange.com,serveftp.com,serveftp.net,serveftp.org,servegame.com,servegame.org,servehalflife.com,servehttp.com,servehumour.com,serveirc.com,serveminecraft.net,servemp3.com,servep2p.com,servepics.com,servequake.com,servesarcasm.com,service.gov.uk,services,services.aero,ses,setagaya.tokyo.jp,seto.aichi.jp,setouchi.okayama.jp,settlement.museum,settlers.museum,settsu.osaka.jp,sevastopol.ua,seven,sew,sex,sex.hu,sex.pl,sexy,sf.no,sfr,sg,sh,sh.cn,shacknet.nu,shakotan.hokkaido.jp,shangrila,shari.hokkaido.jp,sharp,shaw,shell,shell.museum,sherbrooke.museum,shia,shibata.miyagi.jp,shibata.niigata.jp,shibecha.hokkaido.jp,shibetsu.hokkaido.jp,shibukawa.gunma.jp,shibuya.tokyo.jp,shichikashuku.miyagi.jp,shichinohe.aomori.jp,shiftedit.io,shiga.jp,shiiba.miyazaki.jp,shijonawate.osaka.jp,shika.ishikawa.jp,shikabe.hokkaido.jp,shikama.miyagi.jp,shikaoi.hokkaido.jp,shikatsu.aichi.jp,shiki.saitama.jp,shikokuchuo.ehime.jp,shiksha,shima.mie.jp,shimabara.nagasaki.jp,shimada.shizuoka.jp,shimamaki.hokkaido.jp,shimamoto.osaka.jp,shimane.jp,shimane.shimane.jp,shimizu.hokkaido.jp,shimizu.shizuoka.jp,shimoda.shizuoka.jp,shimodate.ibaraki.jp,shimofusa.chiba.jp,shimogo.fukushima.jp,shimoichi.nara.jp,shimoji.okinawa.jp,shimokawa.hokkaido.jp,shimokitayama.nara.jp,shimonita.gunma.jp,shimonoseki.yamaguchi.jp,shimosuwa.nagano.jp,shimotsuke.tochigi.jp,shimotsuma.ibaraki.jp,shinagawa.tokyo.jp,shinanomachi.nagano.jp,shingo.aomori.jp,shingu.fukuoka.jp,shingu.hyogo.jp,shingu.wakayama.jp,shinichi.hiroshima.jp,shinjo.nara.jp,shinjo.okayama.jp,shinjo.yamagata.jp,shinjuku.tokyo.jp,shinkamigoto.nagasaki.jp,shinonsen.hyogo.jp,shinshinotsu.hokkaido.jp,shinshiro.aichi.jp,shinto.gunma.jp,shintoku.hokkaido.jp,shintomi.miyazaki.jp,shinyoshitomi.fukuoka.jp,shiogama.miyagi.jp,shiojiri.nagano.jp,shioya.tochigi.jp,shirahama.wakayama.jp,shirakawa.fukushima.jp,shirakawa.gifu.jp,shirako.chiba.jp,shiranuka.hokkaido.jp,shiraoi.hokkaido.jp,shiraoka.saitama.jp,shirataka.yamagata.jp,shiriuchi.hokkaido.jp,shiroi.chiba.jp,shiroishi.miyagi.jp,shiroishi.saga.jp,shirosato.ibaraki.jp,shishikui.tokushima.jp,shiso.hyogo.jp,shisui.chiba.jp,shitara.aichi.jp,shiwa.iwate.jp,shizukuishi.iwate.jp,shizuoka.jp,shizuoka.shizuoka.jp,shobara.hiroshima.jp,shoes,shonai.fukuoka.jp,shonai.yamagata.jp,shoo.okayama.jp,shop,shop.ht,shop.hu,shop.pl,shop.ro,shop.th,shopitsite.com,shopping,shouji,show,show.aero,showa.fukushima.jp,showa.gunma.jp,showa.yamanashi.jp,showtime,shriram,shunan.yamaguchi.jp,si,si.eu.org,si.it,sibenik.museum,sic.it,sicilia.it,sicily.it,siellak.no,siena.it,sigdal.no,siljan.no,silk,silk.museum,simple-url.com,sina,sinaapp.com,singles,siracusa.it,sirdal.no,site,site.builder.nu,siteleaf.net,sites.static.land,sj,sjc.br,sk,sk.ca,sk.eu.org,skanit.no,skanland.no,skaun.no,skedsmo.no,skedsmokorset.no,ski,ski.museum,ski.no,skien.no,skierva.no,skiervá.no,skin,skiptvet.no,skjak.no,skjervoy.no,skjervøy.no,skjåk.no,sklep.pl,sko.gov.pl,skoczow.pl,skodje.no,skole.museum,sky,skydiving.aero,skype,skánit.no,skånland.no,sl,slask.pl,slattum.no,sld.do,sld.pa,slg.br,sling,slupsk.pl,slz.br,sm,sm.ua,smart,smile,smola.no,smøla.no,sn,sn.cn,snaase.no,snasa.no,sncf,snillfjord.no,snoasa.no,snåase.no,snåsa.no,so,so.gov.pl,so.it,sobetsu.hokkaido.jp,soc.lk,soc.srcf.net,soccer,sochi.su,social,society.museum,sodegaura.chiba.jp,soeda.fukuoka.jp,softbank,software,software.aero,sogndal.no,sogne.no,sohu,soja.okayama.jp,soka.saitama.jp,sokndal.no,sola.no,solar,sologne.museum,solund.no,solutions,soma.fukushima.jp,somna.no,sondre-land.no,sondrio.it,song,songdalen.no,soni.nara.jp,sony,soo.kagoshima.jp,sopot.pl,sor-aurdal.no,sor-fron.no,sor-odal.no,sor-varanger.no,sorfold.no,sorocaba.br,sorreisa.no,sortland.no,sorum.no,sos.pl,sosa.chiba.jp,sosnowiec.pl,soundandvision.museum,soundcast.me,southcarolina.museum,southwest.museum,sowa.ibaraki.jp,soy,sp.gov.br,sp.it,sp.leg.br,space,space-to-rent.com,space.museum,spacekit.io,spb.ru,spb.su,spdns.de,spdns.eu,spdns.org,spectrum.myjino.ru,spjelkavik.no,sport,sport.hu,spot,spreadbetting,spy.museum,spydeberg.no,square.museum,square7.ch,square7.de,square7.net,sr,sr.gov.pl,sr.it,srl,srt,srv.br,ss.it,ssl.origin.cdn77-secure.org,st,st.no,stackhero-network.com,stada,stadt.museum,stage.nodeart.io,staging.onred.one,stalbans.museum,stalowa-wola.pl,stange.no,staples,star,starachowice.pl,stargard.pl,starhub,starnberg.museum,starostwo.gov.pl,stat.no,state.museum,statebank,statefarm,stateofdelaware.museum,stathelle.no,static-access.net,static.land,statics.cloud,station.museum,stavanger.no,stavern.no,stc,stcgroup,steam.museum,steiermark.museum,steigen.no,steinkjer.no,stg.dev,stjohn.museum,stjordal.no,stjordalshalsen.no,stjørdal.no,stjørdalshalsen.no,stockholm,stockholm.museum,stokke.no,stolos.io,stor-elvdal.no,storage,storage.yandexcloud.net,stord.no,stordal.no,store,store.bb,store.dk,store.nf,store.ro,store.st,store.ve,storfjord.no,storj.farm,stpetersburg.museum,strand.no,stranda.no,stream,stryn.no,student.aero,studio,study,stuff-4-sale.org,stuff-4-sale.us,stufftoread.com,stuttgart.museum,style,su,sucks,sue.fukuoka.jp,suedtirol.it,suginami.tokyo.jp,sugito.saitama.jp,suifu.ibaraki.jp,suisse.museum,suita.osaka.jp,sukagawa.fukushima.jp,sukumo.kochi.jp,sula.no,suldal.no,suli.hu,sumida.tokyo.jp,sumita.iwate.jp,sumoto.hyogo.jp,sumoto.kumamoto.jp,sumy.ua,sunagawa.hokkaido.jp,sund.no,sunndal.no,supplies,supply,support,surf,surgeonshall.museum,surgery,surnadal.no,surrey.museum,susaki.kochi.jp,susono.shizuoka.jp,suwa.nagano.jp,suwalki.pl,suzaka.nagano.jp,suzu.ishikawa.jp,suzuka.mie.jp,suzuki,sv,sv.it,svalbard.no,sveio.no,svelvik.no,svizzera.museum,svn-repos.de,swatch,sweden.museum,sweetpepper.org,swidnica.pl,swidnik.pl,swiebodzin.pl,swiftcover,swinoujscie.pl,swiss,sx,sx.cn,sy,sydney,sydney.museum,sykkylven.no,symantec,syncloud.it,syno-ds.de,synology-diskstation.de,synology-ds.de,synology.me,systems,sytes.net,sz,szczecin.pl,szczytno.pl,szex.hu,szkola.pl,sálat.no,sálát.no,søgne.no,sømna.no,søndre-land.no,sør-aurdal.no,sør-fron.no,sør-odal.no,sør-varanger.no,sørfold.no,sørreisa.no,sørum.no,südtirol.it,t.bg,t.se,t3l3p0rt.net,ta.it,taa.it,tab,tabayama.yamanashi.jp,tabuse.yamaguchi.jp,tachiarai.fukuoka.jp,tachikawa.tokyo.jp,tadaoka.osaka.jp,tado.mie.jp,tadotsu.kagawa.jp,tagajo.miyagi.jp,tagami.niigata.jp,tagawa.fukuoka.jp,tahara.aichi.jp,taifun-dns.de,taiji.wakayama.jp,taiki.hokkaido.jp,taiki.mie.jp,tainai.niigata.jp,taipei,taira.toyama.jp,taishi.hyogo.jp,taishi.osaka.jp,taishin.fukushima.jp,taito.tokyo.jp,taiwa.miyagi.jp,tajimi.gifu.jp,tajiri.osaka.jp,taka.hyogo.jp,takagi.nagano.jp,takahagi.ibaraki.jp,takahama.aichi.jp,takahama.fukui.jp,takaharu.miyazaki.jp,takahashi.okayama.jp,takahata.yamagata.jp,takaishi.osaka.jp,takamatsu.kagawa.jp,takamori.kumamoto.jp,takamori.nagano.jp,takanabe.miyazaki.jp,takanezawa.tochigi.jp,takaoka.toyama.jp,takarazuka.hyogo.jp,takasago.hyogo.jp,takasaki.gunma.jp,takashima.shiga.jp,takasu.hokkaido.jp,takata.fukuoka.jp,takatori.nara.jp,takatsuki.osaka.jp,takatsuki.shiga.jp,takayama.gifu.jp,takayama.gunma.jp,takayama.nagano.jp,takazaki.miyazaki.jp,takehara.hiroshima.jp,taketa.oita.jp,taketomi.okinawa.jp,taki.mie.jp,takikawa.hokkaido.jp,takino.hyogo.jp,takinoue.hokkaido.jp,takko.aomori.jp,tako.chiba.jp,taku.saga.jp,talk,tama.tokyo.jp,tamakawa.fukushima.jp,tamaki.mie.jp,tamamura.gunma.jp,tamano.okayama.jp,tamatsukuri.ibaraki.jp,tamayu.shimane.jp,tamba.hyogo.jp,tana.no,tanabe.kyoto.jp,tanabe.wakayama.jp,tanagura.fukushima.jp,tananger.no,tank.museum,tanohata.iwate.jp,taobao,tara.saga.jp,tarama.okinawa.jp,taranto.it,target,targi.pl,tarnobrzeg.pl,tarui.gifu.jp,tarumizu.kagoshima.jp,tas.au,tas.edu.au,tas.gov.au,tashkent.su,tatamotors,tatar,tatebayashi.gunma.jp,tateshina.nagano.jp,tateyama.chiba.jp,tateyama.toyama.jp,tatsuno.hyogo.jp,tatsuno.nagano.jp,tattoo,tawaramoto.nara.jp,tax,taxi,taxi.br,tc,tc.br,tci,tcm.museum,tcp4.me,td,tdk,te.it,te.ua,teaches-yoga.com,team,tec.mi.us,tec.ve,tech,technology,technology.museum,tecnologia.bo,tel,tel.tr,tele.amune.org,telebit.app,telebit.io,telebit.xyz,telefonica,telekommunikation.museum,television.museum,temasek,temp-dns.com,tempio-olbia.it,tempioolbia.it,tendo.yamagata.jp,tenei.fukushima.jp,tenkawa.nara.jp,tennis,tenri.nara.jp,teo.br,teramo.it,termez.su,terni.it,ternopil.ua,teshikaga.hokkaido.jp,test-iserv.de,test.ru,test.tj,teva,texas.museum,textile.museum,tf,tg,tgory.pl,th,thd,the.br,theater,theater.museum,theatre,theworkpc.com,thingdustdata.com,thruhere.net,tiaa,tickets,tienda,tiffany,time.museum,time.no,timekeeping.museum,tingvoll.no,tinn.no,tips,tires,tirol,tj,tj.cn,tjeldsund.no,tjmaxx,tjome.no,tjx,tjøme.no,tk,tkmaxx,tksat.bo,tl,tm,tm.cy,tm.fr,tm.hu,tm.km,tm.mc,tm.mg,tm.no,tm.pl,tm.ro,tm.se,tm.za,tmall,tmp.br,tn,tn.it,tn.us,to,to.gov.br,to.it,to.leg.br,to.work,toba.mie.jp,tobe.ehime.jp,tobetsu.hokkaido.jp,tobishima.aichi.jp,tochigi.jp,tochigi.tochigi.jp,tochio.niigata.jp,toda.saitama.jp,today,toei.aichi.jp,toga.toyama.jp,togakushi.nagano.jp,togane.chiba.jp,togitsu.nagasaki.jp,togliatti.su,togo.aichi.jp,togura.nagano.jp,tohma.hokkaido.jp,tohnosho.chiba.jp,toho.fukuoka.jp,tokai.aichi.jp,tokai.ibaraki.jp,tokamachi.niigata.jp,tokashiki.okinawa.jp,toki.gifu.jp,tokigawa.saitama.jp,tokke.no,tokoname.aichi.jp,tokorozawa.saitama.jp,tokushima.jp,tokushima.tokushima.jp,tokuyama.yamaguchi.jp,tokyo,tokyo.jp,tolga.no,tomakomai.hokkaido.jp,tomari.hokkaido.jp,tome.miyagi.jp,tomi.nagano.jp,tomigusuku.okinawa.jp,tomika.gifu.jp,tomioka.gunma.jp,tomisato.chiba.jp,tomiya.miyagi.jp,tomobe.ibaraki.jp,tonaki.okinawa.jp,tonami.toyama.jp,tondabayashi.osaka.jp,tone.ibaraki.jp,tono.iwate.jp,tonosho.kagawa.jp,tonsberg.no,tools,toon.ehime.jp,top,topology.museum,torahime.shiga.jp,toray,toride.ibaraki.jp,torino.it,torino.museum,torsken.no,tos.it,tosa.kochi.jp,tosashimizu.kochi.jp,toscana.it,toshiba,toshima.tokyo.jp,tosu.saga.jp,total,tottori.jp,tottori.tottori.jp,touch.museum,tourism.pl,tourism.tn,tours,towada.aomori.jp,town,town.museum,townnews-staging.com,toya.hokkaido.jp,toyako.hokkaido.jp,toyama.jp,toyama.toyama.jp,toyo.kochi.jp,toyoake.aichi.jp,toyohashi.aichi.jp,toyokawa.aichi.jp,toyonaka.osaka.jp,toyone.aichi.jp,toyono.osaka.jp,toyooka.hyogo.jp,toyosato.shiga.jp,toyota,toyota.aichi.jp,toyota.yamaguchi.jp,toyotomi.hokkaido.jp,toyotsu.fukuoka.jp,toyoura.hokkaido.jp,toys,tozawa.yamagata.jp,tozsde.hu,tp.it,tr,tr.eu.org,tr.it,tr.no,tra.kp,trade,trader.aero,trading,trading.aero,traeumtgerade.de,trafficplex.cloud,trainer.aero,training,trana.no,tranby.no,trani-andria-barletta.it,trani-barletta-andria.it,traniandriabarletta.it,tranibarlettaandria.it,tranoy.no,transport.museum,transporte.bo,transurl.be,transurl.eu,transurl.nl,tranøy.no,trapani.it,travel,travel.pl,travel.tt,travelchannel,travelers,travelersinsurance,trd.br,tree.museum,trentin-sud-tirol.it,trentin-sudtirol.it,trentin-sued-tirol.it,trentin-suedtirol.it,trentin-süd-tirol.it,trentin-südtirol.it,trentino-a-adige.it,trentino-aadige.it,trentino-alto-adige.it,trentino-altoadige.it,trentino-s-tirol.it,trentino-stirol.it,trentino-sud-tirol.it,trentino-sudtirol.it,trentino-sued-tirol.it,trentino-suedtirol.it,trentino-süd-tirol.it,trentino-südtirol.it,trentino.it,trentinoa-adige.it,trentinoaadige.it,trentinoalto-adige.it,trentinoaltoadige.it,trentinos-tirol.it,trentinostirol.it,trentinosud-tirol.it,trentinosudtirol.it,trentinosued-tirol.it,trentinosuedtirol.it,trentinosüd-tirol.it,trentinosüdtirol.it,trentinsud-tirol.it,trentinsudtirol.it,trentinsued-tirol.it,trentinsuedtirol.it,trentinsüd-tirol.it,trentinsüdtirol.it,trento.it,treviso.it,trieste.it,triton.zone,troandin.no,trogstad.no,troitsk.su,trolley.museum,tromsa.no,tromso.no,tromsø.no,trondheim.no,trust,trust.museum,trustee.museum,trv,trycloudflare.com,trysil.no,træna.no,trøgstad.no,ts.it,tselinograd.su,tsk.tr,tsu.mie.jp,tsubame.niigata.jp,tsubata.ishikawa.jp,tsubetsu.hokkaido.jp,tsuchiura.ibaraki.jp,tsuga.tochigi.jp,tsugaru.aomori.jp,tsuiki.fukuoka.jp,tsukigata.hokkaido.jp,tsukiyono.gunma.jp,tsukuba.ibaraki.jp,tsukui.kanagawa.jp,tsukumi.oita.jp,tsumagoi.gunma.jp,tsunan.niigata.jp,tsuno.kochi.jp,tsuno.miyazaki.jp,tsuru.yamanashi.jp,tsuruga.fukui.jp,tsurugashima.saitama.jp,tsurugi.ishikawa.jp,tsuruoka.yamagata.jp,tsuruta.aomori.jp,tsushima.aichi.jp,tsushima.nagasaki.jp,tsuwano.shimane.jp,tsuyama.okayama.jp,tt,tt.im,tube,tui,tula.su,tunes,tunk.org,tur.ar,tur.br,turek.pl,turen.tn,turin.it,turystyka.pl,tuscany.it,tushu,tuva.su,tuxfamily.org,tv,tv.bb,tv.bo,tv.br,tv.im,tv.it,tv.na,tv.sd,tv.tr,tv.tz,tvedestrand.no,tvs,tw,tw.cn,twmail.cc,twmail.net,twmail.org,tx.us,tychy.pl,tydal.no,tynset.no,tysfjord.no,tysnes.no,tysvar.no,tysvær.no,tz,tønsberg.no,u.bg,u.se,u2-local.xnbay.com,u2.xnbay.com,ua,ua.rs,ubank,ube.yamaguchi.jp,uber.space,uberspace.de,ubs,uchihara.ibaraki.jp,uchiko.ehime.jp,uchinada.ishikawa.jp,uchinomi.kagawa.jp,uconnect,ud.it,uda.nara.jp,udi.br,udine.it,udono.mie.jp,ueda.nagano.jp,ueno.gunma.jp,uenohara.yamanashi.jp,ufcfan.org,ug,ug.gov.pl,ugim.gov.pl,uhren.museum,ui.nabu.casa,uji.kyoto.jp,ujiie.tochigi.jp,ujitawara.kyoto.jp,uk,uk.com,uk.eu.org,uk.net,uk0.bigv.io,uki.kumamoto.jp,ukiha.fukuoka.jp,uklugs.org,ullensaker.no,ullensvang.no,ulm.museum,ulsan.kr,ulvik.no,um.gov.pl,umaji.kochi.jp,umb.it,umbria.it,umi.fukuoka.jp,umig.gov.pl,unazuki.toyama.jp,undersea.museum,uni5.net,unicom,union.aero,univ.sn,university,university.museum,unjarga.no,unjárga.no,unnan.shimane.jp,uno,unusualperson.com,unzen.nagasaki.jp,uol,uonuma.niigata.jp,uozu.toyama.jp,upow.gov.pl,uppo.gov.pl,ups,urakawa.hokkaido.jp,urasoe.okinawa.jp,urausu.hokkaido.jp,urawa.saitama.jp,urayasu.chiba.jp,urbino-pesaro.it,urbinopesaro.it,ureshino.mie.jp,uri.arpa,url.tw,urn.arpa,uruma.okinawa.jp,uryu.hokkaido.jp,us,us-1.evennode.com,us-2.evennode.com,us-3.evennode.com,us-4.evennode.com,us-east-1.amazonaws.com,us-east-1.elasticbeanstalk.com,us-east-2.elasticbeanstalk.com,us-gov-west-1.elasticbeanstalk.com,us-west-1.elasticbeanstalk.com,us-west-2.elasticbeanstalk.com,us.com,us.eu.org,us.gov.pl,us.na,us.org,usa.museum,usa.oita.jp,usantiques.museum,usarts.museum,uscountryestate.museum,usculture.museum,usdecorativearts.museum,user.aseinet.ne.jp,user.party.eus,user.srcf.net,usercontent.jp,usgarden.museum,ushiku.ibaraki.jp,ushistory.museum,ushuaia.museum,uslivinghistory.museum,usr.cloud.muni.cz,ustka.pl,usui.fukuoka.jp,usuki.oita.jp,ut.us,utah.museum,utashinai.hokkaido.jp,utazas.hu,utazu.kagawa.jp,uto.kumamoto.jp,utsira.no,utsunomiya.tochigi.jp,utwente.io,uvic.museum,uw.gov.pl,uwajima.ehime.jp,uwu.ai,uy,uy.com,uz,uz.ua,uzhgorod.ua,uzs.gov.pl,v-info.info,v.bg,va,va.it,va.no,va.us,vaapste.no,vacations,vadso.no,vadsø.no,vaga.no,vagan.no,vagsoy.no,vaksdal.no,val-d-aosta.it,val-daosta.it,vald-aosta.it,valdaosta.it,valer.hedmark.no,valer.ostfold.no,valle-aosta.it,valle-d-aosta.it,valle-daosta.it,valle.no,valleaosta.it,valled-aosta.it,valledaosta.it,vallee-aoste.it,vallee-d-aoste.it,valleeaoste.it,valleedaoste.it,valley.museum,vallée-aoste.it,vallée-d-aoste.it,valléeaoste.it,valléedaoste.it,vana,vang.no,vanguard,vantaa.museum,vanylven.no,vao.it,vapor.cloud,vaporcloud.io,vardo.no,vardø.no,varese.it,varggat.no,varoy.no,vb.it,vc,vc.it,vda.it,ve,ve.it,vefsn.no,vega.no,vegarshei.no,vegas,vegårshei.no,ven.it,veneto.it,venezia.it,venice.it,vennesla.no,ventures,verbania.it,vercelli.it,verdal.no,verisign,vermögensberater,vermögensberatung,verona.it,verran.no,versailles.museum,versicherung,vestby.no,vestnes.no,vestre-slidre.no,vestre-toten.no,vestvagoy.no,vestvågøy.no,vet,vet.br,veterinaire.fr,veterinaire.km,vevelstad.no,vf.no,vg,vgs.no,vi,vi.it,vi.us,viajes,vibo-valentia.it,vibovalentia.it,vic.au,vic.edu.au,vic.gov.au,vicenza.it,video,video.hu,vig,vik.no,viking,viking.museum,vikna.no,village.museum,villas,vin,vindafjord.no,vinnica.ua,vinnytsia.ua,vip,vipsinaapp.com,virgin,virginia.museum,virtual-user.de,virtual.museum,virtualserver.io,virtualuser.de,virtueeldomein.nl,virtuel.museum,visa,vision,vistaprint,viterbo.it,viva,vivo,vix.br,vlaanderen,vlaanderen.museum,vladikavkaz.ru,vladikavkaz.su,vladimir.ru,vladimir.su,vlog.br,vm.bytemark.co.uk,vn,vn.ua,voagat.no,vodka,volda.no,volkenkunde.museum,volkswagen,vologda.su,volvo,volyn.ua,voorloper.cloud,voss.no,vossevangen.no,vote,voting,voto,voyage,vpndns.net,vpnplus.to,vps.myjino.ru,vr.it,vs.it,vt.it,vt.us,vu,vuelos,vv.it,várggát.no,vågan.no,vågsøy.no,vågå.no,våler.hedmark.no,våler.østfold.no,værøy.no,w.bg,w.se,wa.au,wa.edu.au,wa.gov.au,wa.us,wada.nagano.jp,wafflecell.com,wajiki.tokushima.jp,wajima.ishikawa.jp,wakasa.fukui.jp,wakasa.tottori.jp,wakayama.jp,wakayama.wakayama.jp,wake.okayama.jp,wakkanai.hokkaido.jp,wakuya.miyagi.jp,walbrzych.pl,wales,wales.museum,wallonie.museum,walmart,walter,wang,wanggou,wanouchi.gifu.jp,war.museum,warabi.saitama.jp,warman,warmia.pl,warszawa.pl,washingtondc.museum,washtenaw.mi.us,wassamu.hokkaido.jp,watarai.mie.jp,watari.miyagi.jp,watch,watch-and-clock.museum,watchandclock.museum,watches,waw.pl,wazuka.kyoto.jp,we.bs,weather,weatherchannel,web.app,web.bo,web.co,web.do,web.gu,web.id,web.lk,web.nf,web.ni,web.pk,web.tj,web.tr,web.ve,web.za,webcam,weber,webhare.dev,webhop.biz,webhop.info,webhop.me,webhop.net,webhop.org,webhosting.be,webredirect.org,website,website.yandexcloud.net,webspace.rocks,wed,wedding,wedeploy.io,wedeploy.me,wedeploy.sh,wegrow.pl,weibo,weir,wellbeingzone.co.uk,wellbeingzone.eu,western.museum,westfalen.museum,wf,whaling.museum,whoswho,wi.us,wielun.pl,wien,wif.gov.pl,wiih.gov.pl,wiki,wiki.bo,wiki.br,wildlife.museum,williamhill,williamsburg.museum,win,winb.gov.pl,windmill.museum,windows,wine,winners,wios.gov.pl,witd.gov.pl,withgoogle.com,withyoutube.com,wiw.gov.pl,wlocl.pl,wloclawek.pl,wme,wmflabs.org,wnext.app,wodzislaw.pl,wolomin.pl,wolterskluwer,woodside,work,workers.dev,workinggroup.aero,workisboring.com,works,works.aero,workshop.museum,world,worse-than.tv,wow,wpcomstaging.com,wpdevcloud.com,writesthisblog.com,wroc.pl,wroclaw.pl,ws,ws.na,wsa.gov.pl,wskr.gov.pl,wtc,wtf,wuoz.gov.pl,wv.us,www.ro,wy.us,wzmiuw.gov.pl,x.bg,x.se,x443.pw,xbox,xen.prgmr.com,xenapponazure.com,xerox,xfinity,xihuan,xin,xj.cn,xnbay.com,xs4all.space,xxx,xyz,xz.cn,y.bg,y.se,yabu.hyogo.jp,yabuki.fukushima.jp,yachimata.chiba.jp,yachiyo.chiba.jp,yachiyo.ibaraki.jp,yachts,yaese.okinawa.jp,yahaba.iwate.jp,yahiko.niigata.jp,yahoo,yaita.tochigi.jp,yaizu.shizuoka.jp,yakage.okayama.jp,yakumo.hokkaido.jp,yakumo.shimane.jp,yalta.ua,yamada.fukuoka.jp,yamada.iwate.jp,yamada.toyama.jp,yamaga.kumamoto.jp,yamagata.gifu.jp,yamagata.ibaraki.jp,yamagata.jp,yamagata.nagano.jp,yamagata.yamagata.jp,yamaguchi.jp,yamakita.kanagawa.jp,yamamoto.miyagi.jp,yamanakako.yamanashi.jp,yamanashi.jp,yamanashi.yamanashi.jp,yamanobe.yamagata.jp,yamanouchi.nagano.jp,yamashina.kyoto.jp,yamato.fukushima.jp,yamato.kanagawa.jp,yamato.kumamoto.jp,yamatokoriyama.nara.jp,yamatotakada.nara.jp,yamatsuri.fukushima.jp,yamaxun,yamazoe.nara.jp,yame.fukuoka.jp,yanagawa.fukuoka.jp,yanaizu.fukushima.jp,yandex,yandexcloud.net,yao.osaka.jp,yaotsu.gifu.jp,yasaka.nagano.jp,yashio.saitama.jp,yashiro.hyogo.jp,yasu.shiga.jp,yasuda.kochi.jp,yasugi.shimane.jp,yasuoka.nagano.jp,yatomi.aichi.jp,yatsuka.shimane.jp,yatsushiro.kumamoto.jp,yawara.ibaraki.jp,yawata.kyoto.jp,yawatahama.ehime.jp,yazu.tottori.jp,ybo.faith,ybo.party,ybo.review,ybo.science,ybo.trade,ye,yk.ca,yn.cn,yodobashi,yoga,yoichi.hokkaido.jp,yoita.niigata.jp,yoka.hyogo.jp,yokaichiba.chiba.jp,yokawa.hyogo.jp,yokkaichi.mie.jp,yokohama,yokohama.jp,yokoshibahikari.chiba.jp,yokosuka.kanagawa.jp,yokote.akita.jp,yokoze.saitama.jp,yolasite.com,yombo.me,yomitan.okinawa.jp,yonabaru.okinawa.jp,yonago.tottori.jp,yonaguni.okinawa.jp,yonezawa.yamagata.jp,yono.saitama.jp,yorii.saitama.jp,york.museum,yorkshire.museum,yoro.gifu.jp,yosemite.museum,yoshida.saitama.jp,yoshida.shizuoka.jp,yoshikawa.saitama.jp,yoshimi.saitama.jp,yoshino.nara.jp,yoshinogari.saga.jp,yoshioka.gunma.jp,yotsukaido.chiba.jp,you,youth.museum,youtube,yt,yuasa.wakayama.jp,yufu.oita.jp,yugawa.fukushima.jp,yugawara.kanagawa.jp,yuki.ibaraki.jp,yukuhashi.fukuoka.jp,yun,yura.wakayama.jp,yurihonjo.akita.jp,yusuhara.kochi.jp,yusui.kagoshima.jp,yuu.yamaguchi.jp,yuza.yamagata.jp,yuzawa.niigata.jp,z.bg,z.se,za.bz,za.com,za.net,za.org,zachpomor.pl,zagan.pl,zakopane.pl,zama.kanagawa.jp,zamami.okinawa.jp,zao.miyagi.jp,zaporizhzhe.ua,zaporizhzhia.ua,zappos,zapto.org,zapto.xyz,zara,zarow.pl,zentsuji.kagawa.jp,zero,zgora.pl,zgorzelec.pl,zhitomir.ua,zhytomyr.ua,zip,zj.cn,zlg.br,zm,zone,zone.id,zoological.museum,zoology.museum,zp.gov.pl,zp.ua,zt.ua,zuerich,zushi.kanagawa.jp,zw,ákŋoluokta.no,álaheadju.no,áltá.no,åfjord.no,åkrehamn.no,ål.no,ålesund.no,ålgård.no,åmli.no,åmot.no,årdal.no,ås.no,åseral.no,åsnes.no,øksnes.no,ørland.no,ørskog.no,ørsta.no,østre-toten.no,øvre-eiker.no,øyer.no,øygarden.no,øystre-slidre.no,čáhcesuolo.no,ελ,ак.срб,бг,бел,дети,ею,иком.museum,католик,ком,мкд,мон,москва,обр.срб,од.срб,онлайн,орг,орг.срб,пр.срб,рус,рф,сайт,срб,укр,упр.срб,қаз,հայ,ירושלים.museum,קום,ابوظبي,اتصالات,ارامكو,الاردن,الجزائر,السعودية,السعوديه,السعودیة,السعودیۃ,العليان,المغرب,اليمن,امارات,ايران,ايران.ir,ایران,ایران.ir,بارت,بازار,بيتك,بھارت,تونس,سودان,سوريا,سورية,شبكة,عراق,عرب,عمان,فلسطين,قطر,كاثوليك,كوم,مصر,مليسيا,موبايلي,موقع,همراه,پاكستان,پاکستان,ڀارت,कॉम,नेट,भारत,भारतम्,भारोत,संगठन,বাংলা,ভারত,ভাৰত,ਭਾਰਤ,ભારત,ଭାରତ,இந்தியா,இலங்கை,சிங்கப்பூர்,భారత్,ಭಾರತ,ഭാരതം,ලංකා,คอม,ทหาร.ไทย,ธุรกิจ.ไทย,รัฐบาล.ไทย,ศึกษา.ไทย,องค์กร.ไทย,เน็ต.ไทย,ไทย,გე,みんな,クラウド,グーグル,コム,ストア,セール,ファッション,ポイント,三重.jp,世界,个人.hk,中信,中国,中國,中文网,京都.jp,企业,佐賀.jp,佛山,信息,個人.hk,個人.香港,健康,八卦,公司,公司.cn,公司.hk,公司.香港,公益,兵庫.jp,北海道.jp,千葉.jp,台湾,台灣,和歌山.jp,商城,商店,商标,商業.tw,嘉里,嘉里大酒店,在线,埼玉.jp,大众汽车,大分.jp,大拿,大阪.jp,天主教,奈良.jp,娱乐,宮城.jp,宮崎.jp,家電,富山.jp,山口.jp,山形.jp,山梨.jp,岐阜.jp,岡山.jp,岩手.jp,島根.jp,工行,广东,広島.jp,微博,徳島.jp,愛媛.jp,愛知.jp,慈善,我爱你,手机,手表,招聘,政务,政府,政府.hk,政府.香港,敎育.hk,教育.hk,教育.香港,新加坡,新潟.jp,新闻,时尚,書籍,机构,東京.jp,栃木.jp,沖縄.jp,淡马锡,游戏,滋賀.jp,澳門,澳门,点看,熊本.jp,珠宝,石川.jp,神奈川.jp,福井.jp,福岡.jp,福島.jp,秋田.jp,移动,箇人.hk,組織.hk,組織.tw,組織.香港,組织.hk,網絡.cn,網絡.hk,網絡.香港,網络.hk,網路.tw,组織.hk,组织.hk,组织机构,网址,网店,网站,网絡.hk,网络,网络.cn,网络.hk,群馬.jp,联通,臺灣,茨城.jp,诺基亚,谷歌,购物,通販,長崎.jp,長野.jp,集团,電訊盈科,青森.jp,静岡.jp,飞利浦,食品,餐厅,香川.jp,香格里拉,香港,高知.jp,鳥取.jp,鹿児島.jp,닷넷,닷컴,삼성,한국'\n"
  },
  {
    "path": "src/proxy/src/tld.js",
    "content": "// https://publicsuffix.org/list/effective_tld_names.dat\nimport tldData from './tld-data.js'\nimport {isIPv4} from './util.js'\n\n\n/** @type {Map<string, string>} */\nconst mTldCache = new Map()\nconst mTldSet = new Set(tldData.split(','))\n\n/**\n * @param {string} domain \n */\nfunction getDomainTld(domain) {\n  if (isTld(domain)) {\n    return domain\n  }\n  let pos = 0\n  for (;;) {\n    // a.b.c -> b.c\n    pos = domain.indexOf('.', pos + 1)\n    if (pos === -1) {\n      return ''\n    }\n    const str = domain.substr(pos + 1)\n    if (isTld(str)) {\n      return str\n    }\n  }\n}\n\n/**\n * @param {string} domain \n */\nexport function getTld(domain) {\n  let ret = mTldCache.get(domain)\n  if (ret !== undefined) {\n    return ret\n  }\n\n  if (isIPv4(domain)) {\n    ret = domain\n  } else {\n    ret = getDomainTld(domain)\n  }\n\n  mTldCache.set(domain, ret)\n  return ret\n}\n\n\n/**\n * @param {string} domain \n */\nexport function isTld(domain) {\n  return mTldSet.has(domain)\n}"
  },
  {
    "path": "src/proxy/src/urlx.js",
    "content": "import * as util from './util.js'\nimport * as env from './env.js'\nimport * as path from './path.js'\nimport * as tld from './tld.js'\n\n\nconst PREFIX = path.PREFIX\nconst PREFIX_LEN = PREFIX.length\nconst ROOT_LEN = path.ROOT.length\n\n/**\n * @param {string} url \n */\nexport function isHttpProto(url) {\n  return /^https?:/.test(url)\n}\n\n\n/**\n * @param {string} url \n */\nfunction isInternalUrl(url) {\n  return !isHttpProto(url) || url.startsWith(PREFIX)\n}\n\n\n/**\n * @param {string} url \n * @param {string | URL=} baseUrl \n */\nexport function newUrl(url, baseUrl) {\n  try {\n    // [safari] baseUrl 不能为空\n    return baseUrl\n      ? new URL(url, baseUrl)\n      : new URL(url)\n  } catch (err) {\n  }\n}\n\n\n/**\n * @param {URL | Location} urlObj \n */\nexport function encUrlObj(urlObj) {\n  const fullUrl = urlObj.href\n  if (isInternalUrl(fullUrl)) {\n    return fullUrl\n  }\n  return PREFIX + fullUrl\n}\n\nconst IS_SW = env.isSwEnv()\nconst IS_WORKER = env.isWorkerEnv()\nconst WORKER_URL = IS_WORKER && decUrlStrAbs(location.href)\n\n/**\n * @param {string} url \n * @param {*} relObj \n */\nexport function encUrlStrRel(url, relObj) {\n  let baseUrl\n\n  if (IS_SW) {\n    baseUrl = relObj\n  } else if (IS_WORKER) {\n    baseUrl = WORKER_URL\n  } else {\n    const {doc} = env.get(relObj)\n    baseUrl = doc.baseURI\n  }\n\n  const urlObj = newUrl(url, baseUrl)\n  if (!urlObj) {\n    return url\n  }\n  return encUrlObj(urlObj)\n}\n\n\n/**\n * @param {string} url \n */\nexport function encUrlStrAbs(url) {\n  const urlObj = newUrl(url)\n  if (!urlObj) {\n    return url\n  }\n  return encUrlObj(urlObj)\n}\n\n\n/**\n * @param {URL | Location} urlObj \n */\nexport function decUrlObj(urlObj) {\n  const fullUrl = urlObj.href\n  if (!fullUrl.startsWith(PREFIX)) {\n    return fullUrl\n  }\n  return fullUrl.substr(PREFIX_LEN)\n}\n\n\n/**\n * @param {string} url \n * @param {*} relObj \n */\nexport function decUrlStrRel(url, relObj) {\n  let baseUrl\n\n  if (IS_WORKER) {\n    baseUrl = WORKER_URL\n  } else {\n    const {doc} = env.get(relObj)\n    baseUrl = doc.baseURI\n  }\n\n  const urlObj = newUrl(url, baseUrl)\n  if (!urlObj) {\n    return url\n  }\n  return decUrlObj(urlObj)\n}\n\n\n/**\n * @param {string} url \n */\nexport function decUrlStrAbs(url) {\n  const urlObj = newUrl(url)\n  if (!urlObj) {\n    return url\n  }\n  return decUrlObj(urlObj)\n}\n\n\n\n/**\n * @param {string} url \n */\nexport function delHash(url) {\n  const p = url.indexOf('#')\n  return (p === -1) ? url : url.substr(0, p)\n}\n\n\n/**\n * @param {string} url \n */\nexport function delScheme(url) {\n  const p = url.indexOf('://')\n  return (p === -1) ? url : url.substr(p + 3)\n}\n\n\n/**\n * @param {string} val \n */\nexport function replaceHttpRefresh(val, relObj) {\n  return val.replace(/(;\\s*url=)(.+)/i, (_, $1, url) => {\n    return $1 + encUrlStrRel(url, relObj)\n  })\n}\n\n\n/**\n * URL 导航调整\n * \n * 标准\n *  https://example.com/-----https://www.google.com/\n * \n * 无路径\n *  https://example.com/-----https://www.google.com\n * \n * 无协议\n *  https://example.com/-----www.google.com\n * \n * 任意数量的分隔符\n *  https://example.com/---https://www.google.com\n *  https://example.com/---------https://www.google.com\n *  https://example.com/https://www.google.com\n * \n * 重复\n *  https://example.com/-----https://example.com/-----https://www.google.com\n * \n * 别名\n *  https://example.com/google\n * \n * \n * 搜索\n *  https://example.com/-----xxx\n *  ->\n *  https://www.google.com/search?q=xxx\n */\nconst DEFAULT_ALIAS = {\n  'www.google.com': ['google', 'gg', 'g'],\n  'www.youtube.com': ['youtube', 'yt', 'y'],\n  'www.wikipedia.org': ['wikipedia', 'wiki', 'wk', 'w'],\n  'www.facebook.com': ['facebook', 'fb', 'f'],\n  'twitter.com': ['twitter', 'tw', 't'],\n}\n\nconst DEFAULT_SEARCH = 'https://www.google.com/search?q=%s'\n\n/** @type {Map<string, string>} */\nlet aliasDomainMap\n\n/**\n * @param {string} alias \n */\nfunction getAliasUrl(alias) {\n  if (!aliasDomainMap) {\n    aliasDomainMap = new Map()\n    for (const [domain, aliasArr] of Object.entries(DEFAULT_ALIAS)) {\n      for (const v of aliasArr) {\n        aliasDomainMap.set(v, domain)\n      }\n    }\n  }\n  \n  const domain = aliasDomainMap.get(alias)\n  if (domain) {\n    return 'https://' + domain + '/'\n  }\n}\n\n\n/**\n * @param {string} part \n */\nfunction padUrl(part) {\n  // TODO: HSTS\n  const urlStr = isHttpProto(part) ? part : `http://${part}`\n  const urlObj = newUrl(urlStr)\n  if (!urlObj) {\n    return\n  }\n  const {hostname} = urlObj\n\n  // http://localhost\n  if (!hostname.includes('.')) {\n    return\n  }\n\n  // http://a.b\n  if (!tld.getTld(hostname)) {\n    return\n  }\n\n  // 数字会被当做 IP 地址:\n  // new URL('http://1024').href == 'http://0.0.4.0'\n  // 这种情况应该搜索，而不是访问\n  // 只有出现完整的 IP 才访问\n  if (util.isIPv4(hostname) && !urlStr.includes(hostname)) {\n    return\n  }\n\n  return urlObj.href\n}\n\n\n/**\n * @param {string} urlStr\n */\nexport function adjustNav(urlStr) {\n  // 分隔符 `-----` 之后的部分\n  const rawUrlStr = urlStr.substr(PREFIX_LEN)\n  const rawUrlObj = newUrl(rawUrlStr)\n\n  if (rawUrlObj) {\n    // 循环引用\n    const m = rawUrlStr.match(/\\/-----(https?:\\/\\/.+)$/)\n    if (m) {\n      return PREFIX + m[1]\n    }\n    // 标准格式（大概率）\n    if (isHttpProto(rawUrlObj.protocol) &&\n        PREFIX + rawUrlObj.href === urlStr\n    ) {\n      return\n    }\n  }\n\n  // 任意数量 `-` 之后的部分\n  const part = urlStr.substr(ROOT_LEN).replace(/^-*/, '')\n\n  const ret = getAliasUrl(part) || padUrl(part)\n  if (ret) {\n    return PREFIX + ret\n  }\n\n  const keyword = part.replace(/&/g, '%26')\n  return PREFIX + DEFAULT_SEARCH.replace('%s', keyword)\n}\n"
  },
  {
    "path": "src/proxy/src/util.js",
    "content": "const ENC = new TextEncoder()\n\n/**\n * @param {string} str \n */\nexport function strToBytes(str) {\n  return ENC.encode(str)\n}\n\n/**\n * @param {BufferSource} bytes \n * @param {string} charset \n */\nexport function bytesToStr(bytes, charset = 'utf-8') {\n  return new TextDecoder(charset).decode(bytes)\n}\n\n/**\n * @param {string} label \n */\nexport function isUtf8(label) {\n  return /^utf-?8$/i.test(label)\n}\n\n\nconst R_IP = /^(?:\\d+\\.){0,3}\\d+$/\n\n/**\n * @param {string} str \n */\nexport function isIPv4(str) {\n  return R_IP.test(str)\n}\n\n\nconst JS_MIME_SET = new Set([\n  'text/javascript',\n  'application/javascript',\n  'application/ecmascript',\n  'application/x-ecmascript',\n  'module',\n])\n\n/**\n * @param {string} mime \n */\nexport function isJsMime(mime) {\n  return JS_MIME_SET.has(mime)\n}\n\n\n/**\n * 将多个 Uint8Array 拼接成一个\n * @param {Uint8Array[]} bufs \n */\nexport function concatBufs(bufs) {\n  let size = 0\n  bufs.forEach(v => {\n    size += v.length\n  })\n\n  let ret = new Uint8Array(size)\n  let pos = 0\n  bufs.forEach(v => {\n    ret.set(v, pos)\n    pos += v.length\n  })\n  return ret\n}\n\n\n/**\n * @param {string} str \n */\nexport function strHash(str) {\n  let sum = 0\n  for (let i = 0, n = str.length; i < n; i++) {\n    sum = (sum * 31 + str.charCodeAt(i)) >>> 0\n  }\n  return sum\n}\n\n\n/**\n * @param {number} num \n * @param {number} len \n */\nexport function numToHex(num, len) {\n  return ('00000000' + num.toString(16)).slice(-len)\n}\n\n\n/**\n * @param {number} ms \n */\nexport async function sleep(ms) {\n  return new Promise(y => setTimeout(y, ms))\n}\n\n\nexport function getTimeSeconds() {\n  return (Date.now() / 1000) | 0\n}"
  },
  {
    "path": "www/404.html",
    "content": "<html><head><meta charset=utf-8></head><body id=t><svg xmlns=http://www.w3.org/2000/svg width=100% height=100% viewBox=\"0 0 100 100\"preserveAspectRatio=xMidYMid fill=none><circle cx=50 cy=50 r=25.944 stroke=#93dbe9><animate attributeName=r calcMode=spline values=0;40 keyTimes=0;1 dur=1 keySplines=\"0 0.2 0.8 1\"begin=-0.5s repeatCount=indefinite stroke-width=2 /><animate attributeName=opacity calcMode=spline values=1;0 keyTimes=0;1 dur=1 keySplines=\"0.2 0 0.8 1\"begin=-0.5s repeatCount=indefinite stroke-width=2 /></circle><circle cx=50 cy=50 r=40 stroke=#689cc5><animate attributeName=r calcMode=spline values=0;40 keyTimes=0;1 dur=1 keySplines=\"0 0.2 0.8 1\"begin=0s repeatCount=indefinite stroke-width=2 /><animate attributeName=opacity calcMode=spline values=1;0 keyTimes=0;1 dur=1 keySplines=\"0.2 0 0.8 1\"begin=0s repeatCount=indefinite stroke-width=2 /></circle></svg><script>function a(){var e=Date.now();try{var t=+sessionStorage._ts||0;if((sessionStorage._ts=e)-t<100)return setTimeout(a,5e3)}catch(r){}location.reload()}function i(e){n(e.message)}function n(e){t.innerHTML=e}!function s(){if(self.isSecureContext)if(self.ReadableStream){var e=navigator.serviceWorker;if(e)e.register(function r(){return location.pathname.replace(/\\/-+https?:.+/,\"\").replace(/\\w+\\.\\w+$/,\"\").replace(/\\/*$/,\"/\")}()+\"sw.js\").then(a)[\"catch\"](i);else{var t=navigator.userAgent;/Firefox/.test(t)?n(\"本网站不支持 FireFox 隐身模式\"):/iPhone|iPad/.test(t)&&n(\"iOS 上请使用 Safari 浏览器\")}}else n(\"请使用最新的 HTML5 浏览器\");else n(\"本程序需要 HTTPS 站点\")}()</script></body></html>"
  },
  {
    "path": "www/assets/README.md",
    "content": "该目录的文件可通过 CDN 加速"
  },
  {
    "path": "www/assets/cors_v1.txt",
    "content": "# HTTP 返回头存在 access-control-allow-origin: * 的站点，不走代理直接连接\n# 收集了部分，实验中...\n\n# google\nssl.google-analytics.com\n\n# [public]\ncdn.jsdelivr.net\nunpkg.com\ncdnjs.cloudflare.com\ncdn.bootcss.com\nuse.fontawesome.com\nfast.fonts.net\nscript.hotjar.com\n\n# github\ngithub.githubassets.com\navatars0.githubusercontent.com\navatars1.githubusercontent.com\navatars2.githubusercontent.com\navatars3.githubusercontent.com\n\ndesktop.github.com\n\n# flickr\nstatus.flickr.net\n\n# ali\nat.alicdn.com\nimg.alicdn.com\ng.alicdn.com\ni.alicdn.com\natanx.alicdn.com\nwwc.alicdn.com\ngw.alicdn.com\nassets.alicdn.com\naeis.alicdn.com\natanx.alicdn.com\nhudong.alicdn.com\ngma.alicdn.com\n\nsc01.alicdn.com\nsc02.alicdn.com\nsc03.alicdn.com\nsc04.alicdn.com\n\ncbu01.alicdn.com\ncbu02.alicdn.com\ncbu03.alicdn.com\ncbu04.alicdn.com\n\n# baidu\n# img*.bdimg.com\nimg0.bdimg.com\nimg1.bdimg.com\nimg2.bdimg.com\nimg3.bdimg.com\nimg4.bdimg.com\nimg5.bdimg.com\n\nwebmap0.bdimg.com\nwebmap1.bdimg.com\niknowpc.bdimg.com\nbkssl.bdimg.com\nbaikebcs.bdimg.com\ngh.bdstatic.com\n\n# qq\n3gimg.qq.com\ncombo.b.qq.com\n\n# bilibili\nupos-hz-mirrorakam.akamaized.net\n\n# toutiao\nimages.taboola.com\nimages.taboola.com.cn\nimages-dup.taboola.com\n\n# zhihu\nstatic.zhihu.com\npic1.zhimg.com\npic2.zhimg.com\npic3.zhimg.com\npic4.zhimg.com\npic5.zhimg.com\npic7.zhimg.com\n\n# jd\nimg11.360buyimg.com\n\n# jianshu\nupload.jianshu.io\nupload-images.jianshu.io\ncdn2.jianshu.io\n\n# 163\nurswebzj.nosdn.127.net\nstatic.ws.126.net\nimg1.cache.netease.com\nimg2.cache.netease.com\nimg3.cache.netease.com\nimg4.cache.netease.com\nimg5.cache.netease.com\nimg6.cache.netease.com\n\n# sina\njs.t.sinajs.cn\nmjs.sinaimg.cn\nh5.sinaimg.cn\n\n# sohu\n0d077ef9e74d8.cdn.sohucs.com\n39d0825d09f05.cdn.sohucs.com\n5b0988e595225.cdn.sohucs.com\ncaaceed4aeaf2.cdn.sohucs.com\n\nimg01.sogoucdn.com\nimg02.sogoucdn.com\nimg03.sogoucdn.com\nimg04.sogoucdn.com\nimg05.sogoucdn.com\n\n# hupu\nw1.hoopchina.com.cn\nw2.hoopchina.com.cn\nw3.hoopchina.com.cn\nw4.hoopchina.com.cn\nshihuo.hupucdn.com\n\n# uc\nimage.uc.cn\n\n# ...\nstatic.cnodejs.org\nstatic2.cnodejs.org\n2b.zol-img.com.cn\nimg.pconline.com.cn\nangular.cn\nimg1.dxycdn.com\ncdn.kastatic.org\nstatic.geetest.com\ncdn.registerdisney.go.com\nsecure-us.imrworldwide.com\nimg1.doubanio.com\nqnwww2.autoimg.cn\nqnwww3.autoimg.cn\ns.autoimg.cn\n\nhb.imgix.net\nmain.qcloudimg.com\nvz-cdn2.contentabc.com\ntwemoji.maxcdn.com\nfgn.cdn.serverable.com\n\ns1.hdslb.com\ns2.hdslb.com\ns3.hdslb.com\n\n# cnblogs\ncommon.cnblogs.com\nmathjax.cnblogs.com\n\n# csdn\ncsdnimg.cn\ng.csdnimg.cn\nimg-ads.csdn.net\nimg-bss.csdn.net\nimg-blog.csdn.net\n\n# ...\nstatic.geekbang.org\nstatic001.infoq.cn\nstatic.docs.com\ncdn1.developermedia.com\ncdn2.developermedia.com\ncdn.optimizely.com\ncdn.ampproject.org\n\ncamshowverse.to\nstatic.camshowhub-cdn.to\n\nxqimg.imedao.com\nxavatar.imedao.com\n\n# ???\nimg-l3.xvideos-cdn.com\nstatic-egc.xvideos-cdn.com\nimg-hw.xvideos-cdn.com\nimg-hw.xnxx-cdn.com\nstatic-egc.xnxx-cdn.com\ndi.phncdn.com\ncv.phncdn.com\nroomimg.stream.highwebmedia.com\nw3.cdn.anvato.net"
  },
  {
    "path": "www/assets/index_v3.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <title>Page Sandbox</title>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0\">\n  <base target=\"_blank\">\n  <style>\n    body {\n      padding: 0 0.5em;\n    }\n    .box {\n      margin-top: 1em;\n    }\n    #txtURL {\n      width: 100%;\n      height: 2em;\n      text-indent: 0.5em;\n      padding: 0.25em 0;\n    }\n    #btnGo {\n      width: 100%;\n      font-size: 1.5em;\n    }\n    #list a {\n      margin: 1em;\n    }\n  </style>\n</head>\n<body>\n  <div class=\"box\">\n    <input id=\"txtURL\" type=\"text\" value=\"www.google.com\" autofocus>\n  </div>\n  <div class=\"box\">\n    <button id=\"btnGo\">Go</button>\n  </div>\n  <div class=\"box\">\n    <span>切换线路:</span>\n    <select id=\"selNode\"></select>\n  </div>\n  <div class=\"box\" id=\"list\">\n  </div>\n  <script>\n    const PAGE_CONF_SET = 110\n    const PAGE_CONF_GET = 111\n\n    const SW_CONF_RETURN = 112\n    const SW_CONF_CHANGE = 113\n\n    const PAGE_READY_CHECK = 200\n    const SW_READY = 201\n\n    const sw = navigator.serviceWorker\n\n\n    sw.addEventListener('message', onSwMsg)\n    sendMsgToSw(PAGE_READY_CHECK)\n\n    btnGo.onclick = function() {\n      const text = txtURL.value.trim()\n      if (text) {\n        const url = './-----' + text\n        open(url, '_blank', 'noopener,noreferrer')\n      }\n    }\n    txtURL.onkeypress = function(e) {\n      if (e.keyCode === 13) {\n        btnGo.onclick()\n      }\n    }\n    txtURL.setSelectionRange(0, txtURL.value.length)\n\n\n    function onSwMsg(e) {\n      const [cmd, msg] = e.data\n\n      switch (cmd) {\n      case SW_CONF_RETURN:\n        conf = msg\n        showConf()\n        break\n\n      case SW_CONF_CHANGE:\n        conf = msg\n        updateSelected()\n        break\n\n      case SW_READY:\n        console.log('sw ready')\n        showIcons()\n        sendMsgToSw(PAGE_CONF_GET)\n        break\n      }\n    }\n\n    function onSwFail(err) {\n      txtURL.value = err\n    }\n\n    selNode.onchange = function() {\n      const item = this.options[this.selectedIndex]\n      const node = item.value\n      conf.node_default = node\n      sendMsgToSw(PAGE_CONF_SET, conf)\n    }\n\n    function sendMsgToSw(cmd, val) {\n      const ctl = sw.controller\n      if (!ctl) {\n        console.log('ctl is null')\n        return\n      }\n      ctl.postMessage([cmd, val])\n    }\n\n    const SITE_LIST = [\n      ['google', ''],\n      ['youtube', ''],\n      ['twitter', 'twitter.com/google'],\n      ['flickr', ''],\n      ['quora', 'www.quora.com/topic/JavaScript-programming-language'],\n      ['twitch', 'www.twitch.tv/'],\n      ['reddit', ''],\n      ['wiki', 'zh.wikipedia.org/'],\n      ['gist', 'gist.github.com/'],\n      ['facebook', 'facebook.com/Google/'],\n      ['blogger', ''],\n    ]\n\n    function showIcons() {\n      list.innerHTML = SITE_LIST.map(v => {\n        let [id, url] = v\n        url = url || `www.${id}.com/`\n        return `\\\n<a rel=\"noopener noreferrer\" href=./-----https://${url}>\\\n<img width=128 height=128 src=__sys__/assets/ico/${id}.png></a>`\n      }).join('')\n    }\n\n    function addNodeItem(id, text) {\n      const optEl = document.createElement('option')\n      optEl.id = '--' + id\n      optEl.text = text\n      optEl.value = id\n      selNode.appendChild(optEl)\n    }\n\n    function updateSelected() {\n      const id = conf.node_default\n      const item = document.getElementById('--' + id)\n      if (item) {\n        item.selected = true\n      } else {\n        console.warn('unknown node:', id)\n      }\n    }\n\n    function showConf() {\n      for (const [id, node] of Object.entries(conf.node_map)) {\n        if (!node.hidden) {\n          addNodeItem(id, node.label)\n        }\n      }\n      updateSelected()\n    }\n  </script>\n</body>\n</html>"
  },
  {
    "path": "www/conf.js",
    "content": "jsproxy_config({\n  // 当前配置的版本（记录在日志中，用于排查问题）\n  // 每次修改配置，该值需要增加，否则不会生效。\n  // 默认每隔 5 分钟自动下载配置，若想立即验证，可通过隐私模式访问。\n  ver: '107',\n\n  // 通过 CDN 加速常用网站的静态资源（实验中）\n  static_boost: {\n    enable: true,\n    ver: 60\n  },\n\n  // 节点配置\n  node_map: {\n    'demo-hk': {\n      label: '演示服务-香港节点',\n      lines: {\n        // 主机:权重\n        'node-aliyun-hk-0.etherdream.com:8443': 1,\n        'node-aliyun-hk-1.etherdream.com:8443': 1,\n        'node-aliyun-hk-2.etherdream.com:8443': 1,\n      }\n    },\n    'demo-sg': {\n      label: '演示服务-新加坡节点',\n      lines: {\n        'node-aliyun-sg.etherdream.com:8443': 1,\n      },\n    },\n    'mysite': {\n      label: '当前站点',\n      lines: {\n        [location.host]: 1,\n      }\n    },\n    // 该节点用于加载大体积的静态资源\n    'cfworker': {\n      label: '',\n      hidden: true,\n      lines: {\n        // 收费版（高权重）\n        'node-cfworker.etherdream.com': 4,\n\n        // 免费版（低权重，分摊一些成本）\n        // 每个账号每天 10 万次免费请求，但有频率限制\n        'b.007.workers.dev': 1,\n        'b.hehe.workers.dev': 1,\n        'b.lulu.workers.dev': 1,\n        'b.jsproxy.workers.dev': 1,\n      }\n    }\n  },\n\n  /**\n   * 默认节点\n   */\n  // node_default: 'mysite',\n  node_default: /jsproxy-demo\\.\\w+$/.test(location.host) ? 'demo-hk' : 'mysite',\n\n  /**\n   * 加速节点\n   */\n  node_acc: 'cfworker',\n\n  /**\n   * 静态资源 CDN 地址\n   * 用于加速 `assets` 目录中的资源访问\n   */\n  assets_cdn: 'https://cdn.jsdelivr.net/gh/zjcqoo/zjcqoo.github.io@master/assets/',\n\n  // 本地测试时打开，否则访问的是线上的\n  // assets_cdn: 'assets/',\n\n  // 首页路径\n  index_path: 'index_v3.html',\n\n  // 支持 CORS 的站点列表（实验中...）\n  direct_host_list: 'cors_v1.txt',\n\n  /**\n   * 自定义注入页面的 HTML\n   */\n  inject_html: '<!-- custom html -->',\n\n  /**\n   * URL 自定义处理（设计中）\n   */\n  url_handler: {\n    'https://www.baidu.com/img/baidu_resultlogo@2.png': {\n      replace: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png'\n    },\n    'https://www.pornhub.com/': {\n      redir: 'https://php.net/'\n    },\n    'http://haha.com/': {\n      content: 'Hello World'\n    },\n  }\n})"
  },
  {
    "path": "www/sw.js",
    "content": "jsproxy_config=x=>{__CONF__=x;importScripts(__FILE__=x.assets_cdn+'bundle.c33e24c5.js')};importScripts('conf.js')"
  }
]