├── .babelrc ├── .gitattributes ├── .gitignore ├── .npmrc ├── .travis.yml ├── CHANGELOG.md ├── Dockerfile ├── README-zh-CN.md ├── README.md ├── bin ├── ca.crt ├── ca.key ├── cert_gen.sh ├── index.js ├── lpm_downgrade.sh ├── lpm_install.sh ├── lpm_upgrade.sh ├── lpm_util.sh ├── lum_electron.js ├── lum_electron_index.js ├── lum_node.js ├── lum_node_index.js ├── polyfill.js ├── pub │ ├── 1ace961377306f106345856f120ede0e.svg │ ├── 21a074040a11f7538c59d77d391ca492.svg │ ├── 43b012cade8883021fd7d5fd10faf245.svg │ ├── 638e03c0e8d8ff1e1e59187caed07674.svg │ ├── 6e8b7e0f9425ef4cf2722b9df94bf206.svg │ ├── 8c65e8e579be395b9ad6.runtime.js │ ├── a2077dab5090f880c07c.vendor.js │ ├── e2fac87f04a2eca49322.app.js │ ├── f983aef76c5cab587c461cb6b36733c7.svg │ ├── favicon.ico │ ├── font │ │ ├── Gibson-Book.woff │ │ ├── Gibson-BookItalic.woff │ │ ├── Gibson-Italic.woff │ │ ├── Gibson-Medium.woff │ │ ├── Gibson-MediumItalic.woff │ │ ├── Gibson-Regular.woff │ │ ├── Gibson-SemiBold.woff │ │ ├── Gibson-SemiBoldItalic.woff │ │ ├── lato_bold.woff2 │ │ └── lato_regular.woff2 │ ├── img │ │ ├── asn.svg │ │ ├── banned_ips.svg │ │ ├── bell.svg │ │ ├── brd_logo_large.svg │ │ ├── brd_logo_letter.svg │ │ ├── checker.png │ │ ├── city.svg │ │ ├── columns.svg │ │ ├── config.svg │ │ ├── country.svg │ │ ├── data_center.svg │ │ ├── delete.svg │ │ ├── down.svg │ │ ├── faq.svg │ │ ├── flag.svg │ │ ├── flag_any_country.svg │ │ ├── g_ip.svg │ │ ├── general.svg │ │ ├── google.svg │ │ ├── har_viewer.svg │ │ ├── howto.svg │ │ ├── ic_admin.svg │ │ ├── ic_api.svg │ │ ├── ic_arrow_down.svg │ │ ├── ic_back.svg │ │ ├── ic_browse.svg │ │ ├── ic_browser.svg │ │ ├── ic_cancel.svg │ │ ├── ic_checkmark.svg │ │ ├── ic_chrome.jpg │ │ ├── ic_code.svg │ │ ├── ic_copy.svg │ │ ├── ic_download.svg │ │ ├── ic_explorer.png │ │ ├── ic_faq.svg │ │ ├── ic_filter.svg │ │ ├── ic_firefox.jpg │ │ ├── ic_general_settings.svg │ │ ├── ic_guest.svg │ │ ├── ic_how_to.svg │ │ ├── ic_off.svg │ │ ├── ic_refresh.svg │ │ ├── ic_remove.svg │ │ ├── ic_resource_document.png │ │ ├── ic_safari.jpg │ │ ├── ic_view.svg │ │ ├── ic_warning.svg │ │ ├── info.svg │ │ ├── large_icons.png │ │ ├── loader.gif │ │ ├── logo_80legs.svg │ │ ├── logo_crawlera.svg │ │ ├── logo_import.svg │ │ ├── logs.svg │ │ ├── map_pin.svg │ │ ├── maps.svg │ │ ├── medium_icons.png │ │ ├── mobile.svg │ │ ├── preset_icon.png │ │ ├── proxies.svg │ │ ├── proxy_ext.svg │ │ ├── proxy_lum.svg │ │ ├── request_headers.svg │ │ ├── residential.svg │ │ ├── rotation.svg │ │ ├── rules.svg │ │ ├── sessions.svg │ │ ├── setup_guide.svg │ │ ├── small_icons.png │ │ ├── state.svg │ │ ├── static_res.svg │ │ ├── stats.svg │ │ ├── stats_white.svg │ │ ├── target.svg │ │ ├── tester.svg │ │ ├── tools.svg │ │ ├── treeoutline_triangles.png │ │ ├── up.svg │ │ ├── warning.svg │ │ ├── zipcode.svg │ │ └── zone_icon.png │ └── index.html └── upgrader.js ├── build ├── icon.ico ├── installer.nsh ├── installerIcon.ico └── pkgicon.ico ├── db └── cities.csv ├── extensions ├── timezone │ ├── background.js │ ├── inject.js │ └── manifest.json └── webrtc │ ├── background.js │ └── manifest.json ├── lib ├── cache.js ├── cache_client.js ├── cities.js ├── cloud_mgr.js ├── cluster_mgr.js ├── config.js ├── consts.js ├── context.js ├── https_agent.js ├── hutil_loader.js ├── ip_cache.js ├── locations.js ├── logger.js ├── loki.js ├── lpm_conn.js ├── lpm_f.js ├── manager.js ├── md5_util.js ├── metrics.js ├── middleware.js ├── migration.js ├── mixins │ ├── core.js │ ├── mgr_config.js │ ├── mgr_proxy.js │ ├── server_handle.js │ ├── server_send.js │ ├── web_api.js │ └── web_server.js ├── perr.js ├── proxy_port.js ├── puppeteer.js ├── requester.js ├── router.js ├── rules.js ├── server.js ├── session.js ├── smtp.js ├── socks.js ├── ssl.js ├── stat.js ├── swagger.json ├── throttle_mgr.js ├── username.js ├── util.js ├── worker.js ├── ws.js ├── zagent_api.js └── zones.js ├── package.json ├── publish_validate.js ├── scripts ├── changelog_validate.js └── stress_test.js ├── src ├── pub │ ├── api.js │ ├── app.js │ ├── chrome_widgets.js │ ├── common.js │ ├── common │ │ ├── api_url_modal.js │ │ ├── controls.js │ │ ├── error_boundry.js │ │ ├── i18n.js │ │ ├── logs_settings_modal.js │ │ ├── modals.js │ │ ├── nav_tabs.js │ │ ├── network_types.js │ │ ├── presets.js │ │ ├── ssl_modal.js │ │ ├── toggle_on_off.js │ │ ├── tooltip.js │ │ ├── warnings_modal.js │ │ └── zone_desc.js │ ├── config.js │ ├── cp_ipc.js │ ├── cpu_warning.js │ ├── css │ │ ├── api_url_modal.less │ │ ├── app.less │ │ ├── chrome_widgets.less │ │ ├── common.less │ │ ├── config.less │ │ ├── login.less │ │ ├── logs.less │ │ ├── nav.less │ │ ├── nav_tabs.less │ │ ├── notif_center.less │ │ ├── overview.less │ │ ├── proxies.less │ │ ├── proxy_add.less │ │ ├── proxy_blank.less │ │ ├── proxy_edit.less │ │ ├── proxy_tester.less │ │ ├── report_bug.less │ │ ├── settings.less │ │ ├── tooltip.less │ │ ├── whitelist_ips.less │ │ └── zone_desc.less │ ├── har_viewer.js │ ├── howto.js │ ├── index.html │ ├── instructions.js │ ├── login.js │ ├── logs.js │ ├── nav.js │ ├── notif_center.js │ ├── overview.js │ ├── proxies.js │ ├── proxy_add.js │ ├── proxy_blank.js │ ├── proxy_edit │ │ ├── alloc_modal.js │ │ ├── browser.js │ │ ├── bw_limit_modal.js │ │ ├── common.js │ │ ├── fields.js │ │ ├── general.js │ │ ├── index.js │ │ ├── logs.js │ │ ├── rotation.js │ │ ├── rules.js │ │ ├── targeting.js │ │ └── users_modal.js │ ├── proxy_tester.js │ ├── report_bug.js │ ├── schema.js │ ├── settings.js │ ├── stats.js │ ├── util.js │ ├── whitelist_ips.js │ └── ws.js └── pub2 │ ├── api.js │ ├── app.js │ ├── chrome_widgets.js │ ├── common.js │ ├── common │ ├── api_url_modal.js │ ├── box_radio.js │ ├── controls.js │ ├── error_boundry.js │ ├── exit_confirm_modal.js │ ├── i18n.js │ ├── logs_settings_modal.js │ ├── modals.js │ ├── nav_tabs.js │ ├── network_types.js │ ├── presets.js │ ├── sidebar.js │ ├── ssl_modal.js │ ├── tab_group.js │ ├── toggle_on_off.js │ ├── tooltip.js │ ├── warnings_modal.js │ └── zone_desc.js │ ├── config.js │ ├── cp_ipc.js │ ├── cpu_warning.js │ ├── css │ ├── api_url_modal.less │ ├── app.less │ ├── box_radio.less │ ├── chrome_widgets.less │ ├── common.less │ ├── config.less │ ├── login.less │ ├── logs.less │ ├── nav.less │ ├── nav_tabs.less │ ├── notif_center.less │ ├── overview.less │ ├── proxies.less │ ├── proxy_add.less │ ├── proxy_blank.less │ ├── proxy_edit.less │ ├── proxy_tester.less │ ├── report_bug.less │ ├── settings.less │ ├── tab_group.less │ ├── tooltip.less │ ├── whitelist_ips.less │ └── zone_desc.less │ ├── har_viewer.js │ ├── howto.js │ ├── instructions.js │ ├── login.js │ ├── logs.js │ ├── nav.js │ ├── notif_center.js │ ├── overview.js │ ├── proxies.js │ ├── proxies_toolbar.js │ ├── proxy_add.js │ ├── proxy_blank.js │ ├── proxy_edit │ ├── alloc_modal.js │ ├── browser.js │ ├── bw_limit_modal.js │ ├── common.js │ ├── fields.js │ ├── general.js │ ├── index.js │ ├── logs.js │ ├── rotation.js │ ├── rules.js │ ├── targeting.js │ └── users_modal.js │ ├── proxy_tester.js │ ├── report_bug.js │ ├── schema.js │ ├── settings.js │ ├── stats.js │ ├── util.js │ ├── whitelist_ips.js │ └── ws.js ├── test ├── api.js ├── common.js ├── config.js ├── index.js ├── ip_cache.js ├── manager.js ├── migration.js ├── rules.js ├── scripts.js ├── username.js ├── util.js └── ws.js ├── util ├── ajax.js ├── array.js ├── buf_pool.js ├── cert_util.js ├── cli.js ├── cluster_ipc.js ├── conf.js ├── config.js ├── conv.js ├── country.js ├── csv.js ├── date.js ├── efile.js ├── es6_shim.js ├── escape.js ├── etask.js ├── events.js ├── exec.js ├── file.js ├── fs_cache.js ├── jtools.js ├── lpm_api_models.js ├── lpm_config.js ├── lpm_config_static.js ├── lpm_esm_loader.js ├── lpm_file.js ├── lpm_request.js ├── lpm_util.js ├── match.js ├── os.js ├── queue.js ├── rand.js ├── rate_limit.js ├── require_node.js ├── rules_util.js ├── setdb.js ├── sinon.js ├── sprintf.js ├── storage.js ├── string.js ├── takeup_util.js ├── tz.js ├── url.js ├── user_agent.js ├── util.js ├── version.js ├── ws.js ├── zcounter.js └── zerr.js ├── versions.json ├── webpack.common.js ├── webpack.config.js ├── webpack.dev.js ├── webpack.prod.js ├── www ├── lum │ └── pub │ │ └── locale │ │ ├── en.json │ │ ├── es.json │ │ ├── ko.json │ │ ├── pt-br.json │ │ ├── ru.json │ │ ├── tr.json │ │ └── zh-hans.json └── util │ └── pub │ ├── bootstrap_methods.js │ ├── bullets.js │ ├── css │ ├── bullets.less │ └── har.less │ ├── har.js │ ├── pure_component.js │ ├── tooltip.js │ ├── urlp.js │ └── user_agent_gen.json └── zon_config.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"], 3 | "plugins": [ 4 | "@babel/plugin-transform-runtime", 5 | "@babel/plugin-transform-modules-amd" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.png binary -eol 3 | *.jpg binary -eol 4 | *.ico binary -eol 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *~ 3 | *.swp 4 | CVS/ 5 | .#* 6 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | puppeteer_skip_chromium_download=true 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | before_install: if [[ `npm -v` != 4* ]]; then npm i -g npm@4; fi 3 | node_js: 4 | # - node 5 | - '8' 6 | os: 7 | - linux 8 | - osx 9 | notifications: 10 | email: 11 | - romank@luminatio.io 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # luminati-proxy Dockerfile 3 | # 4 | # https://github.com/luminati-io/luminati-proxy 5 | # 6 | 7 | # Pull base image. 8 | FROM node:20.12.1-bookworm 9 | 10 | ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true 11 | 12 | RUN apt-get update && apt-get install -y gconf-service libasound2 libatk1.0-0 \ 13 | libcairo2 libcups2 libfontconfig1 libgdk-pixbuf2.0-0 libgtk-3-0 libnspr4 \ 14 | libpango-1.0-0 libxss1 fonts-liberation libappindicator1 libnss3 \ 15 | lsb-release xdg-utils ca-certificates 16 | 17 | # Install latest chrome dev package and fonts to support major charsets (Chinese, Japanese, Arabic, Hebrew, Thai and a few others) 18 | # Note: this installs the necessary libs to make the bundled version of Chromium that Puppeteer installs, work. 19 | RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - 20 | RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' 21 | RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb 22 | RUN dpkg -i google-chrome-stable_current_amd64.deb --fix-missing; apt-get -fy install 23 | RUN rm -rf /var/lib/apt/lists/* 24 | RUN rm google-chrome-stable_current_amd64.deb 25 | 26 | USER root 27 | RUN npm install -g npm@10.9.2 28 | # RUN npm config set user root 29 | 30 | # Install Proxy Manager 31 | RUN npm install -g @luminati-io/luminati-proxy --legacy-peer-deps 32 | 33 | # Reinstall Proxy Manager dependencies omit dev 34 | RUN cd /usr/local/lib/node_modules/@luminati-io/luminati-proxy && \ 35 | rm -rf node_modules/ && NODE_ENV=production npm install --legacy-peer-deps 36 | 37 | # Mark environment as Docker for CLI output 38 | ENV DOCKER=1 39 | 40 | # Define default command. 41 | CMD ["luminati", "--help"] 42 | -------------------------------------------------------------------------------- /bin/ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFozCCA4ugAwIBAgIJAPnnIqmvvTArMA0GCSqGSIb3DQEBBQUAMD8xCzAJBgNV 3 | BAYTAklMMQswCQYDVQQIEwJJTDENMAsGA1UEChMESG9sYTEUMBIGA1UEAxMLbHVt 4 | aW5hdGkuaW8wHhcNMTYwOTI3MTQyODM4WhcNMjYwOTI1MTQyODM4WjA/MQswCQYD 5 | VQQGEwJJTDELMAkGA1UECBMCSUwxDTALBgNVBAoTBEhvbGExFDASBgNVBAMTC2x1 6 | bWluYXRpLmlvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtiqw0DuX 7 | g5g7BC+Cr7mZvgXB7CsJ10YFb2xwoDZlHHJ8G0KEMUeNiY9EjPR8ZIHlnjGJehsW 8 | PUvJeSAoDnT+fh4udWyUJ3VSqDTyGpu4DpfLBwaaZP/fq45UeR0oLs3ZJd6joDss 9 | AjJdQbdBPJj/57MjwbF+jddP6qm9XbCWjYzl1uxdMVjloetyRUgkhkh2ALp/VtK8 10 | hUj/XgvD/Y1souKYs5DKayJTn+GM6MlSOUBQ0+b8yUbDb/9vjbHlX4pZ8gbgSEFf 11 | xUV49Sxd6EhRXzFw4TERQVut0cgojmRmrgXXwc4kJi0Uvtc6tV/hJeH2yRS84Ehg 12 | feY5dcJVc69ILYfGrNmwbFvf5aHZPWFG0kIcy9iMMk+3wSUaBP+FAYyd0i+PJTxy 13 | 5Jfmhs6BHowuEr0zgL+xge+/RCEbVUPvA6w9DWYbpqckZUh9sPga3JcHjaHGs6Cz 14 | dnjEShgmlBm0DL6JMumLWFJrjztsm56Huuai0F5pwyrsyq8fbK6Sp18sq5/vH3Vy 15 | t2XAj4EIFvpWHZjuocCe5/5vAbkSXjQ5HEIS+SyVhlFriCy5Mf3fTyMFqwm3tbZv 16 | jEooumi0/9F2WvisUgheC1uatZ8M+Pzi+Kp3x2SSS992KWs0M35GEstiB09RkNHe 17 | GItI6qxqY/Npw5u6lBE6Z28ISwvuet1a4vMCAwEAAaOBoTCBnjAdBgNVHQ4EFgQU 18 | Wq7PsMnq2tuDhTV0oUW4jjzvLTcwbwYDVR0jBGgwZoAUWq7PsMnq2tuDhTV0oUW4 19 | jjzvLTehQ6RBMD8xCzAJBgNVBAYTAklMMQswCQYDVQQIEwJJTDENMAsGA1UEChME 20 | SG9sYTEUMBIGA1UEAxMLbHVtaW5hdGkuaW+CCQD55yKpr70wKzAMBgNVHRMEBTAD 21 | AQH/MA0GCSqGSIb3DQEBBQUAA4ICAQA3oT4lrUErSqXjQtDUINo62KcJWs4kjEd8 22 | qXZdl/HVim06nOG6DFZCSh8JngFi4MFmSzGlBGxe1pXaYArtekfLWmhwoVoJiiaA 23 | DAAPItcZNlA9zIORyLZlrXlIuP5xzsb9PbnNWhd9xJHksHGoHDPHAW/KI/GJdjQv 24 | uuCyObvv1IgGvfHbv4lXGCwQuU0OBGXv1kfZtAqUS+ei5zkK+nY0qc3L3Ce+Ow6h 25 | /haDe0FDoT7zkwnEHu/ExCGSR3lNnyBAewlPVMzbJznuPMU3FFA3MHT7IcHxJWff 26 | r8jOXo3qXWqd+T2oDO02KUR2ZVolI8FGx6yIKfLwWnj+eR2dfdMx0tUX4F6mRi4N 27 | zGmhhIIHtViAMf59tBL7az26C8DGfX0p4oECpKtc86u5bYTbRZ1xrf6t/wFqqgB/ 28 | RVqn9IhSfXNZtxBn8G0odR8sPIiBxJKvkLMDKoAEeErwd0yqnr8FplskFuPn0FY5 29 | N7n7dj5cHoSUtSAkM6bHCFY+XVtUoy6xisTAobajHvU3e2cDVKizC/ocUbHbTJgh 30 | nevnzyTtKL2w820PDmI7plFN3wR3epd4kTAP5KT196Pjwjg+Dqgt2OnGAafKr+Qr 31 | o2cdIF5MbULVkux4RKzpNKaoDtrnvC1jROM5s1R0Lb96dQcS/VwmyX22lKdbbY9F 32 | ij5GZar9JA== 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /bin/cert_gen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # LICENSE_CODE ZON ISC 3 | openssl req -x509 -sha256 -newkey rsa:4096 -keyout $1 \ 4 | -out $2 -days 365 -nodes \ 5 | -subj /C=IL/ST=IL/O=Luminati/CN=luminati.io \ 6 | -config <(cat /etc/ssl/openssl.cnf <( 7 | cat <<-EOF 8 | [req] 9 | x509_extensions = v3_ca 10 | [v3_ca] 11 | keyUsage = keyCertSign 12 | extendedKeyUsage = serverAuth, clientAuth, codeSigning 13 | EOF 14 | )) 15 | -------------------------------------------------------------------------------- /bin/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // LICENSE_CODE ZON ISC 3 | 'use strict'; /*jslint node:true, esnext:true*/ 4 | require('../util/conf.js'); 5 | require('./polyfill.js'); 6 | const lpm_util = require('../util/lpm_util.js'); 7 | const lpm_config = require('../util/lpm_config.js'); 8 | const Lum_node_index = require('./lum_node_index.js'); 9 | const Lum_electron_index = require('./lum_electron_index.js'); 10 | const argv = lpm_util.init_args(); 11 | const lum = lpm_config.is_electron ? 12 | new Lum_electron_index(argv) : 13 | new Lum_node_index(argv); 14 | lum.run(); 15 | -------------------------------------------------------------------------------- /bin/lpm_downgrade.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # LICENSE_CODE ZON ISC 3 | DIR=$(dirname "$0") 4 | . "$DIR/lpm_util.sh" 5 | LOGFILE=$1 6 | 7 | main() 8 | { 9 | if ! [ -d "$(npm root -g)/@luminati-io/luminati-proxy.old" ]; then 10 | perr "downgrade_no_backup" 11 | exit 1 12 | fi 13 | sudo_cmd "rm -rf $(npm root -g)/@luminati-io/luminati-proxy" 0 1 14 | sudo_cmd "mv $(npm root -g)/@luminati-io/luminati-proxy.old $(npm root -g)/@luminati-io/luminati-proxy" 0 1 15 | reset_luminati_symlink 0 1 16 | perr "downgrade_success_lpm" 17 | } 18 | 19 | main 20 | -------------------------------------------------------------------------------- /bin/lpm_upgrade.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # LICENSE_CODE ZON ISC 3 | DIR=$(dirname "$0") 4 | . "$DIR/lpm_util.sh" 5 | LOGFILE=$1 6 | 7 | main() 8 | { 9 | # create version backup to be possibly used by lpm_downgrade.sh 10 | sudo_cmd "mv $(npm root -g)/@luminati-io/luminati-proxy $(npm root -g)/@luminati-io/luminati-proxy.old" 0 1 11 | retry_sudo_cmd "npm install -g --unsafe-perm --force --loglevel error @luminati-io/luminati-proxy" 0 1 12 | if (($?)); then 13 | perr "upgrade_error_lpm" 14 | exit 1 15 | fi 16 | reset_luminati_symlink 0 1 17 | perr "upgrade_success_lpm" 18 | } 19 | 20 | main 21 | -------------------------------------------------------------------------------- /bin/lum_electron_index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // LICENSE_CODE ZON ISC 3 | 'use strict'; /*jslint node:true, esnext:true*/ 4 | 5 | class Lum_electron_index { 6 | constructor(argv){ 7 | this.argv = argv; 8 | } 9 | run(){ 10 | require('./lum_electron.js').run(this.argv); 11 | } 12 | } 13 | module.exports = Lum_electron_index; 14 | -------------------------------------------------------------------------------- /bin/polyfill.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // LICENSE_CODE ZON ISC 3 | 'use strict'; /*jslint node:true, esnext:true*/ 4 | if (!('hasOwn' in Object)) 5 | Object.hasOwn = Object.call.bind(Object.hasOwnProperty); 6 | -------------------------------------------------------------------------------- /bin/pub/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/favicon.ico -------------------------------------------------------------------------------- /bin/pub/font/Gibson-Book.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/font/Gibson-Book.woff -------------------------------------------------------------------------------- /bin/pub/font/Gibson-BookItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/font/Gibson-BookItalic.woff -------------------------------------------------------------------------------- /bin/pub/font/Gibson-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/font/Gibson-Italic.woff -------------------------------------------------------------------------------- /bin/pub/font/Gibson-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/font/Gibson-Medium.woff -------------------------------------------------------------------------------- /bin/pub/font/Gibson-MediumItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/font/Gibson-MediumItalic.woff -------------------------------------------------------------------------------- /bin/pub/font/Gibson-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/font/Gibson-Regular.woff -------------------------------------------------------------------------------- /bin/pub/font/Gibson-SemiBold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/font/Gibson-SemiBold.woff -------------------------------------------------------------------------------- /bin/pub/font/Gibson-SemiBoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/font/Gibson-SemiBoldItalic.woff -------------------------------------------------------------------------------- /bin/pub/font/lato_bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/font/lato_bold.woff2 -------------------------------------------------------------------------------- /bin/pub/font/lato_regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/font/lato_regular.woff2 -------------------------------------------------------------------------------- /bin/pub/img/asn.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/banned_ips.svg: -------------------------------------------------------------------------------- 1 | ic_ic_banned_ips 2 | -------------------------------------------------------------------------------- /bin/pub/img/bell.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/brd_logo_letter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /bin/pub/img/checker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/img/checker.png -------------------------------------------------------------------------------- /bin/pub/img/city.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/columns.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/config.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/country.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/data_center.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/delete.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/faq.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/flag.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /bin/pub/img/g_ip.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/general.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/google.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/har_viewer.svg: -------------------------------------------------------------------------------- 1 | ic_ic_har_viewer 2 | -------------------------------------------------------------------------------- /bin/pub/img/howto.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/ic_admin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /bin/pub/img/ic_api.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /bin/pub/img/ic_arrow_down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /bin/pub/img/ic_back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /bin/pub/img/ic_browse.svg: -------------------------------------------------------------------------------- 1 | ic_chrome 2 | -------------------------------------------------------------------------------- /bin/pub/img/ic_browser.svg: -------------------------------------------------------------------------------- 1 | ic_browser 2 | -------------------------------------------------------------------------------- /bin/pub/img/ic_cancel.svg: -------------------------------------------------------------------------------- 1 | ic_cancel 2 | -------------------------------------------------------------------------------- /bin/pub/img/ic_checkmark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 26B943F4-0485-4F1D-B3B9-97EE024EF875 5 | Created with sketchtool. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /bin/pub/img/ic_chrome.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/img/ic_chrome.jpg -------------------------------------------------------------------------------- /bin/pub/img/ic_code.svg: -------------------------------------------------------------------------------- 1 | ic_code 2 | -------------------------------------------------------------------------------- /bin/pub/img/ic_copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /bin/pub/img/ic_download.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /bin/pub/img/ic_explorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/img/ic_explorer.png -------------------------------------------------------------------------------- /bin/pub/img/ic_faq.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /bin/pub/img/ic_filter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /bin/pub/img/ic_firefox.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/img/ic_firefox.jpg -------------------------------------------------------------------------------- /bin/pub/img/ic_general_settings.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /bin/pub/img/ic_how_to.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /bin/pub/img/ic_off.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1EE40F92-FD7D-4B6C-B6A4-68CA7752CED2 5 | Created with sketchtool. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /bin/pub/img/ic_refresh.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /bin/pub/img/ic_remove.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /bin/pub/img/ic_resource_document.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/img/ic_resource_document.png -------------------------------------------------------------------------------- /bin/pub/img/ic_safari.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/img/ic_safari.jpg -------------------------------------------------------------------------------- /bin/pub/img/ic_view.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /bin/pub/img/ic_warning.svg: -------------------------------------------------------------------------------- 1 | ic_warning 2 | -------------------------------------------------------------------------------- /bin/pub/img/info.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/large_icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/img/large_icons.png -------------------------------------------------------------------------------- /bin/pub/img/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/img/loader.gif -------------------------------------------------------------------------------- /bin/pub/img/logo_80legs.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | LOGO 9 | Created with Sketch. 10 | 11 | 15 | 17 | 18 | 21 | 25 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /bin/pub/img/logo_import.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | import-logo-white 10 | Created with Sketch. 11 | 12 | 13 | 16 | 19 | 22 | 24 | 25 | 27 | 28 | 30 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /bin/pub/img/logs.svg: -------------------------------------------------------------------------------- 1 | ic_logs 2 | -------------------------------------------------------------------------------- /bin/pub/img/map_pin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /bin/pub/img/medium_icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/img/medium_icons.png -------------------------------------------------------------------------------- /bin/pub/img/mobile.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /bin/pub/img/preset_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/img/preset_icon.png -------------------------------------------------------------------------------- /bin/pub/img/proxies.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/proxy_ext.svg: -------------------------------------------------------------------------------- 1 | ic_proxy_ext 2 | -------------------------------------------------------------------------------- /bin/pub/img/proxy_lum.svg: -------------------------------------------------------------------------------- 1 | ic_proxy_lum 2 | -------------------------------------------------------------------------------- /bin/pub/img/request_headers.svg: -------------------------------------------------------------------------------- 1 | ic_headers_2 2 | -------------------------------------------------------------------------------- /bin/pub/img/residential.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/rotation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/rules.svg: -------------------------------------------------------------------------------- 1 | ic_ic_rules 2 | -------------------------------------------------------------------------------- /bin/pub/img/sessions.svg: -------------------------------------------------------------------------------- 1 | ic_ic_sessions 2 | -------------------------------------------------------------------------------- /bin/pub/img/setup_guide.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /bin/pub/img/small_icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/img/small_icons.png -------------------------------------------------------------------------------- /bin/pub/img/state.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/static_res.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /bin/pub/img/stats.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/stats_white.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /bin/pub/img/target.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/tester.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | ic_proxy_tester 9 | 11 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /bin/pub/img/tools.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/treeoutline_triangles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/img/treeoutline_triangles.png -------------------------------------------------------------------------------- /bin/pub/img/up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/warning.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/pub/img/zipcode.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /bin/pub/img/zone_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/bin/pub/img/zone_icon.png -------------------------------------------------------------------------------- /bin/pub/index.html: -------------------------------------------------------------------------------- 1 | Proxy Manager
-------------------------------------------------------------------------------- /build/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/build/icon.ico -------------------------------------------------------------------------------- /build/installer.nsh: -------------------------------------------------------------------------------- 1 | Caption "${PRODUCT_NAME} ${VERSION} Setup" 2 | !define StrRep "!insertmacro StrRep" 3 | !macro StrRep output string old new 4 | Push `${string}` 5 | Push `${old}` 6 | Push `${new}` 7 | !ifdef __UNINSTALL__ 8 | Call un.StrRep 9 | !else 10 | Call StrRep 11 | !endif 12 | Pop ${output} 13 | !macroend 14 | 15 | !macro Func_StrRep un 16 | Function ${un}StrRep 17 | Exch $R2 ;new 18 | Exch 1 19 | Exch $R1 ;old 20 | Exch 2 21 | Exch $R0 ;string 22 | Push $R3 23 | Push $R4 24 | Push $R5 25 | Push $R6 26 | Push $R7 27 | Push $R8 28 | Push $R9 29 | 30 | StrCpy $R3 0 31 | StrLen $R4 $R1 32 | StrLen $R6 $R0 33 | StrLen $R9 $R2 34 | loop: 35 | StrCpy $R5 $R0 $R4 $R3 36 | StrCmp $R5 $R1 found 37 | StrCmp $R3 $R6 done 38 | IntOp $R3 $R3 + 1 ;move offset by 1 to check the next character 39 | Goto loop 40 | found: 41 | StrCpy $R5 $R0 $R3 42 | IntOp $R8 $R3 + $R4 43 | StrCpy $R7 $R0 "" $R8 44 | StrCpy $R0 $R5$R2$R7 45 | StrLen $R6 $R0 46 | IntOp $R3 $R3 + $R9 ;move offset by length of the replacement string 47 | Goto loop 48 | done: 49 | 50 | Pop $R9 51 | Pop $R8 52 | Pop $R7 53 | Pop $R6 54 | Pop $R5 55 | Pop $R4 56 | Pop $R3 57 | Push $R0 58 | Push $R1 59 | Pop $R0 60 | Pop $R1 61 | Pop $R0 62 | Pop $R2 63 | Exch $R1 64 | FunctionEnd 65 | !macroend 66 | !insertmacro Func_StrRep "" 67 | !insertmacro Func_StrRep "un." 68 | 69 | !macro customInstall 70 | Var /GLOBAL escapedExe 71 | Push "$appExe" 72 | Push " " 73 | Push "^ " 74 | Call StrRep 75 | Pop $escapedExe 76 | Push "$escapedExe" 77 | Push "&" 78 | Push "^&" 79 | Call StrRep 80 | Pop $escapedExe 81 | CreateShortCut "$startMenuLink" "%comspec%" "/C $\"^$\"$escapedExe^$\"$\"" "$appExe" 0 "" "" "${APP_DESCRIPTION}" 82 | CreateShortCut "$desktopLink" "%comspec%" "/C $\"$escapedExe$\"" $appExe" 0 "" "" "${APP_DESCRIPTION}" 83 | !macroend 84 | -------------------------------------------------------------------------------- /build/installerIcon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/build/installerIcon.ico -------------------------------------------------------------------------------- /build/pkgicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luminati-io/luminati-proxy/8c7eedc670099d5e51067de2f69d5f377dc17957/build/pkgicon.ico -------------------------------------------------------------------------------- /extensions/timezone/background.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON 2 | 'use strict'; /*jslint browser:true, es6:true, react:true*//*global chrome*/ 3 | 4 | const df = new Date().getTimezoneOffset(); 5 | 6 | const on_committed = ({url, tabId, frameId})=>{ 7 | const timezone_id = localStorage.getItem('timezone_id'); 8 | const offset = localStorage.getItem('offset'); 9 | const content = `Date.prefs = ["${timezone_id}", ${-1*offset}, ${df}]`; 10 | if (!(url && url.startsWith('http'))) 11 | return; 12 | chrome.tabs.executeScript(tabId, { 13 | runAt: 'document_start', 14 | frameId, 15 | matchAboutBlank: true, 16 | code: 'document.documentElement.appendChild(Object.assign(' 17 | +`document.createElement('script'), {textContent: '${content}'}))` 18 | +'.remove();', 19 | }, ()=>chrome.runtime.lastError); 20 | }; 21 | 22 | window._init = ({timezone_id, offset})=>{ 23 | localStorage.setItem('timezone_id', timezone_id); 24 | localStorage.setItem('offset', offset); 25 | chrome.webNavigation.onCommitted.addListener(on_committed); 26 | }; 27 | -------------------------------------------------------------------------------- /extensions/timezone/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "background": { 3 | "scripts": [ 4 | "background.js" 5 | ] 6 | }, 7 | "content_scripts": [ 8 | { 9 | "matches": [ 10 | "*://*/*" 11 | ], 12 | "match_about_blank": true, 13 | "all_frames": true, 14 | "run_at": "document_start", 15 | "js": [ 16 | "inject.js" 17 | ] 18 | } 19 | ], 20 | "manifest_version": 2, 21 | "name": "Proxy Manager Timezone", 22 | "permissions": [ 23 | "storage", 24 | "*://*/*", 25 | "webNavigation" 26 | ], 27 | "version": "1.519.10" 28 | } -------------------------------------------------------------------------------- /extensions/webrtc/background.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON 2 | 'use strict'; /*jslint browser:true, es6:true*//*global chrome*/ 3 | 4 | chrome.privacy.network.webRTCIPHandlingPolicy 5 | .set({value: 'disable_non_proxied_udp'}); 6 | 7 | -------------------------------------------------------------------------------- /extensions/webrtc/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "background": { 3 | "persistent": false, 4 | "scripts": [ 5 | "background.js" 6 | ] 7 | }, 8 | "manifest_version": 2, 9 | "name": "Proxy Manager WebRTC", 10 | "permissions": [ 11 | "privacy" 12 | ], 13 | "version": "1.519.10" 14 | } -------------------------------------------------------------------------------- /lib/cache.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true, esnext:true, evil: true*/ 3 | const etask = require('../util/etask.js'); 4 | const date = require('../util/date.js'); 5 | const logger = require('./logger.js').child({category: 'Cache'}); 6 | const {CACHE_LIMIT} = require('./consts.js'); 7 | 8 | const Cache = etask._class(class Cache { 9 | constructor(opt={}){ 10 | this.opt = opt; 11 | this.space_taken = 0; 12 | this.map = new Map(); 13 | } 14 | set(url, res_data, headers){ 15 | const duration = date.ms.HOUR; 16 | res_data = res_data.map(d=>Buffer.from(d.data)); 17 | const space = this.calc_size(res_data, headers); 18 | if (this.space_taken+space>=CACHE_LIMIT) 19 | return logger.warn('limit %s reached', CACHE_LIMIT); 20 | if (duration) 21 | { 22 | setTimeout(()=>{ 23 | this.space_taken -= space; 24 | this.map.delete(url); 25 | }, duration); 26 | } 27 | this.map.set(url, {res_data, headers}); 28 | this.space_taken += space; 29 | } 30 | has(url){ 31 | return this.map.has(url); 32 | } 33 | get(url){ 34 | return this.map.get(url); 35 | } 36 | calc_size(res_data, headers){ 37 | const data_size = res_data.reduce((acc, el)=>acc+el.length, 0); 38 | let headers_size = 0; 39 | for (let key in headers) 40 | headers_size += key.length+headers[key].length; 41 | return data_size+headers_size; 42 | } 43 | }); 44 | 45 | let cache; 46 | 47 | function get_cache(){ 48 | if (!cache) 49 | cache = new Cache(); 50 | return cache; 51 | } 52 | 53 | module.exports = get_cache; 54 | -------------------------------------------------------------------------------- /lib/cache_client.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true, esnext:true, evil: true*/ 3 | const etask = require('../util/etask.js'); 4 | const cluster_ipc = require('../util/cluster_ipc.js'); 5 | 6 | class Cache_client { 7 | set(url, res_data, headers){ 8 | return etask(function*_set(){ 9 | return yield cluster_ipc.call_master('cache_set', 10 | {url, res_data, headers}); 11 | }); 12 | } 13 | has(url){ 14 | return etask(function*_has(){ 15 | return yield cluster_ipc.call_master('cache_has', {url}); 16 | }); 17 | } 18 | get(url){ 19 | return etask(function*_get(){ 20 | const res = yield cluster_ipc.call_master('cache_get', {url}); 21 | if (res && res.res_data) 22 | res.res_data = res.res_data.map(d=>Buffer.from(d.data)); 23 | return res; 24 | }); 25 | } 26 | } 27 | 28 | module.exports = Cache_client; 29 | -------------------------------------------------------------------------------- /lib/consts.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true, esnext:true, evil: true*/ 3 | const {constants} = require('crypto'); 4 | const date = require('../util/date.js'); 5 | const E = module.exports, {MIN, HOUR} = date.ms; 6 | 7 | E.NO_PEERS_ERROR_SSL = 'Proxy Error: server_error No peers available'; 8 | E.NO_PEERS_ERROR = 'Proxy Error: No peers available'; 9 | E.SUCCESS_STATUS_CODE_RE = /([123]..|404)/; 10 | E.SESSION_TERMINATED_BODY = 'Session has been terminated. To connectinue you ' 11 | +'need to refresh the session'; 12 | E.TLS_ERROR_MSG = 'TLS error: client has to install certificate'; 13 | E.HIGH_CPU_THRESHOLD = 98; 14 | E.UPGRADE_CHECK_INTERVAL = 10*MIN; 15 | E.UPGRADE_IDLE_PERIOD = 30*MIN; 16 | E.ZAGENT_API_PORT = 3395; 17 | E.MAX_STRING_LENGTH = 300; 18 | E.MAX_URL_LENGTH = 1024; 19 | E.MAX_EXT_PROXIES = 100; 20 | E.CACHE_LIMIT = 1e8; 21 | E.SOURCES = {API: 'API', UI: 'UI'}; 22 | E.USERNAME_PREFS = ['brd', 'lum']; 23 | E.MAX_WS_REFRESH_RETRIES = 10; 24 | E.WS_REFRESH_INTERVAL = 10*MIN; 25 | E.WS_REFRESH_RESON = 'Refresh lpm_f connection'; 26 | E.VIPDB_RELOAD_TIMEOUT = MIN; 27 | E.RL = { 28 | DEF: { 29 | window: MIN, 30 | max_reqs: 2000, 31 | }, 32 | GEN: { 33 | window: HOUR, 34 | max_reqs: 5, 35 | } 36 | }; 37 | E.HL_TRANSPORT_MAX_AGE = 31536000; 38 | E.SSL_OP_NO_TLSv1_1 = constants.SSL_OP_NO_TLSv1 | constants.SSL_OP_NO_TLSv1_1; 39 | -------------------------------------------------------------------------------- /lib/https_agent.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true, esnext:true*/ 3 | const https = require('https'); 4 | const util = require('util'); 5 | const E = module.exports = Https_agent; 6 | 7 | function Https_agent(options){ 8 | if (!(this instanceof Https_agent)) 9 | return new Https_agent(options); 10 | https.Agent.call(this, options); 11 | } 12 | 13 | util.inherits(E, https.Agent); 14 | 15 | E.prototype.getName = function(options){ 16 | let name = https.Agent.prototype.getName.call(this, options); 17 | if (!options.lpm_username) 18 | return options.host_port ? `${name}:${options.host_port}` : name; 19 | return `${name}:${options.lpm_username}`; 20 | }; 21 | -------------------------------------------------------------------------------- /lib/hutil_loader.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true*/ 3 | module.exports = function myLoader(source){ 4 | return '\nvar module;\n'+source 5 | .replace('var define;', '') 6 | .replace('let define;', '') 7 | .replace('define,', '') 8 | .replace(/\{\s*define\s*=[^;]+;([^}]*)\}/gm, '{$1}') 9 | .replace(/define\s*=.+/g, ';'); 10 | }; 11 | -------------------------------------------------------------------------------- /lib/lpm_conn.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // LICENSE_CODE ZON ISC 3 | 'use strict'; /*jslint node:true, esnext:true, es9: true*/ 4 | const dns = require('dns'); 5 | const http = require('http'); 6 | const os = require('os'); 7 | const zws = require('../util/ws.js'); 8 | const etask = require('../util/etask.js'); 9 | const rand = require('../util/rand.js'); 10 | const zerr = require('../util/zerr.js'); 11 | const logger = require('./logger.js').child({category: 'MNGR: lpm_conn'}); 12 | const util_lib = require('./util.js'); 13 | 14 | const Lpm_conn = etask._class(class Lpm_conn { 15 | init(){ 16 | this.ws = new zws.Client('ws://zs-lpm-conn.luminati.io:3360', { 17 | label: 'lpm_conn', 18 | agent: new http.Agent({ 19 | lookup: (hostname, opt, cb)=>{ 20 | const _opt = {family: 4, all: true, hints: opt.hints}; 21 | dns.lookup(hostname, _opt, (err, res)=>{ 22 | if (err) 23 | return cb(err); 24 | const {address, family=4} = rand.rand_element(res)||{}; 25 | if (opt.all) 26 | cb(undefined, [{address, family}]); 27 | else 28 | cb(undefined, address, family); 29 | }); 30 | }, 31 | }), 32 | ipc_client: { 33 | hello: 'post', 34 | report: 'post', 35 | }, 36 | }).on('connected', ()=>{ 37 | logger.notice('Connection established'); 38 | this.ws.ipc.hello(`from ${os.hostname()}`); 39 | }).on('error', e=>{ 40 | logger.error(zerr.e2s(e)); 41 | }).on('disconnected', ()=>{ 42 | logger.warn('Connnection failed'); 43 | }); 44 | } 45 | close(reason, code){ 46 | this.ws?.close(code||1000, reason); 47 | } 48 | connected(){ 49 | return this.ws?.connected; 50 | } 51 | *report(_this, stats){ 52 | this.on('uncaught', e=>{ 53 | logger.error('report %s', zerr.e2s(e)); 54 | util_lib.perr('error', {error: zerr.e2s(e), 55 | ctx: 'lpm_conn report'}); 56 | }); 57 | if (!_this.connected()) 58 | return; 59 | yield _this.ws.ipc.report({stats, id: os.hostname()}); 60 | } 61 | }); 62 | 63 | module.exports = Lpm_conn; 64 | -------------------------------------------------------------------------------- /lib/md5_util.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // LICENSE_CODE ZON ISC 3 | 'use strict'; /*jslint node:true, esnext:true*/ 4 | const crypto = require('crypto'); 5 | const fs = require('fs'); 6 | const path = require('path'); 7 | 8 | const E = module.exports; 9 | 10 | E.md5_files = function(files, opt = {}){ 11 | let hash = crypto.createHash('md5'); 12 | files.forEach(f=>{ 13 | if (opt.root) 14 | f = path.resolve(opt.root, f); 15 | if (fs.lstatSync(f).isFile()) 16 | hash.update(fs.readFileSync(f)); 17 | }); 18 | return hash.digest('hex'); 19 | }; 20 | -------------------------------------------------------------------------------- /lib/metrics.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // LICENSE_CODE ZON ISC 3 | 'use strict'; /*jslint node:true, esnext:true*/ 4 | 5 | function empty_metrics(){ 6 | return {sum: new Map(), avg: new Map()}; 7 | } 8 | 9 | module.exports = { 10 | type: empty_metrics(), 11 | inc(name, by=1){ 12 | const entry = this.type.sum[name] = this.type.sum[name]||{v: 0}; 13 | entry.v += by; 14 | }, 15 | avg(name, val){ 16 | const entry = this.type.avg[name] = this.type.avg[name]||{v: 0, w: 0}; 17 | entry.v += val; 18 | entry.w += 1; 19 | }, 20 | clear(){ 21 | this.type = empty_metrics(); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /lib/mixins/core.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // LICENSE_CODE ZON ISC 3 | 'use strict'; /*jslint node:true, esnext:true, es9: true*/ 4 | const _ = require('lodash4'); 5 | const {assign, keys} = Object; 6 | 7 | const MIXIN_BP = {prototype: {}, static: {}}; 8 | 9 | class Mixin_core { 10 | constructor(){ 11 | this.mixins = new Map(); 12 | } 13 | get as_array(){ 14 | return Array.from(this.mixins.keys()); 15 | } 16 | pick(labels=[]){ 17 | return labels.map(label=>this.mixins.get(label)); 18 | } 19 | new_mixin(label){ 20 | if (!label) 21 | return; 22 | this.mixins.set(label, assign({label}, _.cloneDeep(MIXIN_BP))); 23 | return this.mixins.get(label); 24 | } 25 | assign(target_class, ...req){ 26 | let pick = req.length ? this.pick(req) : this.as_array; 27 | pick.forEach(mixin=>{ 28 | keys(mixin.static).forEach(f=>target_class[f] = mixin.static[f]); 29 | assign(target_class.prototype, mixin.prototype); 30 | }); 31 | } 32 | flush(){ 33 | this.mixins.clear(); 34 | } 35 | } 36 | 37 | module.exports = new Mixin_core(); 38 | -------------------------------------------------------------------------------- /lib/smtp.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true, esnext:true*/ 3 | const events = require('events'); 4 | const logger = require('./logger.js').child({category: 'SMTP'}); 5 | const util = require('util'); 6 | 7 | module.exports = Smtp; 8 | 9 | function Smtp(serv, opt){ 10 | events.EventEmitter.call(this); 11 | this.serv = serv; 12 | this.opt = opt; 13 | } 14 | 15 | util.inherits(Smtp, events.EventEmitter); 16 | 17 | Smtp.prototype.get_host = function(){ 18 | const ips = this.opt.ips; 19 | const address = ips[Math.floor(Math.random()*ips.length)]; 20 | let [ip, port] = address.split(':'); 21 | port = Number(port)||25; 22 | return `${ip}:${port}`; 23 | }; 24 | 25 | Smtp.prototype.connect = function(socket){ 26 | const host = this.get_host(); 27 | socket.unshift(Buffer.from(`CONNECT ${host} HTTP/1.1\r\n\r\n`, 'utf8')); 28 | socket.lpm_onconnect = res=>{ 29 | if (res.headers['x-lpm-error']) 30 | { 31 | logger.error('connection error %s %s: %s', res.status_code, 32 | res.status_message, res.headers['x-lpm-error']||''); 33 | socket.end(); 34 | return false; 35 | } 36 | return true; 37 | }; 38 | socket.lpm_server = this.serv; 39 | this.serv.worker.http_server.emit('connection', socket); 40 | socket.on('error', e=>{ 41 | logger.error('error: %s', e.message); 42 | }); 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /lib/ws.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true, esnext:true*/ 3 | const logger = require('./logger.js').child({category: 'WS'}); 4 | module.exports = Ws; 5 | 6 | function Ws(){ 7 | this.connections = {}; 8 | this.next_id = 0; 9 | } 10 | 11 | Ws.prototype.handle_connection = function(socket, dst){ 12 | dst.pipe(socket).pipe(dst); 13 | const id = this.next_id++; 14 | socket._connectionId = dst._connectionId = id; 15 | this.connections[id] = {socket, dst}; 16 | const close = ()=>{ 17 | const c = this.connections[id]; 18 | if (c && c.socket.destroyed && c.dst.destroyed) 19 | delete this.connections[id]; 20 | }; 21 | socket.once('close', close); 22 | dst.once('close', close); 23 | socket.once('error', error=>{ 24 | logger.error('Ws connection error: %s', error.message); 25 | }); 26 | dst.once('error', error=>{ 27 | logger.error('Ws forward connection error: %s', error.message); 28 | }); 29 | }; 30 | 31 | Ws.prototype.stop = function(){ 32 | for (let k in this.connections) 33 | { 34 | const c = this.connections[k]; 35 | c.socket.destroy(); 36 | c.dst.destroy(); 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /publish_validate.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // LICENSE_CODE ZON 3 | 'use strict'; /*jslint node:true*/ 4 | if (!module.parent) 5 | global.zon_config_fallback = {}; 6 | require('../util/config.js'); 7 | const lpm_config = require('./util/lpm_config_static'); 8 | const etask = require('../util/etask.js'); 9 | const request = require('request'); 10 | const exec = require('../util/exec.js'); 11 | const cli = require('../util/cli.js'); 12 | const cli_opt = [ 13 | ['', 'version=VERSION', 'Version being released'], 14 | ]; 15 | cli.getopt(cli_opt, 'Usage: publish_validate.js\n\n[[OPTIONS]]\n'); 16 | 17 | const main = ()=>etask(function*(){ 18 | cli.process_args(); 19 | if (!cli.opt.version) 20 | return console.log('You need to pass --version'); 21 | const url = 'https://raw.githubusercontent.com/'+lpm_config.github_repo 22 | +'/master/package.json'; 23 | const github_res = yield etask.nfn_apply(request, [{url, json: true}]); 24 | if (github_res.body.version!=cli.opt.version) 25 | return console.log('Wrong version on github.com'); 26 | const npm_check = ['npm', 'view', '@luminati-io/luminati-proxy', 27 | 'version']; 28 | const npm_res = yield exec.sys(npm_check, {out: 'stdout'}); 29 | if (npm_res.trim()!=cli.opt.version) 30 | return console.log('Wrong version on npmjs.com'); 31 | console.log('Success'); 32 | }); 33 | 34 | if (!module.parent) 35 | main(); 36 | -------------------------------------------------------------------------------- /scripts/changelog_validate.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // LICENSE_CODE ZON 3 | 'use strict'; /*jslint node:true*/ 4 | if (!module.parent) 5 | global.zon_config_fallback = {}; 6 | require('../util/config.js'); 7 | const changelog = require('../versions.json'); 8 | 9 | const validate = _changelog=>{ 10 | const last_change = _changelog[0]; 11 | if (!['stable', 'dev'].includes(last_change.type)) 12 | throw Error(`Invalid changelog version type: ${last_change.type}`); 13 | if (!last_change.changes.length) 14 | throw Error(`Changes in the latest changelog should be specified`); 15 | const is_valid_change = 16 | c=>['star', 'sparkles', 'bug', 'boom'].includes(c.type) && c.text; 17 | if (!last_change.changes.every(is_valid_change)) 18 | throw Error('There are invalid changes in the latest changelog'); 19 | }; 20 | 21 | const main = ()=>{ 22 | try { 23 | validate(changelog); 24 | console.log('OK'); 25 | } catch(e){ 26 | console.log(`Error: ${e.message}`); 27 | } 28 | }; 29 | 30 | if (!module.parent) 31 | main(); 32 | 33 | module.exports = {t: {validate}}; 34 | -------------------------------------------------------------------------------- /scripts/stress_test.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // LICENSE_CODE ZON 3 | 'use strict'; /*jslint node:true*/ 4 | const child_process = require('child_process'); 5 | 6 | const headers = { 7 | 'x-lpm-fake': true, 8 | 'x-lpm-fake-data': 50000, 9 | }; 10 | const headers_cmd = Object.entries(headers).reduce((acc, [name, value])=> 11 | acc+`-H "${name}: ${value}" `, ' '); 12 | const opt = { 13 | c: 1500, 14 | t: 10, 15 | port: 24000, 16 | url: 'http://geo.brdtest.com/mygeo.json', 17 | }; 18 | 19 | const cmd = `ab -c ${opt.c} -t ${opt.t} -X 127.0.0.1:${opt.port} ` 20 | +`${headers_cmd} ${opt.url}`; 21 | child_process.spawn(cmd, { 22 | stdio: 'inherit', 23 | shell: true, 24 | }); 25 | -------------------------------------------------------------------------------- /src/pub/common/error_boundry.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true*/ 3 | import React from 'react'; 4 | import Pure_component from '/www/util/pub/pure_component.js'; 5 | import {perr} from '../util.js'; 6 | import {www_api} from '../common.js'; 7 | 8 | export default class Error_boundry extends Pure_component { 9 | state = {error: false, msg: null}; 10 | static getDerivedStateFromError(error){ 11 | const cp_href = www_api+'/cp/zones/lpm'; 12 | let msg = null; 13 | switch (error) 14 | { 15 | case 'duplicate_port_number': 16 | msg =

