├── .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 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/banned_ips.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bin/pub/img/bell.svg:
--------------------------------------------------------------------------------
1 |
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 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/columns.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/config.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/country.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/data_center.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/delete.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/down.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/faq.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/flag.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/bin/pub/img/g_ip.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/general.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/google.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/har_viewer.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bin/pub/img/howto.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_admin.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_api.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_arrow_down.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_back.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_browse.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_browser.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_cancel.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_checkmark.svg:
--------------------------------------------------------------------------------
1 |
2 |
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 |
2 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_copy.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_download.svg:
--------------------------------------------------------------------------------
1 |
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 |
8 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_filter.svg:
--------------------------------------------------------------------------------
1 |
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 |
9 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_how_to.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_off.svg:
--------------------------------------------------------------------------------
1 |
2 |
24 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_refresh.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_remove.svg:
--------------------------------------------------------------------------------
1 |
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 |
9 |
--------------------------------------------------------------------------------
/bin/pub/img/ic_warning.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bin/pub/img/info.svg:
--------------------------------------------------------------------------------
1 |
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 |
30 |
--------------------------------------------------------------------------------
/bin/pub/img/logo_import.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
35 |
--------------------------------------------------------------------------------
/bin/pub/img/logs.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bin/pub/img/map_pin.svg:
--------------------------------------------------------------------------------
1 |
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 |
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 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/proxy_ext.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bin/pub/img/proxy_lum.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bin/pub/img/request_headers.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bin/pub/img/residential.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/rotation.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/rules.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bin/pub/img/sessions.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bin/pub/img/setup_guide.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/static_res.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/bin/pub/img/stats.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/stats_white.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/bin/pub/img/target.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/tester.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
--------------------------------------------------------------------------------
/bin/pub/img/tools.svg:
--------------------------------------------------------------------------------
1 |
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 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/warning.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/bin/pub/img/zipcode.svg:
--------------------------------------------------------------------------------
1 |
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 = ;
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 = ;
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 |
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 | }
--------------------------------------------------------------------------------