Multiple port configuration detected - 17 | please check port set up and delete duplicated port

; 18 | break; 19 | case 'cp_required': 20 | msg =

Cloud Proxy Manager can be opened only 21 | in Bright Data control panel

; 22 | break; 23 | } 24 | return {error: true, msg}; 25 | } 26 | componentDidCatch(error, info){ 27 | this.log_error(error, info); 28 | } 29 | log_error = (error, info)=>{ 30 | const {message, stack} = error; 31 | perr('react', message, info.componentStack+'\n\n'+stack); 32 | }; 33 | render(){ 34 | if (this.state.error) 35 | { 36 | return 37 |

Error

38 | {this.state.msg && this.state.msg} 39 |
; 40 | } 41 | return this.props.children; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/pub/common/nav_tabs.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true, es6:true*/ 3 | import React from 'react'; 4 | import classnames from 'classnames'; 5 | import {withRouter, Route} from 'react-router-dom'; 6 | import Tooltip from './tooltip.js'; 7 | import {T} from './i18n.js'; 8 | import '../css/nav_tabs.less'; 9 | 10 | export const Nav_tabs = ({children, narrow, set_tab, cur_tab})=> 11 |
12 | { 13 | React.Children.map(children, c=> 14 | React.cloneElement(c, {set_tab, cur_tab, narrow})) 15 | } 16 |
; 17 | 18 | export const Nav_tab = withRouter(props=>{ 19 | const {id} = props; 20 | return {({match})=>{ 21 | const active = props.cur_tab==id||!!match; 22 | const {disabled} = props; 23 | const btn_class = classnames('btn_tab', {active, disabled}); 24 | return {t=> 25 |
!disabled && props.set_tab(id)} 26 | className={btn_class}> 27 | {!props.narrow &&
} 28 |
{props.title}
29 |
30 |
31 | }; 32 | }} 33 | ; 34 | }); 35 | -------------------------------------------------------------------------------- /src/pub/common/network_types.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint browser:true, es6:true*/ 3 | 4 | // XXX azamat/krzysztof: copy pasted from lum/pub/plans.js, fix webpack loader 5 | // and import it as a whole module 6 | export const get_plan_network = plan=>{ 7 | if (plan.disable) 8 | return 'disable'; 9 | if (plan.type=='static') 10 | return plan.pool_ip_type=='static_res' && 'res_static' || 'dc'; 11 | if ((plan.type=='resident' || plan.type=='unblocker') && plan.serp) 12 | return 'serp'; 13 | if (!plan.type || plan.type=='resident') 14 | return plan.mobile && 'mobile' || 'res_rotating'; 15 | if (plan.type=='static_res') 16 | return 'res_static'; 17 | return plan.type; 18 | }; 19 | 20 | export const network_types = { 21 | dc: { 22 | label: 'Data Center', 23 | tooltip: 'Static IPs from various data centers located around ' 24 | +'the globe', 25 | }, 26 | res_rotating: { 27 | label: 'Residential', 28 | tooltip: 'P2P residential network. Millions of IPs from real ' 29 | +'devices', 30 | }, 31 | mobile: { 32 | label: 'Mobile', 33 | tooltip: '3G and 4G network from real mobile devices', 34 | }, 35 | res_static: { 36 | label: 'Static residential', 37 | tooltip: 'Static residential IPs', 38 | }, 39 | unblocker: { 40 | label: 'Unblocker', 41 | tooltip: 'Clever proxy which automatically manages IPs, headers, ' 42 | +'and network', 43 | }, 44 | serp: { 45 | label: 'SERP', 46 | tooltip: 'Send requests to various search engines', 47 | }, 48 | disable: { 49 | label: 'Disabled', 50 | tooltip: 'Disabled from control panel. Cannot be used for sending ' 51 | +'traffic', 52 | }, 53 | fallback: { 54 | label: 'Unknown zone type', 55 | tooltip: 'Unknown zone type', 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /src/pub/common/ssl_modal.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true*/ 3 | import React from 'react'; 4 | import Pure_component from '/www/util/pub/pure_component.js'; 5 | import {Loader, with_www_api} from '../common.js'; 6 | import {report_exception} from '../util.js'; 7 | import {main as Api} from '../api.js'; 8 | import {Modal} from './modals.js'; 9 | 10 | export default with_www_api(class Enable_ssl_modal extends Pure_component { 11 | state = {loading: false}; 12 | enable_ssl = ()=>{ 13 | const _this = this; 14 | this.etask(function*(){ 15 | this.on('uncaught', e=>_this.etask(function*(){ 16 | yield report_exception(e, 17 | 'ssl_modal.Enable_ssl_modal.enable_ssl'); 18 | })); 19 | _this.setState({loading: true}); 20 | yield Api.post('enable_ssl'); 21 | _this.setState({loading: false}); 22 | }); 23 | }; 24 | render(){ 25 | return 26 | 27 | 31 | 32 | ; 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /src/pub/common/toggle_on_off.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true*/ 3 | import React from 'react'; 4 | import classnames from 'classnames'; 5 | import Pure_component from '/www/util/pub/pure_component.js'; 6 | 7 | export default class Toggle_on_off extends Pure_component { 8 | render(){ 9 | const {disabled, val} = this.props; 10 | const style = disabled ? {pointerEvents: 'none'} : {}; 11 | const cls = classnames('btn', 'toggle_on_off', this.props.class_name, 12 | {toggle_on_off_active: !!val}); 13 | return ; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/pub/common/tooltip.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true*/ 3 | import React from 'react'; 4 | import Pure_component from '/www/util/pub/pure_component.js'; 5 | import bsm from '/www/util/pub/bootstrap_methods.js'; 6 | import $ from 'jquery'; 7 | import '../css/tooltip.less'; 8 | 9 | export default class Tooltip extends Pure_component { 10 | componentDidMount(){ 11 | if (!this.ref) 12 | return; 13 | $(this.ref).tooltip(); 14 | } 15 | componentWillUnmount(){ 16 | $(this.ref).tooltip(bsm.destroy); 17 | } 18 | componentDidUpdate(){ 19 | $(this.ref).attr('title', this.props.title).tooltip(bsm.fix_title); 20 | } 21 | on_mouse_leave(){ 22 | if (!this.ref) 23 | return; 24 | $(this.ref).tooltip('hide'); 25 | } 26 | set_ref(e){ this.ref = e; } 27 | render(){ 28 | if (this.props.children==undefined) 29 | return null; 30 | if (!this.props.title) 31 | return this.props.children; 32 | const classes = `tooltip har_tooltip ${this.props.className||''}`; 33 | const props = { 34 | 'data-toggle': 'tooltip', 35 | 'data-placement': this.props.placement||'top', 36 | 'data-container': 'body', 37 | 'data-html': true, 38 | 'data-template': ``, 43 | title: this.props.title, 44 | ref: this.set_ref.bind(this), 45 | onMouseLeave: this.on_mouse_leave.bind(this), 46 | }; 47 | return React.Children.map(this.props.children, c=>{ 48 | if (typeof c=='number') 49 | c = ''+c; 50 | if (typeof c=='string' || typeof c=='object' && c.type.name=='T') 51 | return React.createElement('span', props, c); 52 | return React.cloneElement(c, props); 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/pub/common/warnings_modal.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true*/ 3 | import React from 'react'; 4 | import {T} from './i18n.js'; 5 | import {Modal} from './modals.js'; 6 | import {Warnings} from '../common.js'; 7 | 8 | export default function Warnings_modal(props){ 9 | return {t=> 10 | 12 | 13 | 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /src/pub/cp_ipc.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint browser:true, react:true, es6:true*/ 3 | import _ from 'lodash4'; 4 | import zurl from '../../util/url.js'; 5 | 6 | const url_o = zurl.parse(document.location.href); 7 | const qs_o = zurl.qs_parse((url_o.search||'').substr(1)); 8 | const parent_origin = qs_o.parent || location.ancestorOrigins && 9 | location.ancestorOrigins.length && location.ancestorOrigins[0]; 10 | 11 | class CP_ipc { 12 | static listen(type, callback){ 13 | if (!parent_origin) 14 | return _.noop; 15 | const handler = event=>{ 16 | let data; 17 | if (event.origin!=parent_origin || !event.data) 18 | return; 19 | if (typeof event.data == 'string') 20 | { 21 | try { 22 | data = JSON.parse(event.data); 23 | } catch(e){ 24 | return console.error('Can not parse message from parent', 25 | parent_origin, event.data, e.message); 26 | } 27 | } 28 | else 29 | data = event.data; 30 | if (data.type==type) 31 | callback(_.omit(data||{}, ['type'])); 32 | }; 33 | window.addEventListener('message', handler); 34 | return ()=>window.removeEventListener('message', handler); 35 | } 36 | static post(type, payload={}){ 37 | if (!parent_origin) 38 | return false; 39 | if (!type) 40 | return console.error('Can not post cp message without type'); 41 | let message; 42 | try { 43 | message = JSON.stringify(Object.assign({type}, payload)); 44 | } catch(e){ 45 | return console.error('Can not stringify message', origin, type, 46 | payload, e.message); 47 | } 48 | window.parent.postMessage(message, parent_origin); 49 | } 50 | } 51 | 52 | export default CP_ipc; 53 | -------------------------------------------------------------------------------- /src/pub/cpu_warning.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true, es6:true*/ 3 | import React from 'react'; 4 | import classnames from 'classnames'; 5 | import ws from './ws.js'; 6 | import {T} from './common/i18n.js'; 7 | 8 | class Cpu_warning extends React.Component { 9 | constructor(props){ 10 | super(props); 11 | this.state = {usage: 0, level: null}; 12 | } 13 | componentDidMount(){ 14 | ws.addEventListener('cpu_usage', this.on_cpu_usage); 15 | } 16 | componentWillUnmount(){ 17 | ws.removeEventListener('cpu_usage', this.on_cpu_usage); 18 | } 19 | shouldComponentUpdate(_, next_state){ 20 | return this.state.usage!=next_state.usage; 21 | } 22 | on_cpu_usage = ({data})=>this.setState({ 23 | usage: data.usage, 24 | level: data.level 25 | }); 26 | render(){ 27 | const {usage, level} = this.state; 28 | if (!level) 29 | return null; 30 | return
31 | 32 | High CPU usage: {usage}% 33 |
; 34 | } 35 | } 36 | 37 | export default Cpu_warning; 38 | -------------------------------------------------------------------------------- /src/pub/css/api_url_modal.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .api_url_modal { 3 | .desc { margin-right: 10px; } 4 | .btn_support { 5 | position: relative; 6 | width: 280px; 7 | margin-bottom: 5px; 8 | .icon { 9 | margin-right: 10px; 10 | position: absolute; 11 | left: 10px; 12 | top: 0; 13 | bottom: 0; 14 | margin-top: auto; 15 | margin-bottom: auto; 16 | height: 16px; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/pub/css/config.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .config { 3 | height: 100%; 4 | font-size: 14px; 5 | padding: 0 15px; 6 | .btn { width: 140px; } 7 | .nav_buttons { 8 | position: absolute; 9 | z-index: 10; 10 | right: 15px; 11 | top: 15px; 12 | white-space: nowrap; 13 | flex: 1; 14 | .btn:last-child { margin-right: 0; } 15 | } 16 | .code_panel { 17 | .panel_body { 18 | background-color: @light_grey; 19 | position: relative; 20 | padding: 1px; 21 | .CodeMirror { 22 | flex: auto; 23 | display: flex; 24 | flex-direction: column; 25 | .CodeMirror-scroll { flex: auto; } 26 | &.cm-s-default { 27 | padding: 5px; 28 | background-color: @light_grey; 29 | } 30 | } 31 | .nav_buttons { right: 25px; } 32 | } 33 | } 34 | .code_panel.editable { 35 | border-color: @first_color; 36 | .panel_body { 37 | background-color: transparent; 38 | .CodeMirror.cm-s-default { background-color: white; } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/pub/css/nav.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .nav_left { 3 | .menu { 4 | z-index: 10; 5 | top: 60px; 6 | position: fixed; 7 | width: 50px; 8 | .menu_item { 9 | height: 40px; 10 | position: relative; 11 | cursor: pointer; 12 | &.active { 13 | background-color: @cp_dark; 14 | cursor: default; 15 | .text { color: @first_color; } 16 | } 17 | &.active, &:hover { opacity: 1; } 18 | } 19 | .icon { 20 | padding: 0; 21 | width: 20px; 22 | height: 20px; 23 | position: relative; 24 | top: 10px; 25 | left: 15px; 26 | } 27 | .howto { background-image: url('img/howto.svg'); } 28 | .proxies { background-image: url('img/proxies.svg'); } 29 | .overview { background-image: url('img/proxies.svg'); } 30 | .logs { background-image: url('img/stats.svg'); } 31 | .proxy_tester { background-image: url('img/tester.svg'); } 32 | .tools { background-image: url('img/tools.svg'); } 33 | .config { background-image: url('img/tools.svg'); } 34 | .general_config { background-image: url('img/config.svg'); } 35 | .api { background-image: url('img/ic_api.svg'); } 36 | .faq { background-image: url('img/ic_faq.svg'); } 37 | &.lock { 38 | pointer-events: none; 39 | .menu_item { 40 | opacity: 0.4; 41 | cursor: default; 42 | } 43 | } 44 | } 45 | .menu_filler { 46 | border-right: 1px solid @cp_border_dark; 47 | background-color: white; 48 | height: 100%; 49 | position: fixed; 50 | width: 50px; 51 | z-index: 1; 52 | } 53 | .footer { 54 | z-index: 5; 55 | font-size: 13px; 56 | color: @link; 57 | width: 50px; 58 | position: fixed; 59 | bottom: 100px; 60 | a { margin: 3px; } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/pub/css/notif_center.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .notif_modal { 3 | .notifs { 4 | h4.no_messages { text-align: center; } 5 | .message { 6 | width: 100%; 7 | background-color: @light_grey; 8 | border-radius: 2px; 9 | padding: 15px; 10 | margin: 10px 0; 11 | .subject { 12 | color: @first_color; 13 | font-size: 16px; 14 | font-weight: bold 15 | } 16 | .text { font-size: 13px; } 17 | &.unread { background-color: @x_light; } 18 | &.clickable { cursor: pointer; } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/pub/css/proxies.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .proxies { 3 | &.nav_header { padding: 0 15px 10px; } 4 | .proxies_panel { 5 | padding-bottom: 0; 6 | } 7 | .proxies_actions { 8 | visibility: hidden; 9 | display: grid; 10 | grid-template-columns: repeat(3, 30%); 11 | .action_icon { width: 16px; height:16px; } 12 | .remove { grid-column: 1; } 13 | .duplicate { grid-column: 2; } 14 | .refresh { grid-column: 3; } 15 | } 16 | .proxies_actions_local { 17 | visibility: hidden; 18 | display: grid; 19 | grid-template-columns: 33% 33% 33%; 20 | .action_icon { width: 16px; height:16px; } 21 | .remove { grid-column: 1; } 22 | .duplicate { grid-column: 2; } 23 | .refresh { grid-column: 3; } 24 | } 25 | .port_cell { 26 | &.master { 27 | flex-direction: row; 28 | display: flex; 29 | } 30 | &.multiplied { 31 | padding: 10px; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/pub/css/proxy_add.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .proxy_form { 3 | max-height: 500px; 4 | &.animated { 5 | animation-duration: 600ms; 6 | -webkit-animation-duration: 600ms; 7 | } 8 | .step_title { 9 | padding: 2px 0px 0px; 10 | font-size: 18px; 11 | font-weight: 600; 12 | } 13 | .step_content { 14 | margin-top: 0; 15 | max-height: 0; 16 | visibility: hidden; 17 | &.shown { 18 | margin-top: 10px; 19 | max-height: initial; 20 | visibility: visible; 21 | } 22 | .note { margin-bottom: 10px; } 23 | } 24 | } 25 | .add_proxy_modal.modal .modal-content { 26 | select { width: auto; } 27 | .nav_tabs { margin-bottom: 15px; } 28 | .ext_proxy { 29 | textarea { width: 100%; } 30 | .json_error { 31 | position: relative; 32 | color: #eb3a28; 33 | font-size: 13px; 34 | margin-left: 3px; 35 | line-height: 2; 36 | } 37 | .json_example { 38 | margin-left: 3px; 39 | position: relative; 40 | line-height: 1; 41 | font-size: 13px; 42 | } 43 | } 44 | .field { 45 | display: flex; 46 | margin-bottom: 10px; 47 | &:last-child { margin-bottom: 0; } 48 | .field_header { 49 | display: flex; 50 | align-items: center; 51 | margin-right: 12px; 52 | .icon { 53 | width: 26px; 54 | height: 26px; 55 | margin-right: 5px; 56 | } 57 | .zone_icon { background: url(/img/zone_icon.png); } 58 | .preset_icon { background: url(/img/preset_icon.png); } 59 | h4 { 60 | color: @first_color; 61 | font-weight: bold; 62 | font-size: 17px; 63 | letter-spacing: 0.5px; 64 | } 65 | } 66 | } 67 | .preview { 68 | border: solid 1px @grey; 69 | padding: 5px 10px; 70 | border-radius: 4px; 71 | .header { 72 | height: 30px; 73 | font-size: 16px; 74 | font-weight: bold; 75 | } 76 | .desc { 77 | font-size: 14px; 78 | line-height: 1.3; 79 | margin-bottom: 12px; 80 | } 81 | } 82 | } 83 | .created_port { 84 | &_number { 85 | display: flex; 86 | align-items: center; 87 | column-gap: 5px; 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /src/pub/css/proxy_blank.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .no_proxies { 3 | text-align: center; 4 | .btn_add_port { margin: 20px auto; } 5 | } 6 | -------------------------------------------------------------------------------- /src/pub/css/proxy_tester.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .proxy_tester { 3 | flex: 1; 4 | select, input { width: 100% !important; } 5 | .title_value_pairs { 6 | font-size: 14px; 7 | .pair { 8 | display: flex; 9 | .title { flex: 1; } 10 | .value { flex: 1; } 11 | } 12 | } 13 | .har_preview { 14 | margin-bottom: 10px; 15 | border: 1px solid #cdcdcd; 16 | min-height: 300px; 17 | z-index: 2000; 18 | } 19 | .panel { 20 | &.request { 21 | .request_params { 22 | display: flex; 23 | margin-bottom: 10px; 24 | } 25 | .field { 26 | &:first-child { margin-left: 0; } 27 | &:last-child { margin-right: 0; } 28 | margin: 0 5px; 29 | .title { 30 | font-size: 14px; 31 | margin-bottom: 3px; 32 | margin-left: 2px; 33 | } 34 | &.url { flex: 1; } 35 | } 36 | .headers { 37 | .header_line { 38 | display: flex; 39 | align-items: center; 40 | margin: 5px 0; 41 | &:first-child { margin-top: 0; } 42 | &:last-child { margin-bottom: 10px; } 43 | button { min-width: 140px; } 44 | .header_input { 45 | margin-right: 10px; 46 | flex: 1; 47 | } 48 | .value_input { 49 | margin-right: 5px; 50 | flex: 2; 51 | } 52 | .action_icons { 53 | width: 45px; 54 | .add_header { margin-left: 5px; } 55 | } 56 | } 57 | } 58 | .footer_buttons { 59 | margin-top: 10px; 60 | .btn { margin: 0; } 61 | } 62 | } 63 | &.body { 64 | .panel.code { 65 | font-size: 14px; 66 | margin-bottom: 0; 67 | .panel_body { 68 | overflow: auto; 69 | max-height: 400px; 70 | padding: 5px; 71 | span { word-wrap: break-word; } 72 | } 73 | } 74 | } 75 | &.info { 76 | .title_value_pairs .pair .value { text-align: right; } 77 | } 78 | &.response { 79 | .title_value_pairs .pair { 80 | .key { min-width: 160px; } 81 | .value { word-break: break-all; } 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/pub/css/report_bug.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .report_bug { 3 | .desc { margin: 10px 0; } 4 | .modal-footer { 5 | button.ok { margin-right: 0; } 6 | } 7 | .email_field { 8 | display: flex; 9 | align-items: center; 10 | span { width: 200px; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/pub/css/settings.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .settings { 3 | padding: 0 15px; 4 | .settings_form { 5 | .field_row { 6 | align-items: baseline; 7 | .desc { 8 | width: 170px; 9 | margin-right: 5px; 10 | white-space: nowrap; 11 | } 12 | } 13 | } 14 | .cp_panel { 15 | height: 100%; 16 | overflow: auto; 17 | } 18 | &.vbox { overflow-y: hidden; } 19 | } 20 | .logs_settings_modal { 21 | &_tabs{ 22 | margin-top: 10px; 23 | margin-bottom: 10px; 24 | .inputs_container { 25 | display: flex; 26 | input { 27 | width: 100%; 28 | } 29 | margin-top: 10px; 30 | .aggr_url { 31 | flex: 1; 32 | margin-right: 10px; 33 | width: 100%; 34 | } 35 | .input_full { 36 | flex: 1; 37 | width: 100%; 38 | } 39 | .btn_test { 40 | min-width: 80px; 41 | } 42 | .input_main{ 43 | width: 70%; 44 | &_sub { 45 | width: 30%; 46 | } 47 | } 48 | .input_second{ 49 | margin-left: 10px; 50 | width: 30%; 51 | } 52 | .input_half{ 53 | width: 50%; 54 | &_sub { 55 | width: 50%; 56 | margin-left: 10px; 57 | } 58 | } 59 | } 60 | } 61 | .use_limit { 62 | align-items: center; 63 | display: flex; 64 | margin-top: 10px; 65 | &_tooltip { 66 | margin-right: 15px; 67 | font-size: 15px; 68 | } 69 | } 70 | } 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/pub/css/tooltip.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .tooltip { 3 | z-index: 10000; 4 | } 5 | .tooltip.in { 6 | opacity: 1; 7 | } 8 | .tooltip-proxy-status .tooltip-inner, .tooltip-default .tooltip-inner, 9 | .tooltip .tooltip-inner { 10 | word-break: break-word; 11 | max-width: 315px; 12 | border: solid 1px @tooltip; 13 | background: white; 14 | color: @first_color; 15 | font-size: 14px; 16 | text-align: left; 17 | ul { padding-left: 20px; padding-top: 10px; } 18 | } 19 | .tooltip.har_tooltip { 20 | .tooltip-inner { 21 | position: relative; 22 | max-width: 550px; 23 | background: hsl(0, 0%, 95%); 24 | border-radius: 2px; 25 | color: hsl(0, 0%, 20%); 26 | padding: 5px 8px; 27 | line-height: 14px; 28 | align-items: center; 29 | -webkit-filter: drop-shadow(0 1px 2px hsla(0, 0%, 0%, 0.3)); 30 | border: 1px solid hsla(0, 0%, 0%, 0.1); 31 | background-clip: padding-box; 32 | box-sizing: border-box; 33 | transition: visibility 0s 100ms, opacity 150ms cubic-bezier(0, 0, .2, 1); 34 | z-index: 20001; 35 | text-overflow: ellipsis; 36 | overflow: hidden; 37 | font-size: 12px; 38 | font-family: Roboto, Ubuntu, Arial, sans-serif; 39 | } 40 | .tooltip-arrow { display: none; } 41 | &.top { 42 | .tooltip-inner { top: 7px; } 43 | } 44 | &.bottom { 45 | margin-top: 0; 46 | padding-top: 0; 47 | margin-left: 9px; 48 | .tooltip-inner { top: 4px; } 49 | } 50 | &.left { margin-left: 0; } 51 | } 52 | .tooltip.wide .tooltip-inner { max-width: 600px; } 53 | .tooltip.top .tooltip-arrow { border-top-color: @tooltip; } 54 | .tooltip.bottom .tooltip-arrow { border-bottom-color: @tooltip; } 55 | -------------------------------------------------------------------------------- /src/pub/css/whitelist_ips.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .whitelist_ips { 3 | padding-top: 70px; 4 | max-width: 800px; 5 | margin: auto; 6 | .user_choice { 7 | display: flex; 8 | .user { 9 | cursor: pointer; 10 | padding: 30px; 11 | width: 240px; 12 | height: 280px; 13 | margin-right: 20px; 14 | outline: 1px solid @grey_border; 15 | &.active { 16 | outline: 2px solid @first_color; 17 | } 18 | .img_wrapper { 19 | width: 88px; 20 | height: 88px; 21 | margin: 0 auto 30px; 22 | .img { 23 | width: 100%; 24 | height: 100%; 25 | } 26 | .admin { background-image: url(img/ic_admin.svg); } 27 | .guest { background-image: url(img/ic_guest.svg); } 28 | } 29 | .user_title { 30 | margin-bottom: 12px; 31 | font-size: 20px; 32 | font-weight: bold; 33 | line-height: 1.2; 34 | } 35 | .user_desc { 36 | font-size: 14px; 37 | line-height: 1.2; 38 | } 39 | } 40 | } 41 | .whitelist_header { 42 | h3 { font-size: 30px; } 43 | margin-bottom: 30px; 44 | margin-top: 30px; 45 | text-align: left; 46 | } 47 | .steps { 48 | margin-top: 50px; 49 | h3 { font-size: 17px; } 50 | .instructions { margin: 15px 10px; } 51 | } 52 | .nav_top { 53 | background-color: white; 54 | .logo_big { 55 | background: url(img/brd_logo_large.svg) no-repeat; 56 | width: 158px; 57 | height: 33px; 58 | margin: 7px; 59 | display: block; 60 | } 61 | .version { 62 | position: relative; 63 | top: 30px; 64 | left: -46px; 65 | font-size: 9px; 66 | font-weight: bold; 67 | opacity: 0.5; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/pub/css/zone_desc.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .zone_settings { 3 | cursor: default !important; 4 | .pair { 5 | display: flex; 6 | .title { 7 | margin-right: 5px; 8 | font-weight: 600; 9 | } 10 | .val { 11 | display: flex; 12 | align-items: center; 13 | } 14 | } 15 | .lit { 16 | line-height: 1.9; 17 | padding: 0 6px; 18 | margin-right: 3px; 19 | background-color: #e1e9ed; 20 | color: inherit; 21 | font-size: 11px; 22 | border-radius: 3px; 23 | } 24 | .perm_icon { 25 | width: 18px; 26 | height: 18px; 27 | float: left; 28 | margin: 2px 4px 0; 29 | background-repeat: no-repeat; 30 | background-size: contain; 31 | &.country { background-image: url(/img/country.svg); } 32 | &.state { background-image: url(/img/state.svg); } 33 | &.data_center { background-image: url(/img/data_center.svg); } 34 | &.asn { background-image: url(/img/asn.svg); } 35 | &.city { background-image: url(/img/city.svg); } 36 | &.vip { background-image: url(/img/g_ip.svg); } 37 | &.residential { background-image: url(/img/residential.svg); } 38 | &.static_res { background-image: url(/img/static_res.svg); } 39 | &.zip { background-image: url(/img/zipcode.svg); } 40 | &.mobile { 41 | width: 14px; 42 | background-image: url(/img/mobile.svg); 43 | } 44 | } 45 | .domains_list { 46 | display: flex; 47 | flex-wrap: wrap; 48 | margin-left: 13px; 49 | .domain { 50 | .lit(); 51 | margin-bottom: 3px; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/pub/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Proxy Manager 6 | 8 | 9 | 10 | 13 | 14 | 15 | 16 |
17 |
18 |
19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/pub/logs.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true, es6:true*/ 3 | import React from 'react'; 4 | import Har_viewer from './har_viewer.js'; 5 | import {withRouter} from 'react-router-dom'; 6 | import zurl from '../../util/url.js'; 7 | import Pure_component from '/www/util/pub/pure_component.js'; 8 | import './css/logs.less'; 9 | 10 | export const Logs = withRouter(class Logs extends Pure_component { 11 | state = {cur_tab: 'har'}; 12 | set_tab = id=>this.setState({cur_tab: id}); 13 | render(){ 14 | const {location} = this.props; 15 | const qs_o = zurl.qs_parse((location.search||'').substr(1)); 16 | return
18 | 19 |
; 20 | } 21 | }); 22 | 23 | export const Dock_logs = ()=> 24 |
25 | 26 |
; 27 | -------------------------------------------------------------------------------- /src/pub/proxy_blank.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true, es6:true*/ 3 | import React from 'react'; 4 | import $ from 'jquery'; 5 | import Tooltip from './common/tooltip.js'; 6 | import {T} from './common/i18n.js'; 7 | import ws from './ws.js'; 8 | import './css/proxy_blank.less'; 9 | 10 | const open_modal = ()=>{ 11 | ws.post_event('Start Click'); 12 | $('#add_new_proxy_modal').modal('show'); 13 | }; 14 | 15 | const Proxy_blank = ()=> 16 |
17 |
18 | 19 | 23 | 24 |
25 |
; 26 | 27 | export default Proxy_blank; 28 | -------------------------------------------------------------------------------- /src/pub/ws.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint browser:true, react:true, es6:true*/ 3 | import _ from 'lodash4'; 4 | import {EventTarget} from 'event-target-shim'; 5 | import setdb from '../../util/setdb.js'; 6 | import zws from '../../util/ws.js'; 7 | import {get_location_port} from './util.js'; 8 | 9 | class Ws_wrapper extends EventTarget { 10 | constructor(){ 11 | super(); 12 | this.url = location.hostname; 13 | this.port = get_location_port(); 14 | this.protocol = location.protocol=='https:' ? 'wss' : 'ws'; 15 | } 16 | create_socket(){ 17 | const ws_url = `${this.protocol}://${this.url}:${this.port}`; 18 | const _this = this; 19 | this.socket = new zws.Client(ws_url, { 20 | mux: {use_ack: true}, 21 | label: 'pmgr_ui', 22 | ipc_client: { 23 | hello: 'post', 24 | ui_event: 'post', 25 | }, 26 | }) 27 | .on('connected', ()=>console.log('pmgr ws connected')) 28 | .on('disconnected', ()=>console.log('pmgr ws disconnected')) 29 | .on('json', data=>{ 30 | const event = new MessageEvent(data.msg || 'message', {data}); 31 | _this.dispatchEvent(event); 32 | _this.global_handler(event); 33 | }); 34 | } 35 | connect(){ 36 | if (!this.socket || !this.socket.connected) 37 | this.create_socket(); 38 | } 39 | disconnect(){ 40 | if (!this.socket || !this.socket.connected) 41 | return; 42 | this.socket.close(); 43 | } 44 | global_handler(event){ 45 | if (!event.data || !event.data.msg!='update_path') 46 | return; 47 | const {path, payload} = event.data; 48 | if (path.endsWith('.remove') || path.endsWith('.add')) 49 | return setdb.emit('ws.'+path, payload); 50 | setdb.set('ws.'+path, payload); 51 | } 52 | post_event(name, payload={}){ 53 | if (!this.socket || !this.socket.connected) 54 | return void console.error('pmgr ws not connected', name); 55 | if (!name || !_.isString(name)) 56 | return void console.error('pmgr ws not valid event name', name); 57 | this.socket.ipc.ui_event(Object.assign(payload, 58 | {name, cred: document.cookie})); 59 | } 60 | } 61 | 62 | export default new Ws_wrapper(); 63 | -------------------------------------------------------------------------------- /src/pub2/common/error_boundry.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true*/ 3 | import React from 'react'; 4 | import Pure_component from '/www/util/pub/pure_component.js'; 5 | import {perr} from '../util.js'; 6 | import {www_api} from '../common.js'; 7 | 8 | export default class Error_boundry extends Pure_component { 9 | state = {error: false, msg: null}; 10 | static getDerivedStateFromError(error){ 11 | const cp_href = www_api+'/cp/zones/lpm'; 12 | let msg = null; 13 | switch (error) 14 | { 15 | case 'duplicate_port_number': 16 | msg =

Multiple port configuration detected - 17 | please check port set up and delete duplicated port

; 18 | break; 19 | case 'cp_required': 20 | msg =

Cloud Proxy Manager can be opened only 21 | in Bright Data control panel

; 22 | break; 23 | } 24 | return {error: true, msg}; 25 | } 26 | componentDidCatch(error, info){ 27 | this.log_error(error, info); 28 | } 29 | log_error = (error, info)=>{ 30 | const {message, stack} = error; 31 | perr('react', message, info.componentStack+'\n\n'+stack); 32 | }; 33 | render(){ 34 | if (this.state.error) 35 | { 36 | return 37 |

Error

38 | {this.state.msg && this.state.msg} 39 |
; 40 | } 41 | return this.props.children; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/pub2/common/exit_confirm_modal.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true, es9:true*/ 3 | import React, {useState, useEffect, useCallback} from 'react'; 4 | import _ from 'lodash4'; 5 | import {withRouter} from 'react-router-dom'; 6 | import {Modal} from 'uikit'; 7 | 8 | const Exit_confirm_modal = withRouter(({should_show, history})=>{ 9 | const [show, set_show] = useState(false); 10 | const [last_change, set_last_change] = useState({}); 11 | const confirm = useCallback(()=>{ 12 | if (!_.isEmpty(last_change)) 13 | history.push(last_change); 14 | }, [last_change]); 15 | useEffect(()=>{ 16 | const unblock = history.block(change=>{ 17 | if (!should_show || show) 18 | return true; 19 | set_last_change(change); 20 | set_show(true); 21 | return false; 22 | }); 23 | return ()=>unblock(); 24 | }, [should_show, show]); 25 | return set_show(false)} 29 | title="You have unsaved changes" 30 | content={

Are you sure you want to exit?

} 31 | shadow="sm" 32 | size="md" 33 | />; 34 | }); 35 | Exit_confirm_modal.displayName = 'Exit_confirm_modal'; 36 | 37 | export default Exit_confirm_modal; 38 | -------------------------------------------------------------------------------- /src/pub2/common/nav_tabs.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true, es6:true*/ 3 | import React from 'react'; 4 | import classnames from 'classnames'; 5 | import {withRouter, Route} from 'react-router-dom'; 6 | import Tooltip from './tooltip.js'; 7 | import {T} from './i18n.js'; 8 | import '../css/nav_tabs.less'; 9 | 10 | export const Nav_tabs = ({children, narrow, set_tab, cur_tab})=> 11 |
12 | { 13 | React.Children.map(children, c=> 14 | React.cloneElement(c, {set_tab, cur_tab, narrow})) 15 | } 16 |
; 17 | 18 | export const Nav_tab = withRouter(props=>{ 19 | const {id} = props; 20 | return {({match})=>{ 21 | const active = props.cur_tab==id||!!match; 22 | const {disabled} = props; 23 | const btn_class = classnames('btn_tab', {active, disabled}); 24 | return {t=> 25 |
!disabled && props.set_tab(id)} 26 | className={btn_class}> 27 | {!props.narrow &&
} 28 |
{props.title}
29 |
30 |
31 | }; 32 | }} 33 | ; 34 | }); 35 | -------------------------------------------------------------------------------- /src/pub2/common/network_types.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint browser:true, es6:true*/ 3 | 4 | // XXX azamat/krzysztof: copy pasted from lum/pub/plans.js, fix webpack loader 5 | // and import it as a whole module 6 | export const get_plan_network = plan=>{ 7 | if (plan.disable) 8 | return 'disable'; 9 | if (plan.type=='static') 10 | return plan.pool_ip_type=='static_res' && 'res_static' || 'dc'; 11 | if ((plan.type=='resident' || plan.type=='unblocker') && plan.serp) 12 | return 'serp'; 13 | if (!plan.type || plan.type=='resident') 14 | return plan.mobile && 'mobile' || 'res_rotating'; 15 | if (plan.type=='static_res') 16 | return 'res_static'; 17 | return plan.type; 18 | }; 19 | 20 | export const network_types = { 21 | dc: { 22 | label: 'Data Center', 23 | tooltip: 'Static IPs from various data centers located around ' 24 | +'the globe', 25 | }, 26 | res_rotating: { 27 | label: 'Residential', 28 | tooltip: 'P2P residential network. Millions of IPs from real ' 29 | +'devices', 30 | }, 31 | mobile: { 32 | label: 'Mobile', 33 | tooltip: '3G and 4G network from real mobile devices', 34 | }, 35 | res_static: { 36 | label: 'Static residential', 37 | tooltip: 'Static residential IPs', 38 | }, 39 | unblocker: { 40 | label: 'Unblocker', 41 | tooltip: 'Clever proxy which automatically manages IPs, headers, ' 42 | +'and network', 43 | }, 44 | serp: { 45 | label: 'SERP', 46 | tooltip: 'Send requests to various search engines', 47 | }, 48 | disable: { 49 | label: 'Disabled', 50 | tooltip: 'Disabled from control panel. Cannot be used for sending ' 51 | +'traffic', 52 | }, 53 | fallback: { 54 | label: 'Unknown zone type', 55 | tooltip: 'Unknown zone type', 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /src/pub2/common/ssl_modal.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true*/ 3 | import React from 'react'; 4 | import Pure_component from '/www/util/pub/pure_component.js'; 5 | import {Loader, with_www_api} from '../common.js'; 6 | import {report_exception} from '../util.js'; 7 | import {main as Api} from '../api.js'; 8 | import {Modal} from './modals.js'; 9 | 10 | export default with_www_api(class Enable_ssl_modal extends Pure_component { 11 | state = {loading: false}; 12 | enable_ssl = ()=>{ 13 | const _this = this; 14 | this.etask(function*(){ 15 | this.on('uncaught', e=>_this.etask(function*(){ 16 | yield report_exception(e, 17 | 'ssl_modal.Enable_ssl_modal.enable_ssl'); 18 | })); 19 | _this.setState({loading: true}); 20 | yield Api.post('enable_ssl'); 21 | _this.setState({loading: false}); 22 | }); 23 | }; 24 | render(){ 25 | return 26 | 27 | 31 | 32 | ; 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /src/pub2/common/tab_group.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true, es6:true*/ 3 | import React from 'react'; 4 | import {Tab} from 'uikit'; 5 | import classnames from 'classnames'; 6 | import '../css/tab_group.less'; 7 | 8 | const Tab_group = props=>{ 9 | const {on_click, tabs, selected, variant='main', wide} = props; 10 | const cn = classnames({wide}); 11 | return 12 | {tabs.map((tab, i)=> 13 | )} 14 | ; 15 | }; 16 | Tab_group.displayName = 'Tab_group'; 17 | 18 | export default Tab_group; 19 | -------------------------------------------------------------------------------- /src/pub2/common/toggle_on_off.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true*/ 3 | import React from 'react'; 4 | import classnames from 'classnames'; 5 | import Pure_component from '/www/util/pub/pure_component.js'; 6 | 7 | export default class Toggle_on_off extends Pure_component { 8 | render(){ 9 | const {disabled, val} = this.props; 10 | const style = disabled ? {pointerEvents: 'none'} : {}; 11 | const cls = classnames('btn', 'toggle_on_off', this.props.class_name, 12 | {toggle_on_off_active: !!val}); 13 | return ; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/pub2/common/tooltip.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true*/ 3 | import React from 'react'; 4 | import Pure_component from '/www/util/pub/pure_component.js'; 5 | import bsm from '/www/util/pub/bootstrap_methods.js'; 6 | import $ from 'jquery'; 7 | import '../css/tooltip.less'; 8 | 9 | export default class Tooltip extends Pure_component { 10 | componentDidMount(){ 11 | if (!this.ref) 12 | return; 13 | $(this.ref).tooltip(); 14 | } 15 | componentWillUnmount(){ 16 | $(this.ref).tooltip(bsm.destroy); 17 | } 18 | componentDidUpdate(){ 19 | $(this.ref).attr('title', this.props.title).tooltip(bsm.fix_title); 20 | } 21 | on_mouse_leave(){ 22 | if (!this.ref) 23 | return; 24 | $(this.ref).tooltip('hide'); 25 | } 26 | set_ref(e){ this.ref = e; } 27 | render(){ 28 | if (this.props.children==undefined) 29 | return null; 30 | if (!this.props.title) 31 | return this.props.children; 32 | const classes = `tooltip har_tooltip ${this.props.className||''}`; 33 | const props = { 34 | 'data-toggle': 'tooltip', 35 | 'data-placement': this.props.placement||'top', 36 | 'data-container': 'body', 37 | 'data-html': true, 38 | 'data-template': ``, 43 | title: this.props.title, 44 | ref: this.set_ref.bind(this), 45 | onMouseLeave: this.on_mouse_leave.bind(this), 46 | }; 47 | return React.Children.map(this.props.children, c=>{ 48 | if (typeof c=='number') 49 | c = ''+c; 50 | if (typeof c=='string' || typeof c=='object' && c.type.name=='T') 51 | return React.createElement('span', props, c); 52 | return React.cloneElement(c, props); 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/pub2/common/warnings_modal.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true*/ 3 | import React from 'react'; 4 | import {T} from './i18n.js'; 5 | import {Modal} from './modals.js'; 6 | import {Warnings} from '../common.js'; 7 | 8 | export default function Warnings_modal(props){ 9 | return {t=> 10 | 12 | 13 | 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /src/pub2/cp_ipc.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint browser:true, react:true, es6:true*/ 3 | import _ from 'lodash4'; 4 | import zurl from '../../util/url.js'; 5 | 6 | const url_o = zurl.parse(document.location.href); 7 | const qs_o = zurl.qs_parse((url_o.search||'').substr(1)); 8 | const parent_origin = qs_o.parent || location.ancestorOrigins && 9 | location.ancestorOrigins.length && location.ancestorOrigins[0]; 10 | 11 | class CP_ipc { 12 | static listen(type, callback){ 13 | if (!parent_origin) 14 | return _.noop; 15 | const handler = event=>{ 16 | let data; 17 | if (event.origin!=parent_origin || !event.data) 18 | return; 19 | if (typeof event.data == 'string') 20 | { 21 | try { 22 | data = JSON.parse(event.data); 23 | } catch(e){ 24 | return console.error('Can not parse message from parent', 25 | parent_origin, event.data, e.message); 26 | } 27 | } 28 | else 29 | data = event.data; 30 | if (data.type==type) 31 | callback(_.omit(data||{}, ['type'])); 32 | }; 33 | window.addEventListener('message', handler); 34 | return ()=>window.removeEventListener('message', handler); 35 | } 36 | static post(type, payload={}){ 37 | if (!parent_origin) 38 | return false; 39 | if (!type) 40 | return console.error('Can not post cp message without type'); 41 | let message; 42 | try { 43 | message = JSON.stringify(Object.assign({type}, payload)); 44 | } catch(e){ 45 | return console.error('Can not stringify message', origin, type, 46 | payload, e.message); 47 | } 48 | window.parent.postMessage(message, parent_origin); 49 | } 50 | } 51 | 52 | export default CP_ipc; 53 | -------------------------------------------------------------------------------- /src/pub2/cpu_warning.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true, es6:true*/ 3 | import React from 'react'; 4 | import classnames from 'classnames'; 5 | import ws from './ws.js'; 6 | import {T} from './common/i18n.js'; 7 | 8 | class Cpu_warning extends React.Component { 9 | constructor(props){ 10 | super(props); 11 | this.state = {usage: 0, level: null}; 12 | } 13 | componentDidMount(){ 14 | ws.addEventListener('cpu_usage', this.on_cpu_usage); 15 | } 16 | componentWillUnmount(){ 17 | ws.removeEventListener('cpu_usage', this.on_cpu_usage); 18 | } 19 | shouldComponentUpdate(_, next_state){ 20 | return this.state.usage!=next_state.usage; 21 | } 22 | on_cpu_usage = ({data})=>this.setState({ 23 | usage: data.usage, 24 | level: data.level 25 | }); 26 | render(){ 27 | const {usage, level} = this.state; 28 | if (!level) 29 | return null; 30 | return
31 | 32 | High CPU usage: {usage}% 33 |
; 34 | } 35 | } 36 | 37 | export default Cpu_warning; 38 | -------------------------------------------------------------------------------- /src/pub2/css/api_url_modal.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .api_url_modal { 3 | .desc { margin-right: 10px; } 4 | .btn_support { 5 | position: relative; 6 | width: 280px; 7 | margin-bottom: 5px; 8 | .icon { 9 | margin-right: 10px; 10 | position: absolute; 11 | left: 10px; 12 | top: 0; 13 | bottom: 0; 14 | margin-top: auto; 15 | margin-bottom: auto; 16 | height: 16px; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/pub2/css/box_radio.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | 3 | .box_radio { 4 | border: 1px solid @color-base-light; 5 | border-radius: 4px; 6 | overflow: hidden; 7 | max-height: 480px; 8 | &_opt { 9 | cursor: pointer; 10 | font-size: 14px; 11 | display: flex; 12 | align-items: center; 13 | background-color: @color-white; 14 | padding: 0.8em; 15 | column-gap: 0.8em; 16 | width: 100%; 17 | } 18 | &_opt:not(:last-child) { 19 | border-bottom: 1px solid @color-base-light; 20 | } 21 | &_opt:hover, &_opt.checked { 22 | background-color: @color-base-accent; 23 | } 24 | &_opt-text { 25 | display: flex; 26 | flex-direction: column; 27 | row-gap: 2px; 28 | } 29 | &_opt.disabled { 30 | cursor: not-allowed; 31 | background-color: @color-base-accent; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/pub2/css/config.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .config { 3 | height: 100%; 4 | font-size: 14px; 5 | padding: 0 15px; 6 | .btn { width: 140px; } 7 | .nav_buttons { 8 | position: absolute; 9 | z-index: 10; 10 | right: 15px; 11 | top: 15px; 12 | white-space: nowrap; 13 | flex: 1; 14 | .btn:last-child { margin-right: 0; } 15 | } 16 | .code_panel { 17 | .panel_body { 18 | background-color: @light_grey; 19 | position: relative; 20 | padding: 1px; 21 | .CodeMirror { 22 | flex: auto; 23 | display: flex; 24 | flex-direction: column; 25 | .CodeMirror-scroll { flex: auto; } 26 | &.cm-s-default { 27 | padding: 5px; 28 | background-color: @light_grey; 29 | } 30 | } 31 | .nav_buttons { right: 25px; } 32 | } 33 | } 34 | .code_panel.editable { 35 | border-color: @first_color; 36 | .panel_body { 37 | background-color: transparent; 38 | .CodeMirror.cm-s-default { background-color: white; } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/pub2/css/nav.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .nav_left2 { 3 | .menu { 4 | z-index: 10; 5 | top: unset !important; 6 | position: fixed; 7 | width: 80px !important; 8 | height: 100% !important; 9 | .menu_item { 10 | height: 40px; 11 | position: relative; 12 | cursor: pointer; 13 | &.active { 14 | background-color: @cp_dark; 15 | cursor: default; 16 | .text { color: @first_color; } 17 | } 18 | &.active, &:hover { opacity: 1; } 19 | } 20 | .icon { 21 | padding: 0; 22 | width: 20px; 23 | height: 20px; 24 | position: relative; 25 | top: 10px; 26 | left: 15px; 27 | } 28 | .howto { background-image: url('img/howto.svg'); } 29 | .proxies { background-image: url('img/proxies.svg'); } 30 | .overview { background-image: url('img/proxies.svg'); } 31 | .logs { background-image: url('img/stats.svg'); } 32 | .proxy_tester { background-image: url('img/tester.svg'); } 33 | .tools { background-image: url('img/tools.svg'); } 34 | .config { background-image: url('img/tools.svg'); } 35 | .general_config { background-image: url('img/config.svg'); } 36 | .api { background-image: url('img/ic_api.svg'); } 37 | .faq { background-image: url('img/ic_faq.svg'); } 38 | &.lock { 39 | pointer-events: none; 40 | .menu_item { 41 | opacity: 0.4; 42 | cursor: default; 43 | } 44 | } 45 | } 46 | .menu_filler { 47 | border-right: 1px solid @cp_border_dark; 48 | background-color: white; 49 | height: 100%; 50 | position: fixed; 51 | width: 50px; 52 | z-index: 1; 53 | } 54 | .footer { 55 | z-index: 5; 56 | font-size: 13px; 57 | color: @link; 58 | width: 50px; 59 | position: fixed; 60 | bottom: 100px; 61 | a { margin: 3px; } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/pub2/css/notif_center.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .notif_modal { 3 | .notifs { 4 | h4.no_messages { text-align: center; } 5 | .message { 6 | width: 100%; 7 | background-color: @light_grey; 8 | border-radius: 2px; 9 | padding: 15px; 10 | margin: 10px 0; 11 | .subject { 12 | color: @first_color; 13 | font-size: 16px; 14 | font-weight: bold 15 | } 16 | .text { font-size: 13px; } 17 | &.unread { background-color: @x_light; } 18 | &.clickable { cursor: pointer; } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/pub2/css/proxies.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .proxies { 3 | &.nav_header { padding: 0 15px 10px; } 4 | .proxies_panel { 5 | padding-bottom: 0; 6 | } 7 | .proxies_actions { 8 | visibility: hidden; 9 | display: grid; 10 | grid-template-columns: repeat(3, 30%); 11 | .action_icon { width: 16px; height:16px; } 12 | .remove { grid-column: 1; } 13 | .duplicate { grid-column: 2; } 14 | .refresh { grid-column: 3; } 15 | } 16 | .proxies_actions_local { 17 | visibility: hidden; 18 | display: grid; 19 | grid-template-columns: 33% 33% 33%; 20 | .action_icon { width: 16px; height:16px; } 21 | .remove { grid-column: 1; } 22 | .duplicate { grid-column: 2; } 23 | .refresh { grid-column: 3; } 24 | } 25 | .port_cell { 26 | &.master { 27 | flex-direction: row; 28 | display: flex; 29 | } 30 | &.multiplied { 31 | padding: 10px; 32 | } 33 | } 34 | } 35 | 36 | div[role=columnheader], div[role=cell] { 37 | white-space: nowrap; 38 | div:not(.context-menu-wrapper + div) { 39 | text-overflow: ellipsis; 40 | overflow: hidden; 41 | } 42 | div[role=tooltip] { 43 | white-space: normal; 44 | overflow: unset; 45 | div { 46 | overflow: unset; 47 | } 48 | } 49 | div[role=button] > div { 50 | overflow: unset; 51 | } 52 | } 53 | 54 | .context-menu-wrapper + div { 55 | left: -70px !important; 56 | } 57 | -------------------------------------------------------------------------------- /src/pub2/css/proxy_add.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .proxy_add { 3 | padding: 0 15px; 4 | &_form { 5 | padding-left: 5px; 6 | display: flex; 7 | flex-direction: column; 8 | flex-wrap: wrap; 9 | row-gap: 15px; 10 | .field_row { 11 | align-items: baseline; 12 | .desc { 13 | width: 170px; 14 | margin-right: 5px; 15 | white-space: nowrap; 16 | } 17 | } 18 | } 19 | &_zone_select_section { 20 | padding: 10px 0px; 21 | } 22 | &_btn_container { 23 | width: 500px; 24 | display: flex; 25 | justify-content: flex-end; 26 | } 27 | &.animated { 28 | animation-duration: 600ms; 29 | -webkit-animation-duration: 600ms; 30 | } 31 | .cp_panel { 32 | height: 100%; 33 | overflow: auto; 34 | } 35 | .step_title { 36 | padding: 2px 0px 0px; 37 | font-size: 18px; 38 | font-weight: 600; 39 | } 40 | .step_content { 41 | margin-top: 0; 42 | max-height: 0; 43 | visibility: hidden; 44 | &.shown { 45 | margin-top: 10px; 46 | max-height: initial; 47 | visibility: visible; 48 | } 49 | .note { margin-bottom: 15px; } 50 | } 51 | &.vbox { overflow-y: hidden; } 52 | } 53 | .ext_proxy { 54 | width: 500px; 55 | margin-top: 10px; 56 | textarea { 57 | margin-top: 5px; 58 | width: 500px; 59 | max-width: 500px; 60 | } 61 | .json_error { 62 | position: relative; 63 | color: #eb3a28; 64 | font-size: 13px; 65 | margin-left: 3px; 66 | line-height: 2; 67 | } 68 | .json_example { 69 | margin-left: 3px; 70 | position: relative; 71 | line-height: 1; 72 | font-size: 13px; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/pub2/css/proxy_blank.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .no_proxies { 3 | text-align: center; 4 | .btn_add_port { margin: 20px auto; } 5 | } 6 | -------------------------------------------------------------------------------- /src/pub2/css/report_bug.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .report_bug { 3 | .desc { margin: 10px 0; } 4 | .modal-footer { 5 | button.ok { margin-right: 0; } 6 | } 7 | .email_field { 8 | display: flex; 9 | align-items: center; 10 | span { width: 200px; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/pub2/css/settings.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .settings { 3 | padding: 0 15px; 4 | .settings_form { 5 | padding-left: 5px; 6 | display: flex; 7 | flex-direction: column; 8 | flex-wrap: wrap; 9 | row-gap: 15px; 10 | .field_row { 11 | align-items: baseline; 12 | .desc { 13 | width: 170px; 14 | margin-right: 5px; 15 | white-space: nowrap; 16 | } 17 | } 18 | } 19 | .cp_panel { 20 | height: 100%; 21 | overflow: auto; 22 | } 23 | &_btn_container { 24 | width: 500px; 25 | display: flex; 26 | justify-content: flex-end; 27 | } 28 | &.vbox { overflow-y: hidden; } 29 | } 30 | .logs_settings_modal { 31 | &_tabs{ 32 | margin-top: 10px; 33 | margin-bottom: 10px; 34 | .inputs_container { 35 | display: flex; 36 | input { 37 | width: 100%; 38 | } 39 | margin-top: 10px; 40 | .aggr_url { 41 | flex: 1; 42 | margin-right: 10px; 43 | width: 100%; 44 | } 45 | .cred_first { 46 | flex: 1; 47 | margin-right: 10px; 48 | width: 50%; 49 | } 50 | .cred_second { 51 | flex: 1; 52 | width: 50%; 53 | } 54 | .input_full { 55 | flex: 1; 56 | width: 100%; 57 | } 58 | .btn_test { 59 | min-width: 80px; 60 | } 61 | .input_main{ 62 | width: 70%; 63 | &_sub { 64 | width: 30%; 65 | } 66 | } 67 | .input_second{ 68 | margin-left: 10px; 69 | width: 30%; 70 | } 71 | .input_half{ 72 | width: 50%; 73 | &_sub { 74 | width: 50%; 75 | margin-left: 10px; 76 | } 77 | } 78 | } 79 | } 80 | .use_limit { 81 | align-items: center; 82 | display: flex; 83 | margin-top: 10px; 84 | &_tooltip { 85 | margin-right: 15px; 86 | font-size: 15px; 87 | } 88 | } 89 | } 90 | 91 | 92 | -------------------------------------------------------------------------------- /src/pub2/css/tab_group.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | 3 | div[role=tablist].wide { 4 | width: 100%; 5 | button[role=tab] { 6 | width: unset; 7 | flex: 1 1 0; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/pub2/css/tooltip.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .tooltip { 3 | z-index: 10000; 4 | } 5 | .tooltip.in { 6 | opacity: 1; 7 | } 8 | .tooltip-proxy-status .tooltip-inner, .tooltip-default .tooltip-inner, 9 | .tooltip .tooltip-inner { 10 | word-break: break-word; 11 | max-width: 315px; 12 | border: solid 1px @tooltip; 13 | background: white; 14 | color: @first_color; 15 | font-size: 14px; 16 | text-align: left; 17 | ul { padding-left: 20px; padding-top: 10px; } 18 | } 19 | .tooltip.har_tooltip { 20 | .tooltip-inner { 21 | position: relative; 22 | max-width: 550px; 23 | background: hsl(0, 0%, 95%); 24 | border-radius: 2px; 25 | color: hsl(0, 0%, 20%); 26 | padding: 5px 8px; 27 | line-height: 14px; 28 | align-items: center; 29 | -webkit-filter: drop-shadow(0 1px 2px hsla(0, 0%, 0%, 0.3)); 30 | border: 1px solid hsla(0, 0%, 0%, 0.1); 31 | background-clip: padding-box; 32 | box-sizing: border-box; 33 | transition: visibility 0s 100ms, opacity 150ms cubic-bezier(0, 0, .2, 1); 34 | z-index: 20001; 35 | text-overflow: ellipsis; 36 | overflow: hidden; 37 | font-size: 12px; 38 | font-family: Roboto, Ubuntu, Arial, sans-serif; 39 | } 40 | .tooltip-arrow { display: none; } 41 | &.top { 42 | .tooltip-inner { top: 7px; } 43 | } 44 | &.bottom { 45 | margin-top: 0; 46 | padding-top: 0; 47 | margin-left: 9px; 48 | .tooltip-inner { top: 4px; } 49 | } 50 | &.left { margin-left: 0; } 51 | } 52 | .tooltip.wide .tooltip-inner { max-width: 600px; } 53 | .tooltip.top .tooltip-arrow { border-top-color: @tooltip; } 54 | .tooltip.bottom .tooltip-arrow { border-bottom-color: @tooltip; } 55 | -------------------------------------------------------------------------------- /src/pub2/css/whitelist_ips.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .whitelist_ips { 3 | padding-top: 70px; 4 | max-width: 800px; 5 | margin: auto; 6 | .user_choice { 7 | display: flex; 8 | .user { 9 | cursor: pointer; 10 | padding: 30px; 11 | width: 240px; 12 | height: 280px; 13 | margin-right: 20px; 14 | outline: 1px solid @grey_border; 15 | &.active { 16 | outline: 2px solid @first_color; 17 | } 18 | .img_wrapper { 19 | width: 88px; 20 | height: 88px; 21 | margin: 0 auto 30px; 22 | .img { 23 | width: 100%; 24 | height: 100%; 25 | } 26 | .admin { background-image: url(img/ic_admin.svg); } 27 | .guest { background-image: url(img/ic_guest.svg); } 28 | } 29 | .user_title { 30 | margin-bottom: 12px; 31 | font-size: 20px; 32 | font-weight: bold; 33 | line-height: 1.2; 34 | } 35 | .user_desc { 36 | font-size: 14px; 37 | line-height: 1.2; 38 | } 39 | } 40 | } 41 | .whitelist_header { 42 | h3 { font-size: 30px; } 43 | margin-bottom: 30px; 44 | margin-top: 30px; 45 | text-align: left; 46 | } 47 | .steps { 48 | margin-top: 50px; 49 | h3 { font-size: 17px; } 50 | .instructions { margin: 15px 10px; } 51 | } 52 | .nav_top { 53 | background-color: white; 54 | .logo_big { 55 | background: url(img/brd_logo_large.svg) no-repeat; 56 | width: 158px; 57 | height: 33px; 58 | margin: 7px; 59 | display: block; 60 | } 61 | .version { 62 | position: relative; 63 | top: 30px; 64 | left: -46px; 65 | font-size: 9px; 66 | font-weight: bold; 67 | opacity: 0.5; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/pub2/css/zone_desc.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'common.less'; 2 | .zone_settings { 3 | cursor: default !important; 4 | border: 1px solid @color-base-light; 5 | border-radius: 4px; 6 | overflow: hidden; 7 | padding: 10px; 8 | .zone_label { 9 | margin-bottom: 5px; 10 | } 11 | .pair { 12 | display: flex; 13 | .title { 14 | margin-right: 5px; 15 | font-weight: 600; 16 | } 17 | .val { 18 | display: flex; 19 | align-items: center; 20 | } 21 | } 22 | .lit { 23 | line-height: 1.9; 24 | padding: 0 6px; 25 | margin-right: 3px; 26 | background-color: #e1e9ed; 27 | color: inherit; 28 | font-size: 11px; 29 | border-radius: 3px; 30 | } 31 | .perm_icon { 32 | width: 18px; 33 | height: 18px; 34 | float: left; 35 | margin: 2px 4px 0; 36 | background-repeat: no-repeat; 37 | background-size: contain; 38 | &.country { background-image: url(/img/country.svg); } 39 | &.state { background-image: url(/img/state.svg); } 40 | &.data_center { background-image: url(/img/data_center.svg); } 41 | &.asn { background-image: url(/img/asn.svg); } 42 | &.city { background-image: url(/img/city.svg); } 43 | &.vip { background-image: url(/img/g_ip.svg); } 44 | &.residential { background-image: url(/img/residential.svg); } 45 | &.static_res { background-image: url(/img/static_res.svg); } 46 | &.zip { background-image: url(/img/zipcode.svg); } 47 | &.mobile { 48 | width: 14px; 49 | background-image: url(/img/mobile.svg); 50 | } 51 | } 52 | .domains_list { 53 | display: flex; 54 | flex-wrap: wrap; 55 | margin-left: 13px; 56 | .domain { 57 | .lit(); 58 | margin-bottom: 3px; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/pub2/logs.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true, es6:true*/ 3 | import React from 'react'; 4 | import Har_viewer from './har_viewer.js'; 5 | import {withRouter} from 'react-router-dom'; 6 | import zurl from '../../util/url.js'; 7 | import Pure_component from '/www/util/pub/pure_component.js'; 8 | import './css/logs.less'; 9 | 10 | export const Logs = withRouter(class Logs extends Pure_component { 11 | state = {cur_tab: 'har'}; 12 | set_tab = id=>this.setState({cur_tab: id}); 13 | render(){ 14 | const {location} = this.props; 15 | const qs_o = zurl.qs_parse((location.search||'').substr(1)); 16 | return
18 | 19 |
; 20 | } 21 | }); 22 | 23 | export const Dock_logs = ()=> 24 |
25 | 26 |
; 27 | -------------------------------------------------------------------------------- /src/pub2/proxy_blank.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true, es6:true*/ 3 | import React from 'react'; 4 | import $ from 'jquery'; 5 | import Tooltip from './common/tooltip.js'; 6 | import {T} from './common/i18n.js'; 7 | import ws from './ws.js'; 8 | import './css/proxy_blank.less'; 9 | 10 | const open_modal = ()=>{ 11 | ws.post_event('Start Click'); 12 | $('#add_new_proxy_modal').modal('show'); 13 | }; 14 | 15 | const Proxy_blank = ()=> 16 |
17 |
18 | 19 | 23 | 24 |
25 |
; 26 | 27 | export default Proxy_blank; 28 | -------------------------------------------------------------------------------- /src/pub2/ws.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint browser:true, react:true, es6:true*/ 3 | import _ from 'lodash4'; 4 | import {EventTarget} from 'event-target-shim'; 5 | import setdb from '../../util/setdb.js'; 6 | import zws from '../../util/ws.js'; 7 | import {get_location_port} from './util.js'; 8 | 9 | class Ws_wrapper extends EventTarget { 10 | constructor(){ 11 | super(); 12 | this.url = location.hostname; 13 | this.port = get_location_port(); 14 | this.protocol = location.protocol=='https:' ? 'wss' : 'ws'; 15 | } 16 | create_socket(){ 17 | const ws_url = `${this.protocol}://${this.url}:${this.port}`; 18 | const _this = this; 19 | this.socket = new zws.Client(ws_url, { 20 | mux: {use_ack: true}, 21 | label: 'pmgr_ui', 22 | ipc_client: { 23 | hello: 'post', 24 | ui_event: 'post', 25 | }, 26 | }) 27 | .on('connected', ()=>console.log('pmgr new ws connected')) 28 | .on('disconnected', ()=>console.log('pmgr new ws disconnected')) 29 | .on('json', data=>{ 30 | const event = new MessageEvent(data.msg || 'message', {data}); 31 | _this.dispatchEvent(event); 32 | _this.global_handler(event); 33 | }); 34 | } 35 | connect(){ 36 | if (!this.socket || !this.socket.connected) 37 | this.create_socket(); 38 | } 39 | disconnect(){ 40 | if (!this.socket || !this.socket.connected) 41 | return; 42 | this.socket.close(); 43 | } 44 | global_handler(event){ 45 | if (!event.data || !event.data.msg!='update_path') 46 | return; 47 | const {path, payload} = event.data; 48 | if (path.endsWith('.remove') || path.endsWith('.add')) 49 | return setdb.emit('ws.'+path, payload); 50 | setdb.set('ws.'+path, payload); 51 | } 52 | post_event(name, payload={}){ 53 | if (!this.socket || !this.socket.connected) 54 | return void console.error('pmgr ws not connected', name); 55 | if (!name || !_.isString(name)) 56 | return void console.error('pmgr ws not valid event name', name); 57 | this.socket.ipc.ui_event(Object.assign(payload, 58 | {name, cred: document.cookie})); 59 | } 60 | } 61 | 62 | export default new Ws_wrapper(); 63 | -------------------------------------------------------------------------------- /test/scripts.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true, mocha:true*/ 3 | const assert = require('assert'); 4 | const changelog = require('../scripts/changelog_validate.js'); 5 | 6 | describe('changelog_validate', ()=>{ 7 | const valid = { 8 | ver: 'REPLACE_VERSION', 9 | type: 'stable', 10 | changes: [{'type': 'bug', 'text': 'Fix'}], 11 | }; 12 | it('should not throw on valid config', ()=>{ 13 | assert.doesNotThrow(()=>changelog.t.validate([valid])); 14 | }); 15 | it('should throw on invalid version type', ()=>{ 16 | const clog = [Object.assign({}, valid, {type: 'random'})]; 17 | assert.throws(()=>changelog.t.validate(clog), 18 | {message: 'Invalid changelog version type: random'}); 19 | }); 20 | it('should throw on empty changes', ()=>{ 21 | const clog = [Object.assign({}, valid, {changes: []})]; 22 | assert.throws(()=>changelog.t.validate(clog), 23 | {message: 'Changes in the latest changelog should be specified'}); 24 | }); 25 | it('should throw on changes with invalid type', ()=>{ 26 | const clog = [Object.assign({}, valid, 27 | {changes: [{type: 'a', text: 'Fix'}]})]; 28 | assert.throws(()=>changelog.t.validate(clog), 29 | {message: 'There are invalid changes in the latest changelog'}); 30 | }); 31 | it('should throw on changes without text', ()=>{ 32 | const clog = [Object.assign({}, valid, 33 | {changes: [{type: 'bug', text: ''}]})]; 34 | assert.throws(()=>changelog.t.validate(clog), 35 | {message: 'There are invalid changes in the latest changelog'}); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/ws.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true, mocha:true*/ 3 | const net = require('net'); 4 | const sinon = require('sinon'); 5 | const Ws = require('../lib/ws.js'); 6 | 7 | describe('ws', ()=>{ 8 | let ws_handler, socket, s_mock, dst, d_mock; 9 | beforeEach(()=>{ 10 | socket = new net.Socket(); 11 | s_mock = sinon.mock(socket); 12 | dst = new net.Socket(); 13 | d_mock = sinon.mock(dst); 14 | ws_handler = new Ws({}); 15 | }); 16 | afterEach(()=>{ 17 | ws_handler.stop(); 18 | socket.destroy(); 19 | dst.destroy(); 20 | }); 21 | it('pipes both sockets on proxy req upgrade', ()=>{ 22 | d_mock.expects('pipe').returns(socket).once().withArgs(socket); 23 | s_mock.expects('pipe').once().withArgs(dst); 24 | ws_handler.handle_connection(socket, dst); 25 | s_mock.verify(); 26 | d_mock.verify(); 27 | }); 28 | it('destroy sockets on stop', ()=>{ 29 | ws_handler.handle_connection(socket, dst); 30 | s_mock.expects('destroy').once(); 31 | d_mock.expects('destroy').once(); 32 | ws_handler.stop(); 33 | s_mock.verify(); 34 | d_mock.verify(); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /util/buf_pool.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON 2 | 'use strict'; /*jslint node:true*/ 3 | require('./config.js'); 4 | const array = require('./array.js'); 5 | const conv = require('./conv.js'); 6 | const zcounter = require('./zcounter.js'); 7 | const {env} = process; 8 | const KB = 1024, MB = 1024*KB; 9 | 10 | class BufPool { 11 | constructor(max_free_size, free_ttl, name){ 12 | this.max_free_size = max_free_size; 13 | this.free_ttl = free_ttl||3E+5; 14 | this.name = name ? name+'_' : ''; 15 | this.pool = {}; 16 | this.free_size = 0; 17 | this.overflow_ts = 0; 18 | } 19 | create(max_free_size, free_ttl, name){ 20 | return new BufPool(max_free_size, free_ttl, name); 21 | } 22 | counter(bp){ 23 | if (env.AGENT_NUM && !zcounter.is_debug('bp')) 24 | return; 25 | let name = zcounter.to_valid_id('bp_'+this.name+bp.name+'_'); 26 | zcounter.set_level(name+'used', bp.used.length); 27 | zcounter.set_level(name+'free', bp.free.length); 28 | } 29 | alloc(bytes){ 30 | let bp = this.pool[bytes] = this.pool[bytes]||{bytes, 31 | created: new Error().stack, free: [], used: [], 32 | name: conv.scaled_number(bytes, {base: KB})}; 33 | let b = !bp.free.length ? Buffer.alloc(bytes) : bp.free.pop(); 34 | bp.used.push(b); 35 | this.counter(bp); 36 | return b; 37 | } 38 | free(buf){ 39 | let bp = this.pool[buf.length]; 40 | bp.free.push(buf); 41 | array.rm_elm(bp.used, buf); 42 | this.free_size += buf.length; 43 | if (this.max_free_size) 44 | this.cut_free(); 45 | else 46 | this.counter(bp); 47 | } 48 | cut_free(){ 49 | if (this.free_size<=this.max_free_size) 50 | return void (this.overflow_ts = 0); 51 | let now = Date.now(); 52 | if (!this.overflow_ts) 53 | return void (this.overflow_ts = now); 54 | if (now-this.overflow_ts<=this.free_ttl) 55 | return; 56 | let fraction = this.max_free_size/this.free_size; 57 | for (let name in this.pool) 58 | { 59 | let bp = this.pool[name]; 60 | let new_length = Math.floor(bp.free.length*fraction); 61 | this.free_size -= bp.bytes*(bp.free.length-new_length); 62 | bp.free.length = new_length; 63 | this.counter(bp); 64 | } 65 | this.overflow_ts = 0; 66 | } 67 | } 68 | 69 | module.exports = new BufPool(50*MB); 70 | -------------------------------------------------------------------------------- /util/cert_util.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // LICENSE_CODE ZON ISC 3 | 'use strict'; /*jslint node:true, esnext:true*/ 4 | const forge = require('node-forge'); 5 | const date = require('../util/date.js'); 6 | 7 | const DEFAULT_COUNTRY = 'Australia'; 8 | const DEFAULT_STATE = 'Victoria'; 9 | const DEFAULT_CITY = 'Melbourne'; 10 | const ROOT_CA_EXTENSIONS = [{ 11 | name: 'basicConstraints', 12 | cA: true, 13 | }, { 14 | name: 'keyUsage', 15 | keyCertSign: true, 16 | cRLSign: true, 17 | }]; 18 | 19 | const abs = hex=>{ 20 | let first_digit = parseInt(hex[0], 16); 21 | if (first_digit < 8) 22 | return hex; 23 | first_digit -= 8; 24 | return first_digit.toString() + hex.substring(1); 25 | }; 26 | 27 | const rand_sn = ()=>abs(forge.util.bytesToHex(forge.random.getBytesSync(20))); 28 | 29 | const get_attrs = opt=>{ 30 | let {country, state, city, common_name, customer} = opt; 31 | let attrs = [{ 32 | shortName: 'C', 33 | value: country || DEFAULT_COUNTRY, 34 | }, { 35 | shortName: 'ST', 36 | value: state || DEFAULT_STATE, 37 | }, { 38 | shortName: 'L', 39 | value: city || DEFAULT_CITY, 40 | }, { 41 | shortName: 'CN', 42 | value: common_name || `${customer ? customer+' ' : ''}PMGR RootCA`, 43 | }]; 44 | if (customer) 45 | attrs.push({shortName: 'O', value: customer}); 46 | return attrs; 47 | }; 48 | 49 | module.exports = class Cert_gen { 50 | static create_root_ca(opt={}){ 51 | const attrs = get_attrs(opt); 52 | const keys = forge.pki.rsa.generateKeyPair(2048); 53 | const cert = forge.pki.createCertificate(); 54 | cert.publicKey = keys.publicKey; 55 | cert.privateKey = keys.privateKey; 56 | cert.serialNumber = rand_sn(); 57 | cert.validity.notBefore = date.add(date(), {day: -2}); 58 | cert.validity.notAfter = date.add(cert.validity.notBefore, 59 | {year: 20}); 60 | cert.setSubject(attrs); 61 | cert.setIssuer(attrs); 62 | cert.setExtensions(opt.extensions || ROOT_CA_EXTENSIONS); 63 | cert.sign(keys.privateKey, forge.md.sha512.create()); 64 | return { 65 | cert: forge.pki.certificateToPem(cert), 66 | key: forge.pki.privateKeyToPem(keys.privateKey), 67 | not_before: cert.validity.notBefore, 68 | not_after: cert.validity.notAfter, 69 | }; 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /util/conf.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON 2 | 'use strict'; /*jslint node:true*/ 3 | require('./config.js'); 4 | const zerr = require('./zerr.js'); 5 | const file = require('./file.js'); 6 | const path = require('path'); 7 | const os = require('os'); 8 | const env = process.env; 9 | 10 | // XXX: embedded Node now has a regular command line, revisit 11 | // XXX: rm process.zon from hutil 12 | let script_path = !(process.zon && process.zon.main) && process.argv[1] ? 13 | file.normalize(process.argv[1]) : undefined; 14 | 15 | function parse(conf){ 16 | const iniparser = require('iniparser'); 17 | let c = iniparser.parseString(conf); 18 | for (let i in c) 19 | c[i] = c[i].replace(/^"([^"]*)"$/, '$1'); 20 | return c; 21 | } 22 | 23 | function _hostname(){ 24 | let hostname = (env.CONFIG_HOSTNAME || os.hostname()).toLowerCase(); 25 | return hostname.replace(/\.hola\.org$/, '').replace(/\.localdomain$/, '') 26 | .replace(/\.local$/, '').replace(/\.home$/, ''); 27 | } 28 | 29 | function _hostname_base(){ 30 | if (env.AGENT_TYPE) 31 | return 'agent_'+env.AGENT_TYPE; 32 | if (_is_k8s() && env.CONFIG_APP) 33 | return env.CONFIG_APP; 34 | return _hostname().replace(/(-ec2)?\d*$/, '$1'); 35 | } 36 | 37 | function _is_k8s(){ 38 | return !!env.CLUSTER_NAME; 39 | } 40 | 41 | function init(){ 42 | let filename = script_path; 43 | if (filename) 44 | { 45 | if (!file.exists(`${filename}.conf`) && file.is_symlink(filename)) 46 | filename = file.readlink(filename); 47 | let text = file.read(`${filename}.conf`); 48 | if (text) 49 | Object.assign(env, parse(text)); 50 | } 51 | if (env.ZERR) 52 | zerr.set_level(); 53 | } 54 | 55 | init(); 56 | 57 | module.exports = { 58 | hostname: _hostname(), 59 | hostname_base: _hostname_base(), 60 | app: env.CONFIG_APP || script_path&&path.basename(script_path, '.js'), 61 | t: {parse}, 62 | }; 63 | -------------------------------------------------------------------------------- /util/config.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true, es6:false*/ 3 | require('./es6_shim.js'); 4 | module.exports = require('../zon_config.json'); 5 | -------------------------------------------------------------------------------- /util/fs_cache.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON 2 | 'use strict'; /*jslint node:true*/ 3 | const etask = require('./etask.js'); 4 | const fs = require('fs'); 5 | const path = require('path'); 6 | 7 | const E = exports; 8 | 9 | class Fetchable_FS_Cache { 10 | constructor(conf){ 11 | this.path = conf.path; 12 | this.folder = path.dirname(conf.path); 13 | this.expires = conf.expires || 0; 14 | this.fetch_fn = conf.fetch; 15 | this.on_data = conf.on_data; 16 | this.last_fetch = null; 17 | this.fetch_running = null; 18 | } 19 | set(data){ 20 | const _this = this; 21 | return etask(function*(){ 22 | yield fs.promises.mkdir(_this.folder, {recursive: true}); 23 | yield fs.promises.writeFile(_this.path, JSON.stringify(data)); 24 | _this.last_fetch = new Date(); 25 | }); 26 | } 27 | fetch(){ 28 | const _this = this; 29 | return etask(function*(){ 30 | this.finally(()=>_this.fetch_running = null); 31 | _this.fetch_running = this; 32 | const data = yield _this.fetch_fn(); 33 | return yield _this.on_data ? _this.on_data(data) : data; 34 | }); 35 | } 36 | get(){ 37 | const _this = this; 38 | return etask(function*(){ 39 | if (_this.fetch_running) 40 | return yield this.wait_ext(_this.fetch_running); 41 | let exists; 42 | try { 43 | yield fs.promises.access(_this.path, 44 | fs.constants.R_OK); 45 | exists = true; 46 | } catch(e){ exists = false; } 47 | if (!_this.last_fetch || !exists || 48 | _this.expires && new Date()-_this.last_fetch>_this.expires) 49 | { 50 | const data = yield _this.fetch(); 51 | yield _this.set(data); 52 | return data; 53 | } 54 | const content = yield fs.promises.readFile(_this.path, 'utf-8'); 55 | return yield JSON.parse(content); 56 | }); 57 | } 58 | delete(){ 59 | const _this = this; 60 | return etask(function*(){ 61 | return yield fs.promises.rm(_this.folder, {recursive: true}); 62 | }); 63 | } 64 | } 65 | 66 | E.Fetchable_FS_Cache = Fetchable_FS_Cache; 67 | -------------------------------------------------------------------------------- /util/lpm_config.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true, esnext:true*/ 3 | const pkg = require('../package.json'); 4 | const lpm_file = require('./lpm_file.js'); 5 | const file = require('./file.js'); 6 | let conf = require('./lpm_config_static.js'); 7 | 8 | const is_zagent = process.argv.some((a, idx, src)=> 9 | a=='--zagent'&&src[idx+1]!='false'); 10 | conf.version = pkg.version; 11 | conf.hola_agent = 'proxy='+pkg.version+' node='+process.version 12 | +' platform='+process.platform+(is_zagent ? ' cloud_lpm=1' : ''); 13 | conf.is_lum = file.exists(file.cyg2unix('/usr/local/hola/zon_config.sh')); 14 | conf.work_dir = lpm_file.work_dir; 15 | Object.assign(conf.manager_default, { 16 | api_domain: process.env.PMGR_API||pkg.api_domain, 17 | config: lpm_file.get_file_path( 18 | '.luminati.json'.slice(conf.is_win ? 1 : 0)), 19 | loki: lpm_file.get_file_path( 20 | '.luminati.db'.slice(conf.is_win ? 1 : 0)), 21 | session_path: lpm_file.get_file_path( 22 | '.sessions.db'.slice(conf.is_win ? 1 : 0)), 23 | }); 24 | 25 | Object.assign(module.exports, conf); 26 | -------------------------------------------------------------------------------- /util/lpm_esm_loader.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true, esnext:true, es9: true*/ 3 | const Module = require('module').Module; 4 | const babel = require('@babel/core'); 5 | 6 | const transform = filename=>babel.transformFileSync(filename, { 7 | plugins: [ 8 | require.resolve('@babel/plugin-transform-export-namespace-from'), 9 | require.resolve('@babel/plugin-transform-modules-commonjs'), 10 | ], 11 | }); 12 | 13 | const get_loaders = ()=>({ 14 | js_loader: Module._extensions['.js'], 15 | mjs_loader: Module._extensions['.mjs'], 16 | }); 17 | 18 | const apply_loaders = (js, mjs)=>{ 19 | Module._extensions['.js'] = js; 20 | Module._extensions['.mjs'] = mjs||js; 21 | }; 22 | 23 | const make_loader = orig=>(mod, filename)=>{ 24 | try { 25 | return orig(mod, filename); 26 | } catch(e){ 27 | if (e.code==='ERR_REQUIRE_ESM') 28 | mod._compile(transform(filename).code, filename); 29 | else 30 | throw e; 31 | } 32 | }; 33 | 34 | module.exports = { 35 | require: (...args)=>{ 36 | const {js_loader, mjs_loader} = get_loaders(); 37 | let new_loader = make_loader(js_loader); 38 | apply_loaders(new_loader); 39 | let required = require(...args); 40 | apply_loaders(js_loader, mjs_loader); 41 | return required; 42 | }, 43 | }; 44 | -------------------------------------------------------------------------------- /util/lpm_file.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // LICENSE_CODE ZON ISC 3 | 'use strict'; /*jslint node:true, esnext:true*/ 4 | const yargs = require('yargs'); 5 | const path = require('path'); 6 | const os = require('os'); 7 | const cluster = require('cluster'); 8 | const file = require('./file.js'); 9 | const zerr = require('./zerr.js'); 10 | const date = require('./date.js'); 11 | const BASE_PATH = os.homedir(); 12 | const PM_DIRNAME = 'proxy_manager'; 13 | const LEGACY_DIRNAME = 'luminati_proxy_manager'; 14 | const E = module.exports; 15 | 16 | // tells Yargs to show help message from lpm_util usage instead of default one 17 | yargs.help(false); 18 | 19 | const log = (msg, ...args)=>{ 20 | let dt = date.to_sql_ms(Date.now()); 21 | if (cluster.isWorker) 22 | dt = `C${cluster.worker.id} ${dt}`; 23 | return console.log(`${dt} FILE (${process.pid}): ${msg}`, ...args); 24 | }; 25 | 26 | const rename_legacy_dir = (legacy_path, pm_path)=>{ 27 | log(`Renaming ${legacy_path} -> ${pm_path}`); 28 | try { 29 | file.rename_e(legacy_path, pm_path); 30 | log('Rename DONE'); 31 | return pm_path; 32 | } catch(e){ 33 | log(`Rename failed: ${zerr.e2s(e)}`); 34 | return legacy_path; 35 | } 36 | }; 37 | 38 | const init_pm_dir = pm_path=>{ 39 | try { 40 | file.mkdirp_e(pm_path); 41 | return pm_path; 42 | } catch(e){ 43 | log(`Failed to create directory ${pm_path}: ${zerr.e2s(e)}`); 44 | return BASE_PATH; 45 | } 46 | }; 47 | 48 | const mk_work_dir = ()=>{ 49 | const argv = yargs.parse(process.argv.slice(2).map(String)); 50 | if (argv.dir) 51 | return argv.dir; 52 | const pm_path = path.resolve(BASE_PATH, PM_DIRNAME); 53 | if (file.is_dir(pm_path)) 54 | return pm_path; 55 | const legacy_path = path.resolve(BASE_PATH, LEGACY_DIRNAME); 56 | if (file.is_dir(legacy_path)) 57 | return rename_legacy_dir(legacy_path, pm_path); 58 | return init_pm_dir(pm_path); 59 | }; 60 | 61 | E.work_dir = mk_work_dir(); 62 | E.get_file_path = filename=>path.resolve(E.work_dir, filename); 63 | -------------------------------------------------------------------------------- /util/queue.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON 2 | 'use strict'; /*jslint node:true, browser:true, es6:true*/ 3 | (function(){ 4 | let define, is_node = typeof module=='object' && module.exports; 5 | if (!is_node) 6 | define = self.define; 7 | else 8 | define = require('./require_node.js').define(module, '../'); 9 | define(['/util/etask.js', '/util/zerr.js'], function(etask, zerr){ 10 | 11 | class Queue { 12 | constructor(label='queue'){ 13 | this.front = undefined; 14 | this.back = undefined; 15 | this.waiting = undefined; 16 | this.label = label; 17 | } 18 | put(item, ttl){ 19 | this._expire(); 20 | let entry = { 21 | data: item, 22 | expires: ttl ? Date.now()+ttl : undefined, 23 | next: undefined, 24 | }; 25 | if (this.back) 26 | this.back.next = entry; 27 | this.back = entry; 28 | if (!this.front) 29 | this.front = entry; 30 | if (this.waiting) 31 | this.waiting.return(); 32 | } 33 | _get(){ 34 | this._expire(); 35 | let entry = this.front; 36 | if (!entry) 37 | return; 38 | this.front = entry.next; 39 | if (!this.front) 40 | this.back = undefined; 41 | return entry; 42 | } 43 | get(){ 44 | let entry = this._get(); 45 | return entry && entry.data; 46 | } 47 | get_ex(){ 48 | let entry = this._get(); 49 | return entry && {item: entry.data, expires: entry.expires}; 50 | } 51 | wait(){ 52 | if (this.waiting) 53 | { 54 | zerr.zexit(`${this.label}: ` 55 | +`concurrent calls to queue.wait are not allowed`); 56 | } 57 | let _this = this; 58 | return etask(function*queue_get(){ 59 | this.info.label = _this.label; 60 | for (;;) 61 | { 62 | let entry = _this._get(); 63 | if (entry) 64 | return entry.data; 65 | try { 66 | _this.waiting = etask.wait(); 67 | yield _this.waiting; 68 | } finally { _this.waiting = undefined; } 69 | } 70 | }); 71 | } 72 | _expire(){ 73 | if (!this.front) 74 | return; 75 | let now = Date.now(), dropped = 0; 76 | while (this.front && this.front.expiresthis.size; 49 | }; 50 | 51 | E.leaky_bucket.prototype.inc = function(inc){ 52 | if (inc===undefined) 53 | inc = 1; 54 | this._update_level(); 55 | var new_level = this.level + inc; 56 | if (new_level>this.size) 57 | return false; 58 | this.level = new_level; 59 | return true; 60 | }; 61 | 62 | E.leaky_bucket.prototype.inc_size = function(inc){ 63 | if (inc===undefined) 64 | inc = 1; 65 | var new_size = this.size + inc; 66 | if (Number.isFinite(this.opt.min_size)) 67 | new_size = Math.max(new_size, this.opt.min_size); 68 | if (Number.isFinite(this.opt.max_size)) 69 | new_size = Math.min(new_size, this.opt.max_size); 70 | var factor = this.size ? new_size/this.size : 1; 71 | this.size = new_size; 72 | this.rate *= factor; 73 | }; 74 | 75 | return E; }); }()); 76 | -------------------------------------------------------------------------------- /util/require_node.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true, browser:true*/ 3 | var is_node = typeof module=='object' && module.exports && module.children; 4 | var is_rn = (typeof global=='object' && !!global.nativeRequire) || 5 | (typeof navigator=='object' && navigator.product=='ReactNative'); 6 | if (is_rn) 7 | { 8 | // in react native, module resolution is done in compile-time so we must do 9 | // require('dep') and not require(dep) even if dep=='dep' in runtime 10 | // rel_root is not used, it's there for compatability with the signature in 11 | // node and ff 12 | exports.define = function(_module, rel_root/*, deps*/){ 13 | var deps = Array.prototype.slice.call(arguments, 2); 14 | return function(name, req, setup){ 15 | if (arguments.length==2) 16 | { 17 | setup = req; 18 | req = name; 19 | } 20 | _module.exports = setup.apply(this, deps); 21 | }; 22 | }; 23 | } 24 | else 25 | { 26 | if (is_node) 27 | require('./config.js'); 28 | var opt = exports.opt = {}; 29 | exports.define = function(_module, rel_root){ 30 | return function(name, req, setup){ 31 | if (arguments.length==2) 32 | { 33 | setup = req; 34 | req = name; 35 | } 36 | _module.exports = setup.apply(this, req.map(function(dep){ 37 | var ex; 38 | if (opt.on_require && (ex = opt.on_require(dep))) 39 | return ex; 40 | // XXX odin: react native bundler syntax error when require() 41 | // not string literal -> workaround. 42 | var _require = require; 43 | if (!dep||/https?:\/\//.test(dep)) 44 | return null; 45 | if (/^\.?\.?\//.test(dep)) // './' '../' '/' 46 | return _require(/* brd-build-deps ignore */rel_root+dep); 47 | return _require(/* brd-build-deps ignore */dep); 48 | })); 49 | }; 50 | }; 51 | } 52 | -------------------------------------------------------------------------------- /util/setdb.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON 2 | 'use strict'; /*jslint node:true, browser:true, es6:true*/ 3 | (function(){ 4 | var define; 5 | var is_node_ff = typeof module=='object' && module.exports; 6 | var is_rn = typeof global=='object' && !!global.nativeRequire || 7 | typeof navigator=='object' && navigator.product=='ReactNative'; 8 | if (is_rn) 9 | { 10 | define = require('./require_node.js').define(module, '../', 11 | require('lodash4'), require('/util/events.js')); 12 | } 13 | else if (!is_node_ff) 14 | define = self.define; 15 | else 16 | define = require('./require_node.js').define(module, '../'); 17 | define(['lodash4', 'events'], (_, EventEmitter)=>{ 18 | 19 | const RECURSIVE = '.'; 20 | 21 | const E = new EventEmitter(); 22 | E.state = {}; 23 | 24 | E.on = (path, fn, opt)=>{ 25 | opt = _.assign({recursive: false, init: true}, opt); 26 | EventEmitter.prototype.on.call(E, path, fn); 27 | if (opt.recursive) 28 | EventEmitter.prototype.on.call(E, RECURSIVE+path, fn); 29 | if (opt.init) 30 | fn(E.get(path)); 31 | return {path, fn, recursive: opt.recursive}; 32 | }; 33 | 34 | E.once = (path, fn, opt)=>{ 35 | let listener; 36 | listener = E.on(path, (...args)=>{ 37 | E.off(listener); 38 | return fn(...args); 39 | }, _.assign({init: false}, opt)); 40 | }; 41 | 42 | E.off = listener=>{ 43 | EventEmitter.prototype.removeListener.call(E, listener.path, listener.fn); 44 | if (listener.recursive) 45 | { 46 | EventEmitter.prototype.removeListener 47 | .call(E, RECURSIVE+listener.path, listener.fn); 48 | } 49 | }; 50 | 51 | E.get = path=>_.get(E.state, path); 52 | 53 | E.set = (path, curr, opt)=>{ 54 | opt = _.assign({force_emit: false}, opt); 55 | if (!opt.force_emit && _.get(E.state, path)===curr) 56 | return; 57 | _.set(E.state, path, curr); 58 | let depth = opt.recursive ? Number.POSITIVE_INFINITY : opt.depth||0; 59 | let _path; 60 | do { 61 | _path = path; 62 | E.emit_path(_path); 63 | if (depth--<=0) 64 | return; 65 | path = path.replace(/\.[^.]+$/, ''); 66 | } while (_path!=path); 67 | }; 68 | 69 | E.delete = path=>E.set(path, undefined); 70 | 71 | E.emit_path = path=>{ 72 | E.emit(path, _.get(E.state, path)); 73 | path = path.split('.'); 74 | while (path.length>1) 75 | { 76 | path.pop(); 77 | let p = path.join('.'); 78 | E.emit(RECURSIVE+p, _.get(E.state, p)); 79 | } 80 | }; 81 | 82 | E.clear = function(){ 83 | this.removeAllListeners(); 84 | this.state = {}; 85 | }; 86 | 87 | E.debug = function(){ 88 | window.setdb = E; 89 | }; 90 | 91 | return E; 92 | 93 | }); }()); 94 | -------------------------------------------------------------------------------- /util/takeup_util.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true*/ 3 | require('./config.js'); 4 | const E = exports; 5 | 6 | // Copy from util/http_hdr.js 7 | // original_raw should be the untransformed value of rawHeaders from the 8 | // Node.js HTTP request or response 9 | E.restore_case = function(headers, original_raw){ 10 | if (!original_raw) 11 | return headers; 12 | const names = {}; 13 | for (let i = 0; iheaders[n]).filter(v=>v)[0]; 30 | if (value!==undefined) 31 | res[names[name][0]] = value; 32 | } 33 | return res; 34 | }; 35 | -------------------------------------------------------------------------------- /util/version.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true*/ 3 | var zconf = require('./config.js'); 4 | var fs = require('fs'); 5 | var version; 6 | var paths = ['.', __dirname, __dirname+'/../..', __dirname+'/../../..']; 7 | if (process.browser) 8 | version = require(/* brd-build-deps ignore */'zon_config.js').ZON_VERSION; 9 | else if (process.zon) 10 | version = process.zon.version; 11 | else if (!(version = zconf.ZON_VERSION)) 12 | { 13 | for (var i=0; imerge(common_config, conf); 9 | 10 | const from_obj = env=>{ 11 | if (env.production) 12 | return merged(prod_config); 13 | if (env.development) 14 | return merged(dev_config); 15 | throw new Error(`Webpack configuration for ${JSON.stringify(env)}` 16 | +' was not found!'); 17 | }; 18 | 19 | const from_str = env=>{ 20 | switch (env) 21 | { 22 | case 'production': return merged(prod_config); 23 | case 'development': return merged(dev_config); 24 | default: 25 | throw new Error(`Webpack configuration for ${env} was not found!`); 26 | } 27 | }; 28 | 29 | module.exports = env=>typeof env==='string' ? from_str(env) : from_obj(env); 30 | -------------------------------------------------------------------------------- /webpack.dev.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true*/ 3 | const webpack = require('webpack'); 4 | module.exports = { 5 | mode: 'development', 6 | devtool: 'eval-source-map', 7 | plugins: [ 8 | new webpack.DefinePlugin({ 9 | ENV_DEV: JSON.stringify(true), 10 | ENV_PROD: JSON.stringify(false), 11 | }), 12 | ] 13 | }; 14 | -------------------------------------------------------------------------------- /webpack.prod.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint node:true*/ 3 | const webpack = require('webpack'); 4 | module.exports = { 5 | mode: 'production', 6 | plugins: [ 7 | new webpack.DefinePlugin({ 8 | ENV_DEV: JSON.stringify(false), 9 | ENV_PROD: JSON.stringify(true), 10 | }), 11 | ] 12 | }; 13 | -------------------------------------------------------------------------------- /www/util/pub/bootstrap_methods.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true, es6:true*/ 3 | define(['bootstrap/package.json'], function({version}) 4 | { 5 | 6 | const is_bs3 = String(version||3).startsWith('3'); 7 | const E = {}; 8 | 9 | E.destroy = is_bs3 ? 'destroy' : 'dispose'; 10 | 11 | E.fix_title = is_bs3 ? 'fixTitle' : '_fixTitle'; 12 | 13 | return E; 14 | 15 | }); 16 | -------------------------------------------------------------------------------- /www/util/pub/bullets.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true, es6:true*/ 3 | define(['react', '/www/util/pub/css/bullets.less'], 4 | React=> 5 | { 6 | const E = {}; 7 | 8 | const Li = ({children})=> 9 |
  • 10 |
    11 |
    12 |
    13 |
    14 | {children} 15 |
    16 |
  • ; 17 | E.Li = Li; 18 | 19 | const Instructions = ({children})=> 20 |
    21 |
      22 | {children} 23 |
    24 |
    ; 25 | E.Instructions = Instructions; 26 | 27 | return E; }); 28 | -------------------------------------------------------------------------------- /www/util/pub/css/bullets.less: -------------------------------------------------------------------------------- 1 | @first_color: #526373; 2 | .instructions { 3 | margin-left: 10px; 4 | border-left: 1px solid @first_color; 5 | position: relative; 6 | .single_instruction { 7 | font-size: 14px; 8 | padding-left: 18px; 9 | position: relative; 10 | top: 2px; 11 | } 12 | ul { margin: 0; } 13 | ol.instruction_list { 14 | counter-reset: section; 15 | list-style-type: none; 16 | padding-left: 0; 17 | } 18 | ol.instruction_list > li { padding-bottom: 12px; } 19 | ol.instruction_list > li .circle_wrapper { 20 | position: absolute; 21 | left: -13px; 22 | background-color: white; 23 | height: 28px; 24 | display: inline-block; 25 | } 26 | ol.instruction_list > li .circle { 27 | border: 1px solid @first_color; 28 | border-radius: 50%; 29 | width: 22px; 30 | height: 22px; 31 | position: relative; 32 | top: 3px; 33 | left: 1px; 34 | } 35 | ol.instruction_list > li:last-child { padding-bottom: 0; } 36 | ol.instruction_list > li .circle:before { 37 | counter-increment: section; 38 | content: counters(section, "."); 39 | display: inline-block; 40 | font-size: 11px; 41 | line-height: 23px; 42 | color: @first_color; 43 | margin-top: 3px; 44 | text-align: center; 45 | font-weight: 600; 46 | position: relative; 47 | width: 20px; 48 | top: -4px; 49 | } 50 | code { 51 | font-family: Menlo,Monaco,Consolas,"Courier New",monospace; 52 | font-size: 12px; 53 | font-weight: 300; 54 | letter-spacing: -0.1px; 55 | color: black; 56 | border-radius: 3px; 57 | padding: 5px 7px 3px; 58 | margin: 0 3px; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /www/util/pub/tooltip.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON ISC 2 | 'use strict'; /*jslint react:true, es6:true*/ 3 | define(['react', 'jquery', '/www/util/pub/bootstrap_methods.js', 4 | '/www/util/pub/pure_component.js'], 5 | function(React, $, bsm, Pure_component) 6 | { 7 | return class Tooltip extends Pure_component { 8 | componentDidMount(){ 9 | if (!this.ref) 10 | return; 11 | $(this.ref).tooltip(); 12 | } 13 | componentWillUnmount(){ 14 | $(this.ref).tooltip(bsm.destroy); 15 | } 16 | componentDidUpdate(){ 17 | $(this.ref).attr('title', this.props.title).tooltip(bsm.fix_title); 18 | } 19 | on_mouse_leave(){ 20 | if (!this.ref) 21 | return; 22 | $(this.ref).tooltip('hide'); 23 | } 24 | set_ref(e){ this.ref = e; } 25 | render(){ 26 | if (this.props.children==undefined) 27 | return null; 28 | if (!this.props.title) 29 | return this.props.children; 30 | const classes = `tooltip har_tooltip ${this.props.className||''}`; 31 | const props = { 32 | 'data-toggle': 'tooltip', 33 | 'data-placement': this.props.placement||'top', 34 | 'data-container': 'body', 35 | 'data-html': true, 36 | 'data-template': ``, 41 | title: this.props.title, 42 | ref: this.set_ref.bind(this), 43 | onMouseLeave: this.on_mouse_leave.bind(this), 44 | }; 45 | return React.Children.map(this.props.children, c=>{ 46 | if (typeof c=='number') 47 | c = ''+c; 48 | if (typeof c=='string' || typeof c=='object' && c.type.name=='T') 49 | return React.createElement('span', props, c); 50 | return React.cloneElement(c, props); 51 | }); 52 | } 53 | }; 54 | }); 55 | -------------------------------------------------------------------------------- /www/util/pub/urlp.js: -------------------------------------------------------------------------------- 1 | // LICENSE_CODE ZON 2 | 'use strict'; /*jslint node:true, browser:true, es6:true*/ 3 | (function(){ 4 | var define; 5 | var is_node = typeof module=='object' && module.exports; 6 | if (!is_node) 7 | define = self.define; 8 | else 9 | define = require('../../../util/require_node.js').define(module, '../'); 10 | define(['/util/url.js', '/util/escape.js'], function(zurl, zescape){ 11 | var E = {}; 12 | 13 | class Urlp { 14 | constructor(opt){ 15 | this.update(opt); 16 | } 17 | update(opt){ 18 | if (!opt || typeof opt=='string') 19 | opt = {url: opt}; 20 | this.url = opt.url||window&&window.location.href; 21 | Object.assign(this, zurl.parse(this.url)); 22 | let qs = zurl.qs_parse(this.query||''); 23 | let hs = zurl.qs_parse((this.hash||'').substr(1)); 24 | if (!opt.validate) 25 | return void Object.assign(this, {qs, hs}); 26 | this.qs = {}; 27 | this.hs = {}; 28 | for (let p in opt.validate.qs||opt.validate) 29 | this.qs[p] = validate(qs[p], opt.validate[p]); 30 | for (let p in opt.validate.hs||{}) 31 | this.hs[p] = validate(hs[p], opt.validate[p]); 32 | } 33 | uri(){ 34 | return zescape.uri(this.pathname, this.qs, this.hs); 35 | } 36 | } 37 | 38 | E.Urlp = Urlp; 39 | 40 | let validate = (param, type)=>{ 41 | if (type=='email' && zurl.is_valid_email(param||'')) 42 | return param; 43 | if (type=='number' && !isNaN(+param)) 44 | return +param; 45 | if (type=='token' && typeof param == 'string' && !param.includes(' ')) 46 | return param; 47 | if (type=='bool' && (!param || param == 1)) 48 | return !!param; 49 | }; 50 | 51 | return E; }); }()); 52 | 53 | -------------------------------------------------------------------------------- /zon_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ZON_VERSION": "1.519.10", 3 | "CONFIG_MAKEFLAGS": "DIST=APP RELEASE=y CC64_32=y CONFIG_LPM=y TOKEN_SIGN=y CONFIG_BATREQ=y CONFIG_BAT_CYCLE=y CONFIG_BAT_PLATFORM=app_win32_lpm", 4 | "CONFIG_BUILD_DATE": "27-Jan-25 13:48:43" 5 | } --------------------------------------------------------------------------------