├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitattributes ├── .gitignore ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README-en_US.md ├── README.md ├── assets ├── fiddler │ └── meta.xml ├── js │ ├── log.js │ ├── weinre.js │ └── worker.js ├── launcher │ ├── README.md │ ├── linux │ │ ├── README.md │ │ └── whistle.gif │ ├── mac │ │ ├── README.md │ │ ├── whistle-desktop.gif │ │ ├── whistle.gif │ │ └── whistle.zip │ └── windows │ │ ├── README.md │ │ ├── whistle.gif │ │ └── whistle.zip ├── menu.html ├── modal.html └── tab.html ├── bin ├── ca │ ├── cli.js │ ├── index.d.ts │ └── index.js ├── import.js ├── plugin.d.ts ├── plugin.js ├── proxy.js ├── status.js ├── use.js ├── util.js └── whistle.js ├── biz ├── index.js ├── init.js ├── webui │ ├── cgi-bin │ │ ├── abort.js │ │ ├── add-rules-values.js │ │ ├── certs │ │ │ ├── all.js │ │ │ ├── remove.js │ │ │ └── upload.js │ │ ├── check-update.js │ │ ├── composer.js │ │ ├── cookies.js │ │ ├── create-cert.js │ │ ├── custom-frames.js │ │ ├── custom-handler.js │ │ ├── do-not-show-again.js │ │ ├── download.js │ │ ├── enable-http2.js │ │ ├── get-cert.js │ │ ├── get-custom-certs-files.js │ │ ├── get-custom-certs-info.js │ │ ├── get-data.js │ │ ├── get-frames.js │ │ ├── get-session.js │ │ ├── hide-https-connects.js │ │ ├── history.js │ │ ├── https-status.js │ │ ├── import-remote.js │ │ ├── init.js │ │ ├── intercept-https-connects.js │ │ ├── log │ │ │ └── set.js │ │ ├── plugins │ │ │ ├── add-registry.js │ │ │ ├── disable-all-plugins.js │ │ │ ├── disable-plugin.js │ │ │ ├── get-plugins.js │ │ │ ├── install.js │ │ │ ├── is-enable.js │ │ │ ├── registry-list.js │ │ │ ├── uninstall.js │ │ │ └── update-rules.js │ │ ├── reset-local-address.js │ │ ├── rootca.js │ │ ├── rules │ │ │ ├── account.js │ │ │ ├── add.js │ │ │ ├── allow-multiple-choice.js │ │ │ ├── disable-all-rules.js │ │ │ ├── disable-default.js │ │ │ ├── enable-back-rules-first.js │ │ │ ├── enable-default.js │ │ │ ├── export.js │ │ │ ├── import.js │ │ │ ├── index.js │ │ │ ├── list.js │ │ │ ├── list2.js │ │ │ ├── move-to.js │ │ │ ├── project.js │ │ │ ├── recycle │ │ │ │ ├── list.js │ │ │ │ ├── remove.js │ │ │ │ └── view.js │ │ │ ├── remove.js │ │ │ ├── rename.js │ │ │ ├── select.js │ │ │ ├── set-sys-hosts.js │ │ │ └── unselect.js │ │ ├── server-info.js │ │ ├── sessions │ │ │ ├── create-temp-file.js │ │ │ ├── expimp.js │ │ │ ├── export.js │ │ │ ├── get-temp-file.js │ │ │ └── import.js │ │ ├── set-custom-column.js │ │ ├── set-dns-order.js │ │ ├── set-ipv6-only.js │ │ ├── socket │ │ │ ├── abort.js │ │ │ ├── change-status.js │ │ │ └── data.js │ │ ├── status.js │ │ ├── top.js │ │ ├── util.js │ │ └── values │ │ │ ├── add.js │ │ │ ├── download.js │ │ │ ├── export.js │ │ │ ├── get.js │ │ │ ├── import.js │ │ │ ├── index.js │ │ │ ├── list.js │ │ │ ├── list2.js │ │ │ ├── move-to.js │ │ │ ├── recycle │ │ │ ├── list.js │ │ │ ├── remove.js │ │ │ └── view.js │ │ │ ├── remove.js │ │ │ ├── rename.js │ │ │ └── value.js │ ├── htdocs.js │ ├── htdocs │ │ ├── editor.html │ │ ├── img │ │ │ ├── app │ │ │ │ ├── alipay.png │ │ │ │ ├── amap.png │ │ │ │ ├── android.png │ │ │ │ ├── baidu.png │ │ │ │ ├── brave.png │ │ │ │ ├── browser.png │ │ │ │ ├── cfnetwork.png │ │ │ │ ├── chrome.png │ │ │ │ ├── cicc.png │ │ │ │ ├── cronet.png │ │ │ │ ├── dingtalk.png │ │ │ │ ├── edge.png │ │ │ │ ├── electron.png │ │ │ │ ├── firefox.png │ │ │ │ ├── huawei.png │ │ │ │ ├── iphone.png │ │ │ │ ├── jd.png │ │ │ │ ├── mac.png │ │ │ │ ├── opera.png │ │ │ │ ├── pdd.png │ │ │ │ ├── qq.png │ │ │ │ ├── safari.png │ │ │ │ ├── taobao.png │ │ │ │ ├── tmall.png │ │ │ │ ├── uc.png │ │ │ │ ├── wechat.png │ │ │ │ ├── weibo.png │ │ │ │ ├── wework.png │ │ │ │ └── windows.png │ │ │ ├── favicon.ico │ │ │ └── whistle.png │ │ ├── index.html │ │ ├── js │ │ │ ├── decode.js │ │ │ └── index.js │ │ ├── preview.html │ │ └── src │ │ │ ├── css │ │ │ ├── about.css │ │ │ ├── base.css │ │ │ ├── btn-group.css │ │ │ ├── certs.css │ │ │ ├── composer.css │ │ │ ├── context-menu.css │ │ │ ├── detail.css │ │ │ ├── divider.css │ │ │ ├── dropdown.css │ │ │ ├── editor-settings.css │ │ │ ├── editor.css │ │ │ ├── export-dialog.css │ │ │ ├── files-dialog.css │ │ │ ├── filter-input.css │ │ │ ├── frames.css │ │ │ ├── iframe-dialog.css │ │ │ ├── iframe.css │ │ │ ├── image-view.css │ │ │ ├── import-dialog.css │ │ │ ├── index.css │ │ │ ├── json-viewer.css │ │ │ ├── kv.css │ │ │ ├── large-dialog.css │ │ │ ├── list-dialog.css │ │ │ ├── list.css │ │ │ ├── menu-item.css │ │ │ ├── message.css │ │ │ ├── modal.css │ │ │ ├── network-settings.css │ │ │ ├── online.css │ │ │ ├── overview.css │ │ │ ├── plugins-mgr.css │ │ │ ├── plugins.css │ │ │ ├── properties.css │ │ │ ├── props-editor.css │ │ │ ├── record-btn.css │ │ │ ├── req-data.css │ │ │ ├── req-detail.css │ │ │ ├── res-detail.css │ │ │ ├── service.css │ │ │ ├── sync-dialog.css │ │ │ ├── table.css │ │ │ ├── textarea.css │ │ │ ├── timeline.css │ │ │ └── tools.css │ │ │ ├── js │ │ │ ├── about.js │ │ │ ├── base-css.js │ │ │ ├── bridge.js │ │ │ ├── btn-group.js │ │ │ ├── certs-info-dialog.js │ │ │ ├── cgi.js │ │ │ ├── columns.js │ │ │ ├── components │ │ │ │ ├── json │ │ │ │ │ ├── index.js │ │ │ │ │ ├── parse.js │ │ │ │ │ └── stringify.js │ │ │ │ └── react-json-tree │ │ │ │ │ ├── ItemRange.js │ │ │ │ │ ├── JSONArrayNode.js │ │ │ │ │ ├── JSONArrow.js │ │ │ │ │ ├── JSONIterableNode.js │ │ │ │ │ ├── JSONNestedNode.js │ │ │ │ │ ├── JSONNode.js │ │ │ │ │ ├── JSONObjectNode.js │ │ │ │ │ ├── JSONValueNode.js │ │ │ │ │ ├── createStylingFromTheme.js │ │ │ │ │ ├── getCollectionEntries.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── objType.js │ │ │ │ │ ├── themes │ │ │ │ │ └── solarized.js │ │ │ │ │ └── utils │ │ │ │ │ └── hexToRgb.js │ │ │ ├── composer-list.js │ │ │ ├── composer.js │ │ │ ├── console.js │ │ │ ├── context-menu.js │ │ │ ├── cookies-dialog.js │ │ │ ├── copy-btn.js │ │ │ ├── data-center.js │ │ │ ├── decode.js │ │ │ ├── detail-dialog.js │ │ │ ├── detail.js │ │ │ ├── dialog.js │ │ │ ├── divider.js │ │ │ ├── dns-servers-dialog.js │ │ │ ├── dropdown.js │ │ │ ├── editor-dialog.js │ │ │ ├── editor-settings.js │ │ │ ├── editor.js │ │ │ ├── enable-https-btn.js │ │ │ ├── events.js │ │ │ ├── expand-collapse.js │ │ │ ├── export-dialog.js │ │ │ ├── filter-btn.js │ │ │ ├── filter-input.js │ │ │ ├── forward-back-btn.js │ │ │ ├── frame-composer.js │ │ │ ├── frame-data.js │ │ │ ├── frame-list.js │ │ │ ├── frame-modal.js │ │ │ ├── frames.js │ │ │ ├── github-icon.js │ │ │ ├── history-data.js │ │ │ ├── https-settings.js │ │ │ ├── iframe-dialog.js │ │ │ ├── iframe.js │ │ │ ├── iframes.js │ │ │ ├── image-view.js │ │ │ ├── import-dialog.js │ │ │ ├── index.js │ │ │ ├── inspector.js │ │ │ ├── inspectors.js │ │ │ ├── is-utf8.js │ │ │ ├── json-dialog.js │ │ │ ├── json-viewer.js │ │ │ ├── kv-dialog.js │ │ │ ├── large-dialog.js │ │ │ ├── lazy-init.js │ │ │ ├── list-dialog.js │ │ │ ├── list-modal.js │ │ │ ├── list.js │ │ │ ├── menu-item.js │ │ │ ├── message.js │ │ │ ├── mock-dialog.js │ │ │ ├── modal.js │ │ │ ├── network-modal.js │ │ │ ├── network-settings.js │ │ │ ├── network.js │ │ │ ├── online.js │ │ │ ├── overview.js │ │ │ ├── panel-tips.js │ │ │ ├── parse-curl.js │ │ │ ├── parse-rules.js │ │ │ ├── plugins-mgr.js │ │ │ ├── plugins-tabs.js │ │ │ ├── plugins.js │ │ │ ├── properties.js │ │ │ ├── props-editor.js │ │ │ ├── protocols.js │ │ │ ├── qrcode-dialog.js │ │ │ ├── qrcode.js │ │ │ ├── record-btn.js │ │ │ ├── recycle-bin.js │ │ │ ├── req-data.js │ │ │ ├── req-detail.js │ │ │ ├── res-detail.js │ │ │ ├── rule-list.js │ │ │ ├── rules-dialog.js │ │ │ ├── rules-hint.js │ │ │ ├── rules-mode.js │ │ │ ├── server-log.js │ │ │ ├── service-btn.js │ │ │ ├── share-via-url-btn.js │ │ │ ├── storage.js │ │ │ ├── sync-dialog.js │ │ │ ├── tab-frame.js │ │ │ ├── tab-mgr.js │ │ │ ├── table.js │ │ │ ├── tabs.js │ │ │ ├── text-dialog.js │ │ │ ├── textarea.js │ │ │ ├── textview.js │ │ │ ├── timeline.js │ │ │ ├── tips-dialog.js │ │ │ ├── token-dialog.js │ │ │ ├── tool-box.js │ │ │ ├── tools.js │ │ │ ├── update-all-btn.js │ │ │ ├── util.js │ │ │ ├── win.js │ │ │ └── workers.js │ │ │ └── webpack.config.js │ └── lib │ │ ├── index.js │ │ └── proxy.js └── weinre │ ├── index.js │ └── server.js ├── docs ├── assets │ ├── host01.png │ ├── host02.png │ └── whistle-en_US.png ├── i18n │ ├── en │ │ └── README.md │ └── zh │ │ ├── README.md │ │ ├── about.md │ │ ├── cli │ │ ├── README.md │ │ ├── add.md │ │ ├── ca.md │ │ ├── env.md │ │ ├── exec.md │ │ ├── install.md │ │ ├── proxy.md │ │ ├── start.md │ │ └── status.md │ │ ├── extensions │ │ ├── README.md │ │ ├── npm │ │ │ ├── README.md │ │ │ ├── api.md │ │ │ └── dev.md │ │ └── plugins │ │ │ ├── README.md │ │ │ ├── api.md │ │ │ ├── dev.md │ │ │ └── install.md │ │ ├── feedback.md │ │ ├── mobile │ │ ├── README.md │ │ ├── android.md │ │ └── ios.md │ │ ├── pc │ │ ├── README.md │ │ ├── firefox.md │ │ ├── mac.md │ │ ├── others.md │ │ ├── switchyomega.md │ │ └── windows.md │ │ ├── quickstart.md │ │ ├── rules │ │ ├── README.md │ │ ├── filters │ │ │ └── README.md │ │ ├── modify │ │ │ ├── README.md │ │ │ ├── request │ │ │ │ └── README.md │ │ │ └── response │ │ │ │ └── README.md │ │ ├── pattern │ │ │ └── README.md │ │ └── values │ │ │ └── README.md │ │ ├── update.md │ │ └── webui │ │ ├── README.md │ │ ├── about.md │ │ ├── files.md │ │ ├── https.md │ │ ├── network.md │ │ ├── online.md │ │ ├── plugins.md │ │ ├── rules.md │ │ └── values.md └── zh │ ├── README.md │ ├── SUMMARY.md │ ├── attention.md │ ├── book.json │ ├── cases.md │ ├── cli.md │ ├── custom-certs.md │ ├── data.md │ ├── feedback.md │ ├── frequet.md │ ├── gitbook │ └── images │ │ ├── apple-touch-icon-precomposed-152.png │ │ └── favicon.ico │ ├── img │ ├── Android_proxy.png │ ├── composer.gif │ ├── firefox-proxy-1.jpg │ ├── firefox-proxy-2.jpg │ ├── host01.png │ ├── host02.png │ ├── http-request.png │ ├── https.gif │ ├── iOS-proxy-all.jpg │ ├── iOS-proxy.jpg │ ├── iOS_proxy.PNG │ ├── iOS_proxy_settings.png │ ├── ios10.3_ca.PNG │ ├── linux-proxy-1.jpg │ ├── linux-proxy-2.jpg │ ├── log-basic.gif │ ├── log-switch.gif │ ├── mac-proxy-1.jpg │ ├── mac-proxy-2.jpg │ ├── network.gif │ ├── online.gif │ ├── plugin-list.png │ ├── plugin1.png │ ├── plugin2.png │ ├── plugin3.png │ ├── plugins.gif │ ├── rules.gif │ ├── seq.png │ ├── settings.png │ ├── start_w2.jpg │ ├── switchyomega.jpg │ ├── tunnel-request.png │ ├── values.gif │ ├── weinre.gif │ └── windows_rootca.jpeg │ ├── install.md │ ├── mode-options.md │ ├── mode.md │ ├── options.md │ ├── pattern.md │ ├── plugins.md │ ├── principle.md │ ├── proxy.md │ ├── questions.md │ ├── quickstart.md │ ├── rules │ ├── @.md │ ├── README.md │ ├── accept.md │ ├── attachment.md │ ├── auth.md │ ├── cache.md │ ├── cipher.md │ ├── css.md │ ├── cssAppend.md │ ├── cssBody.md │ ├── cssPrepend.md │ ├── delete.md │ ├── disable.md │ ├── dispatch.md │ ├── enable.md │ ├── etag.md │ ├── filter.md │ ├── forwardedFor.md │ ├── headerReplace.md │ ├── host.md │ ├── hostname.md │ ├── html.md │ ├── htmlAppend.md │ ├── htmlBody.md │ ├── htmlPrepend.md │ ├── http-proxy.md │ ├── https-proxy.md │ ├── ignore.md │ ├── js.md │ ├── jsAppend.md │ ├── jsBody.md │ ├── jsPrepend.md │ ├── lineProps.md │ ├── location.md │ ├── log.md │ ├── method.md │ ├── pac.md │ ├── params.md │ ├── pathReplace.md │ ├── pipe.md │ ├── plugin.md │ ├── proxy.md │ ├── referer.md │ ├── replaceStatus.md │ ├── req.md │ ├── reqAppend.md │ ├── reqBody.md │ ├── reqCharset.md │ ├── reqCookies.md │ ├── reqCors.md │ ├── reqDelay.md │ ├── reqHeaders.md │ ├── reqMerge.md │ ├── reqPrepend.md │ ├── reqReplace.md │ ├── reqScript.md │ ├── reqSpeed.md │ ├── reqType.md │ ├── reqWrite.md │ ├── reqWriteRaw.md │ ├── res.md │ ├── resAppend.md │ ├── resBody.md │ ├── resCharset.md │ ├── resCookies.md │ ├── resCors.md │ ├── resDelay.md │ ├── resHeaders.md │ ├── resMerge.md │ ├── resPrepend.md │ ├── resReplace.md │ ├── resScript.md │ ├── resSpeed.md │ ├── resType.md │ ├── resWrite.md │ ├── resWriteRaw.md │ ├── responseFor.md │ ├── rule │ │ ├── README.md │ │ ├── custom.md │ │ ├── file.md │ │ ├── locationHref.md │ │ ├── rawfile.md │ │ ├── redirect.md │ │ ├── replace.md │ │ ├── statusCode.md │ │ ├── tpl.md │ │ ├── xfile.md │ │ ├── xrawfile.md │ │ └── xtpl.md │ ├── rulesFile.md │ ├── sniCallback.md │ ├── socks.md │ ├── statusCode.md │ ├── style.md │ ├── trailers.md │ ├── ua.md │ ├── urlParams.md │ └── weinre.md │ ├── template.md │ ├── update.md │ └── webui │ ├── README.md │ ├── composer.md │ ├── filter.md │ ├── https.md │ ├── log.md │ ├── mock.md │ ├── network.md │ ├── online.md │ ├── plugins.md │ ├── rules.md │ ├── settings.md │ ├── values.md │ ├── websocket.md │ └── weinre.md ├── index.d.ts ├── index.js ├── lib ├── config.js ├── handlers │ ├── error-handler.js │ ├── file-proxy.js │ ├── final-handler.js │ ├── http-proxy.js │ ├── index.js │ └── plugin-handler.js ├── https │ ├── ca.js │ ├── h2.js │ ├── index.js │ └── load-cert.js ├── index.js ├── init.js ├── inspectors │ ├── data.js │ ├── index.js │ ├── log.js │ ├── req.js │ ├── res.js │ ├── rules.js │ └── weinre.js ├── plugins │ ├── get-plugins-sync.js │ ├── get-plugins.js │ ├── index.js │ ├── load-plugin.js │ ├── module-paths.js │ ├── proxy.js │ ├── shared-storage.js │ └── util.js ├── rules │ ├── dns.js │ ├── index.js │ ├── protocols.js │ ├── recycle-bin.js │ ├── rules.js │ ├── storage.js │ └── util.js ├── service │ ├── data-center.js │ ├── extract-saz.js │ ├── generate-saz.js │ ├── index.js │ ├── installer.js │ ├── plugin.js │ ├── service.js │ └── util.js ├── socket-mgr.js ├── tunnel.js ├── upgrade.js └── util │ ├── buf-util.js │ ├── common.js │ ├── data-server.js │ ├── drain.js │ ├── file-mgr.js │ ├── file-writer-transform.js │ ├── http-mgr.js │ ├── index.js │ ├── is-utf8.js │ ├── log-server.js │ ├── logger.js │ ├── parse-query.js │ ├── parse-url-safe.js │ ├── parse-url.js │ ├── patch.js │ ├── perf.js │ ├── process.js │ ├── replace-pattern-transform.js │ ├── replace-string-transform.js │ ├── speed-transform.js │ ├── transproto.js │ ├── whistle-transform.js │ └── zlib.js ├── package-lock.json ├── package.json ├── require.js └── test ├── assets ├── certs │ ├── _.cert.w2.org.crt │ ├── _.cert.w2.org.key │ ├── _root.crt │ ├── cert.w2.org.key │ ├── root.key │ ├── test.crt │ └── test.key ├── files │ ├── 1.txt │ ├── 2.txt │ ├── 3.txt │ ├── empty.txt │ ├── gb2312.txt │ ├── rules.txt │ ├── storage │ │ ├── .backup │ │ │ ├── 1.test1.tx │ │ │ ├── 2.test2.tx │ │ │ ├── 3.test3.tx │ │ │ └── properties │ │ ├── files │ │ │ ├── 1.test1.tx │ │ │ ├── 2.test2.tx │ │ │ └── 3.test3.tx │ │ └── properties │ └── test.txt └── values │ ├── rawFile.html │ ├── rawFile2.js │ ├── reqScript.js │ ├── resScript.js │ ├── rulesFile.js │ ├── rulesFile.txt │ ├── rulesFile2.js │ ├── test.json │ ├── test2.json │ ├── test3.json │ ├── tps.rules │ ├── tps1.json │ └── tps2.json ├── config.test.js ├── events.js ├── index.test.js ├── plugins ├── @test │ └── whistle.test3 │ │ ├── index.js │ │ ├── package.json │ │ ├── rules.txt │ │ └── test │ │ └── abc │ │ ├── abc │ │ └── index.html │ │ └── index.html ├── whistle.pipe-http │ ├── index.js │ ├── lib │ │ ├── reqReadServer.js │ │ ├── reqWriteServer.js │ │ ├── resReadServer.js │ │ └── resWriteServer.js │ ├── package.json │ └── rules.txt ├── whistle.pipe-tunnel │ ├── index.js │ ├── lib │ │ ├── tunnelReqRead.js │ │ ├── tunnelReqWrite.js │ │ ├── tunnelResRead.js │ │ └── tunnelResWrite.js │ ├── package.json │ └── rules.txt ├── whistle.pipe-ws │ ├── index.js │ ├── lib │ │ ├── wsReqRead.js │ │ ├── wsReqWrite.js │ │ ├── wsResRead.js │ │ └── wsResWrite.js │ ├── package.json │ └── rules.txt ├── whistle.test-values │ ├── index.js │ ├── package.json │ └── rules.txt ├── whistle.test │ ├── _rules.txt │ ├── assets │ │ ├── dispatch.js │ │ ├── files │ │ │ ├── append.txt │ │ │ ├── bin │ │ │ │ ├── body.txt │ │ │ │ ├── bottom.txt │ │ │ │ ├── file.txt │ │ │ │ └── top.txt │ │ │ ├── body.txt │ │ │ ├── css.css │ │ │ ├── html.html │ │ │ ├── index.html │ │ │ ├── js.js │ │ │ ├── log.js │ │ │ ├── pac.js │ │ │ ├── prepend.txt │ │ │ ├── rawfile.html │ │ │ ├── ssi-include.html │ │ │ ├── ssi1.html │ │ │ ├── ssi2.html │ │ │ ├── ssi3.html │ │ │ └── tpl.js │ │ └── values │ │ │ ├── headers.json │ │ │ ├── replace.json │ │ │ ├── req.json │ │ │ ├── reqCookies.json │ │ │ ├── reqCors.json │ │ │ ├── res.json │ │ │ ├── resCookies.json │ │ │ ├── resCors.json │ │ │ ├── upload.json │ │ │ ├── urlParams.json │ │ │ └── urlReplace.json │ ├── index.js │ ├── lib │ │ ├── resRulesServer.js │ │ ├── rulesServer.js │ │ ├── server.js │ │ ├── statusServer.js │ │ ├── tunnelRulesServer.js │ │ ├── tunnelServer.js │ │ ├── uiServer.js │ │ └── util.js │ ├── package.json │ └── rules.txt ├── whistle.test1 │ ├── _rules.txt │ ├── index.js │ ├── lib │ │ └── rulesServer.js │ ├── package.json │ └── rules.txt └── whistle.test2 │ ├── _rules.txt │ ├── index.js │ ├── package.json │ ├── rules.txt │ └── test.txt ├── proxy ├── disable.test.js └── enable.test.js ├── rules.txt ├── units ├── _normalizeConnectArgs.test.js ├── attachment.test.js ├── auth.test.js ├── cache.test.js ├── common.test.js ├── composer.test.js ├── connect.test.js ├── css.test.js ├── delete.test.js ├── disable.test.js ├── file.test.js ├── filter.test.js ├── fm.test.js ├── forward.test.js ├── host.test.js ├── html.test.js ├── https.test.js ├── ignore.test.js ├── insertFile.test.js ├── js.test.js ├── log.test.js ├── method.test.js ├── options.test.js ├── others.test.js ├── pac.test.js ├── params.test.js ├── plugin.test.js ├── plugins.test.js ├── proxy.test.js ├── range.test.js ├── rawfile.test.js ├── redirect.test.js ├── referer.test.js ├── replaceStatus.test.js ├── req.prepend.body.append.test.js ├── reqAppend.test.js ├── reqBody.test.js ├── reqCharset.test.js ├── reqCookies.test.js ├── reqCors.test.js ├── reqDelay.test.js ├── reqHeaders.test.js ├── reqPrepend.test.js ├── reqReplace.test.js ├── reqSpeed.test.js ├── reqType.test.js ├── res.prepend.body.append.test.js ├── resAppend.test.js ├── resBody.test.js ├── resCharset.test.js ├── resCookies.test.js ├── resCors.test.js ├── resDelay.test.js ├── resHeaders.test.js ├── resPrepend.test.js ├── resReplace.test.js ├── resSpeed.test.js ├── resType.test.js ├── rule.test.js ├── rulesFile.test.js ├── script.test.js ├── socks.test.js ├── ssi-include.test.js ├── statusCode.test.js ├── tpl.test.js ├── tplStr.test.js ├── tps.test.js ├── tunnel.test.js ├── tunnelPolicy.test.js ├── ua.test.js ├── ui.test.js ├── urlParams.test.js ├── urlReplace.test.js ├── utils.test.js ├── values.test.js ├── var.test.js ├── weinre.test.js ├── wildcard.test.js ├── write.test.js ├── ws.test.js └── xfile.test.js └── util.test.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env", 4 | "react" 5 | ], 6 | "plugins": [ 7 | "transform-class-properties", 8 | "transform-object-rest-spread" 9 | ], 10 | "ignore": [ 11 | "./biz/webui/htdocs/src/js/components/json/eval.js" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | max_line_length = 80 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | max_line_length = 0 15 | trim_trailing_whitespace = false 16 | 17 | [COMMIT_EDITMSG] 18 | max_line_length = 0 -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /biz/webui/htdocs/js 3 | /biz/webui/htdocs/src/js/components 4 | /test/assets/values 5 | /test/plugins/whistle.test/assets 6 | /bin/import.js 7 | /test/all_whistles 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | biz/webui/htdocs/js/index.js diff=nodiff 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "10" 4 | - "11" 5 | - "12" 6 | - "13" 7 | - "14" 8 | - "15" 9 | - "16" 10 | - "17" 11 | - "18" 12 | 13 | install: 14 | - npm install 15 | 16 | script: 17 | - npm run cov 18 | 19 | after_script: 20 | - npm i codecov && codecov 21 | -------------------------------------------------------------------------------- /assets/js/weinre.js: -------------------------------------------------------------------------------- 1 | 2 | ;(function() { 3 | if (typeof window === 'undefined' || window.WeinreServerURL) { 4 | return; 5 | } 6 | var prefixPath = window.__WHISTLE_PATH_PREFIX__; 7 | if (/^\/[\w./-]+$/.test(prefixPath) && prefixPath.length <= 128) { 8 | var len = prefixPath.length - 1; 9 | if (prefixPath[len] === '/') { 10 | prefixPath = prefixPath.substring(0, len); 11 | } 12 | } else { 13 | prefixPath = ''; 14 | } 15 | var baseUrl = '$BASE_URL' + prefixPath; 16 | window.WeinreServerURL = baseUrl + '$WEINRE_PATH'; 17 | var head = document.head || document.getElementsByTagName('head')[0] || document.documentElement; 18 | var script = document.createElement('script'); 19 | script.async = true; 20 | script.charset = 'utf8'; 21 | script.src = baseUrl + '$WEINRE_URL'; 22 | if (head.firstChild) { 23 | head.insertBefore(script, head.firstChild); 24 | } else { 25 | head.appendChild(script); 26 | } 27 | })(); 28 | -------------------------------------------------------------------------------- /assets/launcher/README.md: -------------------------------------------------------------------------------- 1 | # 配置开机重启whistle 2 | 由于whistle是用Node实现的一个命令行程序,相对于客户端程序安装过程多了[安装node、配置代理](https://avwo.github.io/whistle/install.html)这两个步骤及通过命令行启动服务器,而不是点击桌面图标启动,具体参见[安装启动whistle](https://avwo.github.io/whistle/install.html);命令行程序也有一个好处:可以部署在服务器上。事实上,通过把启动脚本写在脚本文件里面(如bat文件)并存在桌面也可以实现双击图标启动whistle,且将该脚本文件放在开机启动项可以实现开机自动重启,具体根据不同的操作系统采取不同的策略: 3 | 4 | 1. [Windows](windows) 5 | 2. [Mac](mac) 6 | 3. [Linux](linux) 7 | -------------------------------------------------------------------------------- /assets/launcher/linux/README.md: -------------------------------------------------------------------------------- 1 | # Linux上配置开机重启whistle 2 | 3 | Linux不完全支持双击脚本文件自动执行(需要whistle v1.0.0及以上版本),只能设置开机自动重启whistle,[安装完whistle](https://avwo.github.io/whistle/install.html)后执行`which w2`查看命令行安装的路径(一般为`/usr/local/bin/w2`),编辑启动执行的文件`sudo vi /etc/rc.d/rc.local`,在最后一行加入`/usr/local/bin/w2 restart`(`/usr/local/bin/w2`视`which w2`输出的字符串为准)。 4 | 5 | ![Linux开机重启whistle](whistle.gif) -------------------------------------------------------------------------------- /assets/launcher/linux/whistle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/assets/launcher/linux/whistle.gif -------------------------------------------------------------------------------- /assets/launcher/mac/README.md: -------------------------------------------------------------------------------- 1 | # Mac上配置开机重启whistle 2 | 首先,下载Mac上的whistle脚步文件:[whistle.zip](https://github.com/avwo/whistle/blob/master/assets/launcher/mac/whistle.zip)。 3 | 4 | 1. 解压whistle.zip获取whistle脚本文件,把该脚本文件拷贝一份到**应用程序**,打开桌面即可看到whistle这个脚本文件,这样可以直接在Mac的桌面上刊登whistle的启动脚本,点击该文件即可重启whistle; 5 | 6 | ![把whistle脚本文件放到Mac桌面](whistle-desktop.gif) 7 | 8 | 2. **打开设置 --> 打开用户与群组 --> 打开登录项 --> 点击下方的+按钮 --> 在应用程序目录里选择whistle --> 勾选上复选框**,这样就配置好了开机自动重启whistle。 9 | 10 | ![在Mac上配置开机重启whistle](whistle.gif) 11 | -------------------------------------------------------------------------------- /assets/launcher/mac/whistle-desktop.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/assets/launcher/mac/whistle-desktop.gif -------------------------------------------------------------------------------- /assets/launcher/mac/whistle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/assets/launcher/mac/whistle.gif -------------------------------------------------------------------------------- /assets/launcher/mac/whistle.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/assets/launcher/mac/whistle.zip -------------------------------------------------------------------------------- /assets/launcher/windows/README.md: -------------------------------------------------------------------------------- 1 | # Windows上配置开机重启whistle 2 | 首先,下载Windows上的whistle脚步文件:[whistle.zip](https://github.com/avwo/whistle/raw/master/assets/launcher/windows/whistle.zip)。 3 | 4 | 1. 解压whistle.zip获取whistle.bat的脚本文件,把该脚本文件拷贝一份到Windows的桌面,这样可以直接在Windows的桌面上看到whistle的启动脚本,双击即可重启whistle(会先弹出一个命令行窗口,等3秒左右就会自动消失); 5 | 6 | 2. 把桌面上的whistle.bat文件拖到桌面左下角的系统**开始菜单 --> 所有程序 --> 启动**目录下面,或者直接拷贝到系统目录`C:\Users\{yourAccount}\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup`(可以直接在开始菜单或者文件管理器中的输入框输入`%appData%\Microsoft\Windows\Start Menu\Programs\Startup`快速定位到启动菜单目录),这样就配置好了开机自动重启whistle。 7 | 8 | ![设置Windows开机重启whistle](whistle.gif) 9 | -------------------------------------------------------------------------------- /assets/launcher/windows/whistle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/assets/launcher/windows/whistle.gif -------------------------------------------------------------------------------- /assets/launcher/windows/whistle.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/assets/launcher/windows/whistle.zip -------------------------------------------------------------------------------- /bin/ca/index.d.ts: -------------------------------------------------------------------------------- 1 | export default function (certFile: String): void; 2 | -------------------------------------------------------------------------------- /bin/import.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | function importModle(filepath, callback) { 4 | return import(filepath).then(callback); 5 | } 6 | 7 | module.exports = function(filepath, callback) { 8 | try { 9 | return callback(require(filepath)); 10 | } catch (e) { 11 | var code =e && e.code; 12 | if (code === 'ERR_REQUIRE_ESM') { 13 | // ignore eslint & fix type=module 14 | return importModle(filepath, callback); 15 | } else if (code === 'MODULE_NOT_FOUND' && /\.js$/i.test(filepath)) { 16 | filepath = filepath.slice(0, -3) + '.mjs'; 17 | if (fs.existsSync(filepath)) { 18 | return importModle(filepath, callback); 19 | } 20 | } 21 | throw e; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /bin/plugin.d.ts: -------------------------------------------------------------------------------- 1 | 2 | export function getWhistlePath(): string; 3 | 4 | export function install(cmd: string, argv: string[]): void; 5 | 6 | export function uninstall(argv: string[]): void; 7 | -------------------------------------------------------------------------------- /biz/init.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var ui = require('./webui/lib'); 3 | var util = require('../lib/util'); 4 | 5 | module.exports = function init(proxy, callback) { 6 | var config = proxy.config; 7 | ui.init(proxy); 8 | if (config.customUIPort) { 9 | var server = http.createServer(); 10 | ui.setupServer(server); 11 | util.getBoundIp(config.uihost, function(host) { 12 | if (host) { 13 | config.customUIHost = host; 14 | server.listen(config.uiport, host, callback); 15 | } else { 16 | server.listen(config.uiport, callback); 17 | } 18 | }); 19 | } else { 20 | callback(); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/abort.js: -------------------------------------------------------------------------------- 1 | var proxy = require('../lib/proxy'); 2 | var socketMgr = proxy.socketMgr; 3 | 4 | function abort(reqId) { 5 | proxy.abortRequest(reqId); 6 | socketMgr.abort(reqId); 7 | } 8 | 9 | module.exports = function(req, res) { 10 | var list = req.body.list; 11 | if (list && typeof list === 'string') { 12 | list.split(',').forEach(abort); 13 | } 14 | res.json({ ec: 0 }); 15 | }; 16 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/add-rules-values.js: -------------------------------------------------------------------------------- 1 | var rules = require('../../../lib/rules/util').rules; 2 | var values = require('../../../lib/rules/util').values; 3 | 4 | module.exports = function(req, res) { 5 | var body = req.body; 6 | var clientId = body.clientId; 7 | var rulesData = body.rules; 8 | var valuesData = body.values; 9 | if (rulesData) { 10 | if (rulesData.name === 'Default') { 11 | rules.setDefault(rulesData.value, clientId); 12 | rules.enableDefault(); 13 | } else { 14 | rules.add(rulesData.name, rulesData.value, clientId); 15 | rules.select(rulesData.name); 16 | } 17 | } 18 | if (valuesData) { 19 | values.add(valuesData.name, valuesData.value, clientId); 20 | } 21 | res.json({ec: 0, em: 'success'}); 22 | }; 23 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/certs/all.js: -------------------------------------------------------------------------------- 1 | var ca = require('../../../../lib/https/ca'); 2 | 3 | module.exports = function(req, res) { 4 | res.json({ 5 | certs: ca.getCustomCertsFiles(), 6 | dir: ca.CUSTOM_CERTS_DIR 7 | }); 8 | }; 9 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/certs/remove.js: -------------------------------------------------------------------------------- 1 | var ca = require('../../../../lib/https/ca'); 2 | 3 | 4 | module.exports = function(req, res) { 5 | ca.removeCert(req.body); 6 | var isparsed = req.query.dataType === 'parsed'; 7 | res.json(isparsed ? ca.getCustomCertsInfo() : ca.getCustomCertsFiles()); 8 | }; 9 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/certs/upload.js: -------------------------------------------------------------------------------- 1 | var ca = require('../../../../lib/https/ca'); 2 | 3 | 4 | module.exports = function(req, res) { 5 | ca.uploadCerts(req.body); 6 | var isparsed = req.query.dataType === 'parsed'; 7 | res.json(isparsed ? ca.getCustomCertsInfo() : ca.getCustomCertsFiles()); 8 | }; 9 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/cookies.js: -------------------------------------------------------------------------------- 1 | var sendGzip = require('./util').sendGzip; 2 | var proxy = require('../lib/proxy'); 3 | 4 | module.exports = function(req, res) { 5 | sendGzip(req, res, { 6 | ec: 0, 7 | cookies: proxy.getCookiesByDomain(req.query.domain) 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/custom-frames.js: -------------------------------------------------------------------------------- 1 | var proxy = require('../lib/proxy'); 2 | var socketMgr = proxy.socketMgr; 3 | 4 | module.exports = function(req, res) { 5 | var result = {}; 6 | req.body.idList.forEach(function(reqId) { 7 | result[reqId] = socketMgr.getData(reqId); 8 | }); 9 | req.body.frames.forEach(function(frame) { 10 | proxy.emit('frame', frame); 11 | }); 12 | res.json(result); 13 | }; 14 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/custom-handler.js: -------------------------------------------------------------------------------- 1 | var config = require('../../../lib/config'); 2 | 3 | module.exports = function(req, res) { 4 | if (!config.customHandler) { 5 | return res.sendStatus(404); 6 | } 7 | config.customHandler(req, res); 8 | }; 9 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/do-not-show-again.js: -------------------------------------------------------------------------------- 1 | var properties = require('../../../lib/rules/util').properties; 2 | 3 | module.exports = function(req, res) { 4 | properties.set('doNotShowAgainVersion', properties.getLatestVersion('latestVersion')); 5 | res.json({ec: 0, em: 'success'}); 6 | }; 7 | 8 | 9 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/enable-http2.js: -------------------------------------------------------------------------------- 1 | var properties = require('../../../lib/rules/util').properties; 2 | 3 | module.exports = function(req, res) { 4 | properties.setEnableHttp2(req.body.enableHttp2 == 1); 5 | res.json({ec: 0, em: 'success'}); 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/get-cert.js: -------------------------------------------------------------------------------- 1 | var ca = require('../../../lib/https/ca'); 2 | 3 | var URL_RE = /^(?:(?:[\w.-]+:)?\/\/)?([\w.-]+)/i; 4 | 5 | function parseDomain(domain) { 6 | domain = domain && typeof domain === 'string' && domain.trim(); 7 | if (!domain || domain.length > 64 || !URL_RE.test(domain)) { 8 | return; 9 | } 10 | return RegExp.$1; 11 | } 12 | 13 | module.exports = function(req, res) { 14 | var domain = parseDomain(req.query.domain); 15 | if (!domain) { 16 | return res.status(400).end('Bad Request'); 17 | } 18 | if (domain === 'rootCA') { 19 | return res.json(ca.getRootCA()); 20 | } 21 | res.json(ca.createCertificate(domain.toLowerCase())); 22 | }; 23 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/get-custom-certs-files.js: -------------------------------------------------------------------------------- 1 | var getCustomCertsFiles = require('../../../lib/https/ca').getCustomCertsFiles; 2 | 3 | module.exports = function(req, res) { 4 | res.json(getCustomCertsFiles()); 5 | }; 6 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/get-custom-certs-info.js: -------------------------------------------------------------------------------- 1 | var getCustomCertsInfo = require('../../../lib/https/ca').getCustomCertsInfo; 2 | // 给第三方用的,不能删除 3 | module.exports = function(req, res) { 4 | res.json(getCustomCertsInfo()); 5 | }; 6 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/get-frames.js: -------------------------------------------------------------------------------- 1 | var proxy = require('../lib/proxy'); 2 | var socketMgr = proxy.socketMgr; 3 | 4 | module.exports = function(req, res) { 5 | var frames = proxy.getFrames(req.query); 6 | if (frames && !frames.length && 7 | !socketMgr.exists(req.query.curReqId)) { 8 | frames = undefined; 9 | } 10 | res.json({ 11 | ec: 0, 12 | frames: frames 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/get-session.js: -------------------------------------------------------------------------------- 1 | var proxy = require('../lib/proxy'); 2 | 3 | var emptyArr = []; 4 | var parseArray = function(str) { 5 | try { 6 | str = JSON.parse(str); 7 | return Array.isArray(str) ? str : emptyArr; 8 | } catch(e) {} 9 | return emptyArr; 10 | }; 11 | 12 | module.exports = function(req, res) { 13 | var reqList = parseArray(req.query.reqList); 14 | var resList = parseArray(req.query.resList); 15 | var result = {}; 16 | reqList.concat(resList).forEach(function(id) { 17 | if (result[id] != null) { 18 | return; 19 | } 20 | var item = proxy.getItem(id); 21 | if (!item) { 22 | result[id] = 0; 23 | return; 24 | } 25 | if ((item.requestTime && reqList.indexOf(id) !== -1) || item.endTime) { 26 | result[id] = item; 27 | } 28 | }); 29 | res.json(result); 30 | }; 31 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/hide-https-connects.js: -------------------------------------------------------------------------------- 1 | module.exports = function(req, res) { 2 | res.json({ec: 0, em: 'success'}); 3 | }; 4 | 5 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/history.js: -------------------------------------------------------------------------------- 1 | var util = require('./util'); 2 | var properties = require('../../../lib/rules/util').properties; 3 | 4 | module.exports = function(req, res) { 5 | util.sendGzip(req, res, properties.getHistory()); 6 | }; 7 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/https-status.js: -------------------------------------------------------------------------------- 1 | var properties = require('../../../lib/rules/util').properties; 2 | 3 | module.exports = function(req, res) { 4 | res.json({ 5 | ec: 0, 6 | enableCapture: properties.isEnableCapture(), 7 | enableHttp2: properties.isEnableHttp2() 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/intercept-https-connects.js: -------------------------------------------------------------------------------- 1 | var properties = require('../../../lib/rules/util').properties; 2 | 3 | module.exports = function(req, res) { 4 | properties.setEnableCapture(req.body.interceptHttpsConnects == 1); 5 | res.json({ec: 0, em: 'success'}); 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/log/set.js: -------------------------------------------------------------------------------- 1 | var proxy = require('../../lib/proxy'); 2 | 3 | module.exports = function(req, res) { 4 | proxy.addLog(req.query); 5 | res.setHeader('content-type', 'image/png'); 6 | res.end(); 7 | }; 8 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/plugins/add-registry.js: -------------------------------------------------------------------------------- 1 | var pluginMgr = require('../../lib/proxy').pluginMgr; 2 | 3 | module.exports = function(req, res) { 4 | pluginMgr.addRegistry(req.body.registry); 5 | res.json({ec: 0}); 6 | }; 7 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/plugins/disable-all-plugins.js: -------------------------------------------------------------------------------- 1 | var properties = require('../../../../lib/rules/util').properties; 2 | var pluginMgr = require('../../lib/proxy').pluginMgr; 3 | 4 | module.exports = function(req, res) { 5 | properties.set('disabledAllPlugins', req.body.disabledAllPlugins == 1); 6 | pluginMgr.updateRules(); 7 | res.json({ec: 0, em: 'success'}); 8 | }; 9 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/plugins/disable-plugin.js: -------------------------------------------------------------------------------- 1 | var properties = require('../../../../lib/rules/util').properties; 2 | var pluginMgr = require('../../lib/proxy').pluginMgr; 3 | 4 | module.exports = function(req, res) { 5 | var disabledPlugins = properties.get('disabledPlugins') || {}; 6 | if (req.body.disabled == 1) { 7 | disabledPlugins[req.body.name] = 1; 8 | } else { 9 | delete disabledPlugins[req.body.name]; 10 | } 11 | properties.set('disabledPlugins', disabledPlugins); 12 | pluginMgr.updateRules(); 13 | res.json({ec: 0, data: disabledPlugins}); 14 | }; 15 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/plugins/get-plugins.js: -------------------------------------------------------------------------------- 1 | var properties = require('../../../../lib/rules/util').properties; 2 | var pluginMgr = require('../../lib/proxy').pluginMgr; 3 | 4 | module.exports = function(req, res) { 5 | res.json({ 6 | ec: 0, 7 | plugins: pluginMgr.getPlugins(), 8 | disabledPlugins: properties.get('disabledPlugins') || {}, 9 | disabledAllPlugins: properties.get('disabledAllPlugins') 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/plugins/install.js: -------------------------------------------------------------------------------- 1 | var config = require('../../../../lib/config'); 2 | var common = require('../../../../lib/util/common'); 3 | 4 | module.exports = function(req, res) { 5 | if (!config.installPlugins) { 6 | return res.status(404).end(); 7 | } 8 | var data = common.parsePlugins(req.body); 9 | data && config.installPlugins(data); 10 | res.json({ ec: 0, count: data ? data.pkgs.length : 0 }); 11 | }; 12 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/plugins/is-enable.js: -------------------------------------------------------------------------------- 1 | var pluginMgr = require('../../lib/proxy').pluginMgr; 2 | var config = require('../../../../lib/config'); 3 | 4 | module.exports = function(req, res) { 5 | var name = req.headers[config.PROXY_ID_HEADER]; 6 | res.json({ 7 | ec: 0, 8 | enable: !!name && !!pluginMgr.getPlugin(name + ':') 9 | }); 10 | }; 11 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/plugins/registry-list.js: -------------------------------------------------------------------------------- 1 | var pluginMgr = require('../../lib/proxy').pluginMgr; 2 | 3 | module.exports = function(req, res) { 4 | res.json({ ec: 0, list: pluginMgr.getRegistryList() }); 5 | }; 6 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/plugins/uninstall.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var fs = require('fs'); 3 | var pluginMgr = require('../../lib/proxy').pluginMgr; 4 | 5 | module.exports = function(req, res) { 6 | var plugin = pluginMgr.getModifiablePlugin(req.body.name); 7 | if (!plugin) { 8 | return res.json({ ec: 0 }); 9 | } 10 | var pkgPath = path.join(plugin.path, 'package.json'); 11 | var newPkgPath = pkgPath + '.' + Date.now(); 12 | var retry; 13 | var handleCb = function(err) { 14 | if (err && err.code !== 'ENOENT') { 15 | if (!retry) { 16 | retry = true; 17 | return fs.unlink(pkgPath, handleCb); 18 | } 19 | return res.json({ ec: 2, em: err.message || 'Error' }); 20 | } 21 | pluginMgr.refreshPlugins(); 22 | res.json({ ec: 0 }); 23 | }; 24 | fs.rename(pkgPath, newPkgPath, handleCb); 25 | }; 26 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/plugins/update-rules.js: -------------------------------------------------------------------------------- 1 | var config = require('../../../../lib/config'); 2 | var pluginMgr = require('../../lib/proxy').pluginMgr; 3 | 4 | module.exports = function(req, res) { 5 | var name = req.headers[config.PROXY_ID_HEADER]; 6 | pluginMgr.updatePluginRules(name); 7 | res.json({ec: 0}); 8 | }; 9 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/reset-local-address.js: -------------------------------------------------------------------------------- 1 | var util = require('../../../lib/util'); 2 | 3 | module.exports = function(req, res) { 4 | util.localIpCache.reset(); 5 | res.json({ec: 0, em: 'success'}); 6 | }; 7 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rootca.js: -------------------------------------------------------------------------------- 1 | var properties = require('../../../lib/rules/util').properties; 2 | var getRootCAFile = require('../../../lib/https/ca').getRootCAFile; 3 | 4 | module.exports = function(req, res) { 5 | var type = req.query.type; 6 | if (type !== 'crt' && type !== 'pem') { 7 | type = 'cer'; 8 | } 9 | if (req.query.enableHttps) { 10 | properties.setEnableCapture(true); 11 | } 12 | res.download(getRootCAFile(), 'rootCA.' + type); 13 | }; 14 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/account.js: -------------------------------------------------------------------------------- 1 | var getAccountRules = require('../../../../lib/rules/util').getAccountRules; 2 | 3 | module.exports = function(_, res) { 4 | res.json({ec: 0, rules: getAccountRules() }); 5 | }; 6 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/allow-multiple-choice.js: -------------------------------------------------------------------------------- 1 | var properties = require('../../../../lib/rules/util').properties; 2 | var proxy = require('../../lib/proxy'); 3 | 4 | module.exports = function(req, res) { 5 | var enable = req.body.allowMultipleChoice == 1; 6 | properties.set('allowMultipleChoice', enable); 7 | proxy.emit('rulesDataChange', 'allowMultipleChoice', enable); 8 | res.json({ec: 0, em: 'success'}); 9 | }; 10 | 11 | 12 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/disable-all-rules.js: -------------------------------------------------------------------------------- 1 | var properties = require('../../../../lib/rules/util').properties; 2 | var rules = require('../../../../lib/rules/util').rules; 3 | 4 | module.exports = function(req, res) { 5 | properties.set('disabledAllRules', req.body.disabledAllRules == 1); 6 | rules.parseRules(); 7 | res.json({ec: 0, em: 'success'}); 8 | }; 9 | 10 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/disable-default.js: -------------------------------------------------------------------------------- 1 | var rules = require('../../../../lib/rules/util').rules; 2 | 3 | module.exports = function(req, res) { 4 | rules.disableDefault(); 5 | res.json({ec: 0, em: 'success', defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList()}); 6 | }; 7 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/enable-back-rules-first.js: -------------------------------------------------------------------------------- 1 | var rules = require('../../../../lib/rules/util').rules; 2 | 3 | module.exports = function(req, res) { 4 | rules.enableBackRulesFirst(req.body.backRulesFirst === '1'); 5 | res.json({ec: 0, em: 'success'}); 6 | }; 7 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/enable-default.js: -------------------------------------------------------------------------------- 1 | var rules = require('../../../../lib/rules/util').rules; 2 | 3 | module.exports = function(req, res) { 4 | rules.enableDefault(); 5 | rules.setDefault(req.body.value, req.body.clientId); 6 | res.json({ec: 0, em: 'success', defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList()}); 7 | }; 8 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/export.js: -------------------------------------------------------------------------------- 1 | var rules = require('../../../../lib/rules/util').rules; 2 | var util = require('../util'); 3 | 4 | module.exports = function(req, res) { 5 | var exportRules = req.query.rules; 6 | try { 7 | exportRules = exportRules && JSON.parse(exportRules); 8 | } catch(e) { 9 | exportRules = null; 10 | } 11 | var result = {}; 12 | if (!exportRules || exportRules.Default) { 13 | var defaultRules = rules.getDefault() || ''; 14 | result.Default = defaultRules; 15 | } 16 | rules.list().forEach(function(file) { 17 | if (!exportRules || exportRules[file.name]) { 18 | result[file.name] = file.data; 19 | } 20 | }); 21 | var filename = req.query.filename; 22 | if (filename && typeof filename === 'string') { 23 | if (!/\.(txt|json)/i.test(filename)) { 24 | filename += '.txt'; 25 | } 26 | } else { 27 | filename = 'rules_' + util.formatDate() + '.txt'; 28 | } 29 | res.attachment(filename).send(JSON.stringify(result, null, ' ')); 30 | }; 31 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/import.js: -------------------------------------------------------------------------------- 1 | var get = require('./index'); 2 | var getReqData = require('../util').getReqData; 3 | var addRules = require('../../../../lib/rules/util').addRules; 4 | 5 | module.exports = function(req, res) { 6 | getReqData(req, function(err, result) { 7 | if (err) { 8 | res.status(200).json({ ec: 2, em: err.message }); 9 | } else { 10 | addRules(result.data, result.replace, req.query.clientId); 11 | res.json(get()); 12 | } 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/index.js: -------------------------------------------------------------------------------- 1 | var rules = require('../../../../lib/rules/util').rules; 2 | var properties = require('../../../../lib/rules/util').properties; 3 | 4 | module.exports = function get() { 5 | return { 6 | ec: 0, 7 | defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), 8 | defaultRules: rules.getDefault(), 9 | allowMultipleChoice: properties.get('allowMultipleChoice'), 10 | backRulesFirst: properties.get('backRulesFirst'), 11 | list: rules.list() 12 | }; 13 | }; 14 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/list.js: -------------------------------------------------------------------------------- 1 | var get = require('./index'); 2 | 3 | module.exports = function(req, res) { 4 | res.json(get()); 5 | }; 6 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/list2.js: -------------------------------------------------------------------------------- 1 | var get = require('./index'); 2 | 3 | module.exports = function(req, res) { 4 | var rules = get(); 5 | var data; 6 | if (req.query.order) { 7 | data = [{ 8 | name: 'Default', 9 | value: rules.defaultRules 10 | }]; 11 | rules.list.forEach(function(item) { 12 | data.push({ 13 | name: item.name, 14 | value: item.data 15 | }); 16 | }); 17 | } else { 18 | data = { 19 | Default: rules.defaultRules 20 | }; 21 | rules.list.forEach(function(item) { 22 | data[item.name] = item.data; 23 | }); 24 | } 25 | res.json(data); 26 | }; 27 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/move-to.js: -------------------------------------------------------------------------------- 1 | var rules = require('../../../../lib/rules/util').rules; 2 | 3 | module.exports = function(req, res) { 4 | var body = req.body; 5 | var result = rules.moveTo(body.from, body.to, body.clientId, body.group === 'true', body.toTop === 'true'); 6 | res.json({ec: result ? 0 : 2, em: 'success'}); 7 | }; 8 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/recycle/list.js: -------------------------------------------------------------------------------- 1 | var recycleBin = require('../../../../../lib/rules/util').rules.recycleBin; 2 | 3 | module.exports = function(req, res) { 4 | res.json({ 5 | ec: 0, 6 | list: recycleBin.list() 7 | }); 8 | }; 9 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/recycle/remove.js: -------------------------------------------------------------------------------- 1 | var recycleBin = require('../../../../../lib/rules/util').rules.recycleBin; 2 | 3 | module.exports = function(req, res) { 4 | recycleBin.remove(req.body.name); 5 | res.json({ 6 | ec: 0, 7 | list: recycleBin.list() 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/recycle/view.js: -------------------------------------------------------------------------------- 1 | var recycleBin = require('../../../../../lib/rules/util').rules.recycleBin; 2 | 3 | module.exports = function(req, res) { 4 | var item = recycleBin.getFile(req.query.name); 5 | res.json({ 6 | ec: item ? 0 : 3, 7 | data: item && item.data 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/remove.js: -------------------------------------------------------------------------------- 1 | var util = require('../../../../lib/rules/util'); 2 | 3 | module.exports = function(req, res) { 4 | util.removeBatch(util.rules, req.body); 5 | res.json({ec: 0, em: 'success'}); 6 | }; 7 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/rename.js: -------------------------------------------------------------------------------- 1 | var rules = require('../../../../lib/rules/util').rules; 2 | 3 | module.exports = function(req, res) { 4 | var body = req.body; 5 | rules.rename(body.name, body.newName, body.clientId); 6 | res.json({ec: 0, em: 'success'}); 7 | }; 8 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/select.js: -------------------------------------------------------------------------------- 1 | var rules = require('../../../../lib/rules/util').rules; 2 | 3 | module.exports = function(req, res) { 4 | var body = req.body; 5 | var exists = rules.exists(body.name); 6 | var changed; 7 | if (rules.add(body.name, body.value, body.clientId) && !exists) { 8 | var group = rules.getFirstGroup(); 9 | if (group) { 10 | rules.moveTo(body.name, group.name, body.clientId, null, true); 11 | changed = true; 12 | } 13 | } 14 | rules.select(req.body.name); 15 | res.json({ec: 0, em: 'success', defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList(), changed: changed}); 16 | }; 17 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/set-sys-hosts.js: -------------------------------------------------------------------------------- 1 | var rules = require('../../../../lib/rules/util').rules; 2 | 3 | module.exports = function(req, res) { 4 | rules.setSysHosts(req.body.hosts, function(err) { 5 | res.json({ec: err ? 2 : 0, em: err ? err.stack : 'success'}); 6 | }); 7 | }; 8 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/rules/unselect.js: -------------------------------------------------------------------------------- 1 | var rules = require('../../../../lib/rules/util').rules; 2 | 3 | module.exports = function(req, res) { 4 | rules.add(req.body.name, req.body.value); 5 | rules.unselect(req.body.name); 6 | res.json({ec: 0, em: 'success', defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList()}); 7 | }; 8 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/server-info.js: -------------------------------------------------------------------------------- 1 | var util = require('./util'); 2 | 3 | module.exports = function(req, res) { 4 | res.json({ec: 0, server: util.getServerInfo(req)}); 5 | }; 6 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/sessions/create-temp-file.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./expimp'); 2 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/sessions/expimp.js: -------------------------------------------------------------------------------- 1 | var loadService = require('../../lib/proxy').loadService; 2 | var transformReq = require('../../../../lib/util').transformReq; 3 | 4 | module.exports = function(req, res) { 5 | loadService(function(err, options) { 6 | if (err) { 7 | res.type('text').status(500).send(err.stack || err); 8 | } else { 9 | transformReq(req, res, options.port); 10 | } 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/sessions/export.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./expimp'); 2 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/sessions/get-temp-file.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./expimp'); 2 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/sessions/import.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./expimp'); 2 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/set-custom-column.js: -------------------------------------------------------------------------------- 1 | var util = require('../../../lib/util'); 2 | var properties = require('../../../lib/rules/util').properties; 3 | 4 | 5 | function updateName(name, value, key) { 6 | properties.set(name, util.isString(value) ? value.trim().toString(0, 16) : name); 7 | properties.set(name + 'Key', util.isString(key) ? key.trim().substring(0, 72) : ''); 8 | } 9 | 10 | module.exports = function(req, res) { 11 | var name = req.body.name; 12 | var value = req.body.value; 13 | if (name === 'Custom1' || name === 'Custom2') { 14 | updateName(name, value, req.body.key); 15 | } 16 | res.json({ ec: 0 }); 17 | }; 18 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/set-dns-order.js: -------------------------------------------------------------------------------- 1 | var properties = require('../../../lib/rules/util').properties; 2 | var config = require('../../../lib/config'); 3 | 4 | module.exports = function(req, res) { 5 | properties.setDnsOrder(req.body.order); 6 | res.json({ec: 0, order: config.dnsOrder}); 7 | }; -------------------------------------------------------------------------------- /biz/webui/cgi-bin/set-ipv6-only.js: -------------------------------------------------------------------------------- 1 | var properties = require('../../../lib/rules/util').properties; 2 | 3 | module.exports = function(req, res) { 4 | properties.setIPv6Only(req.body.checked); 5 | res.json({ec: 0, ipv6Only: req.body.checked}); 6 | }; 7 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/socket/abort.js: -------------------------------------------------------------------------------- 1 | var proxy = require('../../lib/proxy'); 2 | 3 | var socketMgr = proxy.socketMgr; 4 | 5 | module.exports = function(req, res) { 6 | var reqId = req.body.reqId; 7 | proxy.abortRequest(reqId); 8 | socketMgr.abort(req.body.reqId); 9 | res.json({ec: 0}); 10 | }; 11 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/socket/change-status.js: -------------------------------------------------------------------------------- 1 | var socketMgr = require('../../lib/proxy').socketMgr; 2 | 3 | module.exports = function(req, res) { 4 | socketMgr.changeStatus(req.body); 5 | res.json({ec: 0}); 6 | }; 7 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/socket/data.js: -------------------------------------------------------------------------------- 1 | var socketMgr = require('../../lib/proxy').socketMgr; 2 | 3 | module.exports = function(req, res) { 4 | var result = socketMgr.sendData(req.body); 5 | res.json({ec: result === false ? 3 : 0}); 6 | }; 7 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/status.js: -------------------------------------------------------------------------------- 1 | var config = require('../../../lib/config'); 2 | 3 | module.exports = function(_, res) { 4 | res.json({ 5 | storage: config.storage || '', 6 | client: config.client, 7 | whistleName: config.whistleName, 8 | name: config.name, 9 | version: config.version 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/top.js: -------------------------------------------------------------------------------- 1 | var proc = require('../../../lib/util/process'); 2 | 3 | module.exports = function(req, res) { 4 | res.json(proc); 5 | }; 6 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/add.js: -------------------------------------------------------------------------------- 1 | var values = require('../../../../lib/rules/util').values; 2 | var recycleBin = require('../../../../lib/rules/util').values.recycleBin; 3 | var isGroup = require('../../../../lib/util/common').isGroup; 4 | 5 | module.exports = function(req, res) { 6 | var body = req.body; 7 | var list; 8 | var exists = values.exists(body.name); 9 | if (values.add(body.name, body.value, body.clientId) != null) { 10 | if (isGroup(body.name)) { 11 | if (body.focusName) { 12 | values.moveTo(body.name, body.focusName, body.clientId); 13 | } 14 | } else if (body.groupName) { 15 | values.moveToGroup(body.name, body.groupName); 16 | } else if (!exists) { 17 | var group = values.getFirstGroup(); 18 | group && values.moveTo(body.name, group.name, body.clientId, null, true); 19 | } 20 | } 21 | if (req.body.recycleFilename) { 22 | recycleBin.remove(req.body.recycleFilename); 23 | list = recycleBin.list(); 24 | } 25 | res.json({ 26 | ec: 0, 27 | list: list 28 | }); 29 | }; 30 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/download.js: -------------------------------------------------------------------------------- 1 | var values = require('../../../../lib/rules/util').values; 2 | 3 | module.exports = function(req, res) { 4 | values.download(req.query.name, res); 5 | }; 6 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/export.js: -------------------------------------------------------------------------------- 1 | var values = require('../../../../lib/rules/util').values; 2 | var util = require('../util'); 3 | 4 | module.exports = function(req, res) { 5 | var exportValues = req.query.values; 6 | try { 7 | exportValues = exportValues && JSON.parse(exportValues); 8 | } catch(e) { 9 | exportValues = null; 10 | } 11 | var result = {}; 12 | values.list().forEach(function(file) { 13 | if (!exportValues || exportValues[file.name]) { 14 | result[file.name] = file.data; 15 | } 16 | }); 17 | var filename = req.query.filename; 18 | if (filename && typeof filename === 'string') { 19 | if (!/\.(txt|json)/i.test(filename)) { 20 | filename += '.txt'; 21 | } 22 | } else { 23 | filename = 'values_' + util.formatDate() + '.txt'; 24 | } 25 | res.attachment(filename).send(JSON.stringify(result, null, ' ')); 26 | }; 27 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/get.js: -------------------------------------------------------------------------------- 1 | var values = require('../../../../lib/rules/util').values; 2 | var properties = require('../../../../lib/rules/util').properties; 3 | 4 | module.exports = function(req, res) { 5 | res.json({ 6 | fontSize: properties.get('valuesFontSize'), 7 | theme: properties.get('valuesTheme'), 8 | showLineNumbers: properties.get('valuesShowLineNumbers'), 9 | values: values.list() 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/import.js: -------------------------------------------------------------------------------- 1 | var get = require('./index'); 2 | var getReqData = require('../util').getReqData; 3 | var addValues = require('../../../../lib/rules/util').addValues; 4 | 5 | module.exports = function(req, res) { 6 | getReqData(req, function(err, result) { 7 | if (err) { 8 | res.status(200).json({ ec: 2, em: err.message }); 9 | } else { 10 | addValues(result.data, result.replace, req.query.clientId); 11 | res.json(get()); 12 | } 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/index.js: -------------------------------------------------------------------------------- 1 | var rulesUtil = require('../../../../lib/rules/util'); 2 | var values = rulesUtil.values; 3 | 4 | module.exports = function get() { 5 | return { 6 | ec: 0, 7 | list: values.list() 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/list.js: -------------------------------------------------------------------------------- 1 | var get = require('./index'); 2 | 3 | module.exports = function(req, res) { 4 | res.json(get()); 5 | }; 6 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/list2.js: -------------------------------------------------------------------------------- 1 | var get = require('./index'); 2 | 3 | module.exports = function(req, res) { 4 | var data; 5 | if (req.query.order) { 6 | data = []; 7 | get().list.forEach(function(item) { 8 | data.push({ 9 | name: item.name, 10 | value: item.data 11 | }); 12 | }); 13 | } else { 14 | data = {}; 15 | get().list.forEach(function(item) { 16 | data[item.name] = item.data; 17 | }); 18 | } 19 | res.json(data); 20 | }; 21 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/move-to.js: -------------------------------------------------------------------------------- 1 | var values = require('../../../../lib/rules/util').values; 2 | 3 | module.exports = function(req, res) { 4 | var body = req.body; 5 | var result = values.moveTo(body.from, body.to, body.clientId, body.group === 'true'); 6 | res.json({ec: result ? 0 : 2, em: 'success'}); 7 | }; 8 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/recycle/list.js: -------------------------------------------------------------------------------- 1 | var recycleBin = require('../../../../../lib/rules/util').values.recycleBin; 2 | 3 | module.exports = function(req, res) { 4 | res.json({ 5 | ec: 0, 6 | list: recycleBin.list() 7 | }); 8 | }; 9 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/recycle/remove.js: -------------------------------------------------------------------------------- 1 | var recycleBin = require('../../../../../lib/rules/util').values.recycleBin; 2 | 3 | module.exports = function(req, res) { 4 | recycleBin.remove(req.body.name); 5 | res.json({ 6 | ec: 0, 7 | list: recycleBin.list() 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/recycle/view.js: -------------------------------------------------------------------------------- 1 | var recycleBin = require('../../../../../lib/rules/util').values.recycleBin; 2 | 3 | module.exports = function(req, res) { 4 | var item = recycleBin.getFile(req.query.name); 5 | res.json({ 6 | ec: item ? 0 : 3, 7 | data: item && item.data 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/remove.js: -------------------------------------------------------------------------------- 1 | var util = require('../../../../lib/rules/util'); 2 | 3 | module.exports = function(req, res) { 4 | util.removeBatch(util.values, req.body); 5 | res.json({ec: 0, em: 'success'}); 6 | }; 7 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/rename.js: -------------------------------------------------------------------------------- 1 | var values = require('../../../../lib/rules/util').values; 2 | 3 | module.exports = function(req, res) { 4 | var body = req.body; 5 | values.rename(body.name, body.newName, body.clientId); 6 | res.json({ec: 0, em: 'success'}); 7 | }; 8 | -------------------------------------------------------------------------------- /biz/webui/cgi-bin/values/value.js: -------------------------------------------------------------------------------- 1 | var values = require('../../../../lib/rules/util').values; 2 | 3 | module.exports = function(req, res) { 4 | res.json({ value: values.get(req.query.key) }); 5 | }; 6 | -------------------------------------------------------------------------------- /biz/webui/htdocs.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var ROOT = path.join(__dirname, 'htdocs'); 3 | 4 | function getHtmlFile(file) { 5 | return path.join(ROOT, file || ''); 6 | } 7 | 8 | exports.getHtmlFile = getHtmlFile; 9 | 10 | function getImgFile(file) { 11 | return path.join(ROOT, 'img', file || ''); 12 | } 13 | 14 | exports.getImgFile = getImgFile; 15 | 16 | function getJsFile(file) { 17 | return path.join(ROOT, 'js', file || ''); 18 | } 19 | 20 | exports.getJsFile = getJsFile; 21 | -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/alipay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/alipay.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/amap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/amap.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/android.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/baidu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/baidu.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/brave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/brave.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/browser.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/cfnetwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/cfnetwork.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/chrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/chrome.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/cicc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/cicc.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/cronet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/cronet.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/dingtalk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/dingtalk.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/edge.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/electron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/electron.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/firefox.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/huawei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/huawei.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/iphone.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/jd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/jd.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/mac.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/opera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/opera.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/pdd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/pdd.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/qq.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/safari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/safari.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/taobao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/taobao.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/tmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/tmall.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/uc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/uc.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/wechat.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/weibo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/weibo.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/wework.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/wework.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/app/windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/app/windows.png -------------------------------------------------------------------------------- /biz/webui/htdocs/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/favicon.ico -------------------------------------------------------------------------------- /biz/webui/htdocs/img/whistle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/img/whistle.png -------------------------------------------------------------------------------- /biz/webui/htdocs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Whistle Web Debugging Proxy 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/certs.css: -------------------------------------------------------------------------------- 1 | .w-certs-info-dialog { 2 | z-index: 1100; 3 | } 4 | 5 | .w-certs-info-dialog .modal-dialog { 6 | width: 1024px; 7 | } 8 | 9 | .w-certs-info-order { 10 | width: 50px; 11 | } 12 | .w-certs-info-validity { 13 | width: 330px; 14 | } 15 | .w-certs-info-status { 16 | width: 100px; 17 | } 18 | .w-cert-invalid th, 19 | .w-cert-invalid td { 20 | color: red; 21 | } 22 | 23 | .w-certs-info-filename a { 24 | font-size: 12px; 25 | cursor: pointer; 26 | } 27 | 28 | .w-certs-info-filename .glyphicon-lock { 29 | margin-right: 5px; 30 | } 31 | 32 | .w-certs-info-dialog td { 33 | overflow: hidden; 34 | text-overflow: ellipsis; 35 | } 36 | 37 | .w-certs-info-filename { 38 | width: 220px; 39 | } 40 | 41 | .w-certs-info-dialog th, 42 | .w-certs-info-dialog td { 43 | vertical-align: middle !important; 44 | } 45 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/dropdown.css: -------------------------------------------------------------------------------- 1 | .w-dropdown-text { 2 | max-width: 300px; 3 | overflow: hidden; 4 | text-overflow: ellipsis; 5 | white-space: nowrap; 6 | cursor: pointer; 7 | } 8 | .w-dropdown .dropdown-menu .divider { 9 | margin: 0 !important; 10 | } 11 | .w-dropdown .dropdown-menu { 12 | width: auto !important; 13 | max-width: 300px; 14 | white-space: nowrap; 15 | overflow: hidden; 16 | text-overflow: ellipsis; 17 | min-width: auto !important; 18 | display: none; 19 | max-height: 360px; 20 | overflow-x: hidden; 21 | overflow-y: auto; 22 | } 23 | .w-dropdown { 24 | display: inline-block; 25 | } 26 | 27 | .w-dropdown .dropdown-menu li { 28 | padding: 0 10px; 29 | cursor: pointer; 30 | text-overflow: ellipsis; 31 | overflow: hidden; 32 | white-space: nowrap; 33 | } 34 | .w-dropdown .dropdown-menu li:hover { 35 | background: #f5f5f5; 36 | } 37 | .w-dropdown .dropdown-menu a { 38 | padding: 0 10px; 39 | line-height: 20px; 40 | display: block; 41 | text-align: center; 42 | } 43 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/editor-settings.css: -------------------------------------------------------------------------------- 1 | .w-editor-settings label, 2 | .w-editor-settings-box label { 3 | font-weight: normal; 4 | white-space: nowrap; 5 | } 6 | .w-editor-settings label .w-label { 7 | display: inline-block; 8 | width: 60px; 9 | text-align: right; 10 | margin-right: 5px; 11 | } 12 | .w-editor-settings select { 13 | width: 186px; 14 | } 15 | .w-rules-settings-dialog .w-editor-settings select { 16 | width: 260px; 17 | } 18 | .w-editor-settings-box { 19 | padding-left: 65px; 20 | margin: 10px !important; 21 | } 22 | .w-editor-settings .form-control { 23 | display: inline-block; 24 | margin-left: 5px; 25 | } 26 | .w-editor-settings p { 27 | margin: 5px; 28 | } 29 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/editor.css: -------------------------------------------------------------------------------- 1 | .CodeMirror-hints li.CodeMirror-hint-active:after { 2 | content: 'F1'; 3 | position: absolute; 4 | right: 0; 5 | font-size: 12px; 6 | } 7 | 8 | .CodeMirror-hints .CodeMirror-hint { 9 | max-width: unset; 10 | position: relative; 11 | padding-right: 20px; 12 | font-family: consolas, monospace; 13 | font-size: 14px; 14 | } 15 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/export-dialog.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avwo/whistle/44a83c877bb77b0de1122040161ce7339f8f4973/biz/webui/htdocs/src/css/export-dialog.css -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/files-dialog.css: -------------------------------------------------------------------------------- 1 | .w-files-dialog .modal-dialog { 2 | width: 900px; 3 | } 4 | 5 | .w-files-order { 6 | width: 36px; 7 | } 8 | .w-files-date { 9 | width: 205px; 10 | } 11 | .w-files-path { 12 | word-break: break-all; 13 | word-wrap: break-word; 14 | } 15 | .w-files-operation { 16 | width: 240px; 17 | } 18 | 19 | .w-files-operation a { 20 | margin-right: 15px; 21 | display: inline-block; 22 | white-space: nowrap; 23 | } 24 | 25 | .w-files-operation a:last-child { 26 | color: #f66; 27 | } 28 | 29 | .w-files-operation a:last-child:hover { 30 | color: #f00; 31 | } 32 | 33 | .w-files-dialog thead th { 34 | padding: 8px; 35 | } 36 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/iframe-dialog.css: -------------------------------------------------------------------------------- 1 | 2 | .w-iframe-dialog .modal-dialog { 3 | width: max(calc(100% - 240px), 720px); 4 | } 5 | 6 | .w-iframe-dialog .modal-body { 7 | padding: 0; 8 | margin: 0; 9 | width: 100%; 10 | height: max(calc(100vh - 120px), 600px); 11 | } 12 | 13 | .w-iframe-dialog .modal-body iframe { 14 | width: 100%; 15 | height: 100%; 16 | display: block; 17 | border: none; 18 | outline: none; 19 | } 20 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/iframe.css: -------------------------------------------------------------------------------- 1 | .w-iframe { 2 | position: relative; 3 | min-width: 560px; 4 | } 5 | 6 | .w-iframe > iframe.fill { 7 | display: block; 8 | width: 100%; 9 | height: 100%; 10 | outline: none; 11 | border: none; 12 | margin: 0; 13 | padding: 0; 14 | } 15 | 16 | .w-iframe[allow-dragover="1"] > iframe.fill { 17 | pointer-events: none; 18 | } 19 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/image-view.css: -------------------------------------------------------------------------------- 1 | .w-image-view { 2 | font-size: 0; 3 | white-space: nowrap; 4 | overflow: auto; 5 | text-align: center; 6 | position: relative; 7 | } 8 | .w-image-bg { 9 | background: #0e0e0e; 10 | display: flex; 11 | align-items: center; 12 | justify-content: center; 13 | } 14 | .w-image-view.w-image-webview { 15 | padding: 0; 16 | display: flex; 17 | } 18 | .w-image-view img { 19 | max-width: 100%; 20 | } 21 | .w-image-view .w-image-link { 22 | display: inline-block; 23 | width: 300px; 24 | line-height: 30px; 25 | position: absolute; 26 | top: 50%; 27 | left: 50%; 28 | margin: -15px 0 0 -150px; 29 | font-size: 14px; 30 | } 31 | 32 | .w-image-view:hover .w-textarea-bar { 33 | display: block; 34 | } 35 | 36 | .w-image-webview .fill { 37 | width: 100%; 38 | } 39 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/import-dialog.css: -------------------------------------------------------------------------------- 1 | .w-ie-dialog .modal-dialog { 2 | width: 600px; 3 | } 4 | 5 | .w-ie-dialog .modal-body { 6 | background-color: #fafafa; 7 | padding: 20px 10px; 8 | } 9 | 10 | .w-ie-dialog input { 11 | width: 578px; 12 | height: 36px; 13 | line-height: 36px; 14 | padding: 5px; 15 | border: 1px solid #ddd; 16 | } 17 | 18 | .w-ie-dialog .modal-footer { 19 | white-space: nowrap; 20 | } 21 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/json-viewer.css: -------------------------------------------------------------------------------- 1 | .w-properties-wrap:hover .w-textarea-bar { 2 | display: inline-block; 3 | } 4 | .w-textarea-bar:hover .w-download { 5 | display: inline-block; 6 | } 7 | .w-textarea-bar .w-properties-btn { 8 | position: static; 9 | } 10 | .w-json-viewer-str, 11 | .w-json-viewer-tree { 12 | padding: 5px; 13 | overflow: auto; 14 | } 15 | .w-json-viewer-tree > ul { 16 | background: none !important; 17 | font-size: 12px; 18 | margin: 0 !important; 19 | } 20 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/kv.css: -------------------------------------------------------------------------------- 1 | .w-kv-dialog { 2 | z-index: 1100; 3 | } 4 | 5 | .w-kv-dialog .modal-dialog { 6 | width: 720px; 7 | } 8 | .w-kv-name { 9 | width: 330px; 10 | white-space: normal; 11 | word-wrap: break-word; 12 | word-break: break-all; 13 | } 14 | .w-kv-dialog .w-kv-box { 15 | width: 36px; 16 | } 17 | 18 | .w-kv-operation pre { 19 | max-height: 70px; 20 | } 21 | .w-kv-operation a { 22 | display: block; 23 | width: 50px; 24 | margin-top: 3px; 25 | } 26 | .w-kv-name strong { 27 | color: #f66; 28 | margin-left: 5px; 29 | cursor: pointer; 30 | } 31 | 32 | .w-kv-dialog thead th, .w-kv-dialog thead td { 33 | padding: 8px; 34 | } 35 | 36 | .w-kv-check-all { 37 | float: left; 38 | margin: 0 0 0 9px; 39 | display: flex; 40 | align-items: center; 41 | } 42 | 43 | .w-kv-check-all input { 44 | margin-right: 8px; 45 | } 46 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/message.css: -------------------------------------------------------------------------------- 1 | .w-message { 2 | position: fixed; 3 | top: 30px; 4 | left: 50%; 5 | z-index: 999999999; 6 | padding: 8px 20px !important; 7 | max-width: 410px; 8 | } 9 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/modal.css: -------------------------------------------------------------------------------- 1 | .w-dialog-for-plguin .modal-header { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/plugins-mgr.css: -------------------------------------------------------------------------------- 1 | .w-plugins-mgr-dialog { 2 | z-index: 1060; 3 | } 4 | 5 | .w-plugins-mgr-dialog .modal-content { 6 | width: 380px; 7 | } 8 | 9 | .w-plugins-mgr-dialog .plugin-mgr-btn { 10 | display: block; 11 | line-height: 1.5; 12 | width: 320px; 13 | margin: 20px auto; 14 | padding: 15px 10px; 15 | text-align: center; 16 | cursor: pointer; 17 | font-size: 15px; 18 | overflow: hidden; 19 | text-overflow: ellipsis; 20 | font-weight: 500; 21 | } 22 | 23 | .w-plugins-mgr-dialog .plugin-mgr-btn span { 24 | opacity: 0.66; 25 | font-weight: 400; 26 | } 27 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/record-btn.css: -------------------------------------------------------------------------------- 1 | .w-refresh-menu-list .glyphicon-minus-sign, 2 | .w-refresh-menu-list .w-menu-item .glyphicon-stop { 3 | color: #ccc !important; 4 | } 5 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/res-detail.css: -------------------------------------------------------------------------------- 1 | .w-detail-response textarea { 2 | padding: 5px; 3 | border: none; 4 | } 5 | .w-detail-response-headers, 6 | .w-detail-response-cookies { 7 | overflow: auto; 8 | } 9 | .w-detail-response-cookies table { 10 | table-layout: auto; 11 | } 12 | .w-detail-response-cookies thead > th { 13 | white-space: nowrap; 14 | background: #fafafa; 15 | } 16 | .w-detail-response-cookies tbody > tr > td:nth-child(7), 17 | .w-detail-response-cookies tbody > tr > td:nth-child(8), 18 | .w-detail-response-cookies tbody > tr > td:nth-child(10) { 19 | text-align: center; 20 | vertical-align: middle; 21 | } 22 | .w-show-history .w-btn-group-sm { 23 | height: 22px; 24 | overflow: hidden; 25 | } 26 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/service.css: -------------------------------------------------------------------------------- 1 | .w-service-btn { 2 | font-weight: bold; 3 | } 4 | 5 | @media screen and (max-width: 1135px) { 6 | .w-has-token.w-show-rules .w-help-name { 7 | display: none; 8 | } 9 | } 10 | 11 | @media screen and (max-width: 1110px) { 12 | .w-has-token.w-show-rules .w-https-name { 13 | display: none; 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/sync-dialog.css: -------------------------------------------------------------------------------- 1 | .w-sync-dialog .modal-dialog { 2 | width: 420px; 3 | } 4 | 5 | .w-sync-dialog .modal-body .btn { 6 | display: block; 7 | width: 398px; 8 | line-height: 40px; 9 | font-size: 18px; 10 | margin: 10px 0; 11 | } 12 | 13 | .w-sync-dialog .modal-body .btn span { 14 | margin-right: 10px; 15 | } 16 | 17 | .w-history-record-list { 18 | margin: 20px 0 15px 10px; 19 | width: 635px; 20 | display: inline-block; 21 | font-weight: normal; 22 | white-space: nowrap; 23 | } 24 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/css/table.css: -------------------------------------------------------------------------------- 1 | .w-table > thead > tr > th { 2 | background: #eee; 3 | font-weight: normal; 4 | border-bottom: 1px solid #ccc; 5 | vertical-align: top; 6 | } 7 | 8 | .w-table th, 9 | .w-table td { 10 | font-size: 12px; 11 | padding: 3px 5px !important; 12 | border-top: none; 13 | border-bottom: 1px solid #ccc; 14 | word-break: break-word; 15 | } 16 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/js/base-css.js: -------------------------------------------------------------------------------- 1 | require('bootstrap/dist/css/bootstrap.css'); 2 | require('../css/base.css'); 3 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/js/components/json/index.js: -------------------------------------------------------------------------------- 1 | exports.parse = require('./parse'); 2 | exports.stringify = require('./stringify'); 3 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/js/components/react-json-tree/objType.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.__esModule = true; 4 | 5 | var _iterator = require('babel-runtime/core-js/symbol/iterator'); 6 | 7 | var _iterator2 = _interopRequireDefault(_iterator); 8 | 9 | exports['default'] = objType; 10 | 11 | function _interopRequireDefault(obj) { 12 | return obj && obj.__esModule ? obj : { default: obj }; 13 | } 14 | 15 | function objType(obj) { 16 | var type = Object.prototype.toString.call(obj).slice(8, -1); 17 | if (type === 'Object' && typeof obj[_iterator2['default']] === 'function') { 18 | return 'Iterable'; 19 | } 20 | 21 | if (type === 'String' && obj._$isNumber) { 22 | return 'BigNumber'; 23 | } 24 | 25 | if ( 26 | type === 'Custom' && 27 | obj.constructor !== Object && 28 | obj instanceof Object 29 | ) { 30 | // For projects implementing objects overriding `.prototype[Symbol.toStringTag]` 31 | return 'Object'; 32 | } 33 | 34 | return type; 35 | } 36 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/js/components/react-json-tree/themes/solarized.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.__esModule = true; 4 | exports['default'] = { 5 | scheme: 'solarized', 6 | author: 'ethan schoonover (http://ethanschoonover.com/solarized)', 7 | base00: '#002b36', 8 | base01: '#073642', 9 | base02: '#586e75', 10 | base03: '#657b83', 11 | base04: '#839496', 12 | base05: '#93a1a1', 13 | base06: '#eee8d5', 14 | base07: '#fdf6e3', 15 | base08: '#dc322f', 16 | base09: '#cb4b16', 17 | base0A: '#b58900', 18 | base0B: '#859900', 19 | base0C: '#2aa198', 20 | base0D: '#268bd2', 21 | base0E: '#6c71c4', 22 | base0F: '#d33682' 23 | }; 24 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/js/components/react-json-tree/utils/hexToRgb.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.__esModule = true; 4 | 5 | exports['default'] = function (hex) { 6 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 7 | return result 8 | ? { 9 | r: parseInt(result[1], 16), 10 | g: parseInt(result[2], 16), 11 | b: parseInt(result[3], 16) 12 | } 13 | : null; 14 | }; 15 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/js/copy-btn.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | 3 | var CopyBtn = React.createClass({ 4 | getInitialState: function () { 5 | return {}; 6 | }, 7 | handleLeave: function () { 8 | this.setState({ copied: false }); 9 | }, 10 | handleCopy: function () { 11 | this.setState({ copied: true }); 12 | }, 13 | render: function () { 14 | var copied = this.state.copied; 15 | return ( 16 | 24 | {(copied ? 'Copied' : 'Copy') + (this.props.name || '')} 25 | 26 | ); 27 | } 28 | }); 29 | 30 | module.exports = CopyBtn; 31 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/js/decode.js: -------------------------------------------------------------------------------- 1 | var toByteArray = require('base64-js').toByteArray; 2 | var base64Decode = require('js-base64').Base64.decode; 3 | var isUtf8 = require('./is-utf8'); 4 | 5 | var gbkDecoder; 6 | if (self.TextDecoder) { 7 | try { 8 | gbkDecoder = new self.TextDecoder('GB18030'); 9 | } catch (e) {} 10 | } 11 | 12 | function base64toBytes(base64) { 13 | try { 14 | return toByteArray(base64); 15 | } catch (e) {} 16 | } 17 | 18 | self.getText = function(base64) { 19 | var arr = base64 && base64toBytes(base64); 20 | if (!arr) { 21 | return ''; 22 | } 23 | if (!isUtf8(arr)) { 24 | try { 25 | if (gbkDecoder) { 26 | return gbkDecoder.decode(arr); 27 | } 28 | } catch (e) {} 29 | } 30 | try { 31 | return base64Decode(base64); 32 | } catch (e) {} 33 | return ''; 34 | }; 35 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/js/enable-https-btn.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var dataCenter = require('./data-center'); 3 | var events = require('./events'); 4 | 5 | var EnableHttpsBtn = React.createClass({ 6 | showHttpsSettingsDialog: function () { 7 | events.trigger('showHttpsSettingsDialog'); 8 | }, 9 | render: function () { 10 | if (dataCenter.isMultiEnv() || dataCenter.isCapture) { 11 | return null; 12 | } 13 | return ; 14 | } 15 | }); 16 | 17 | module.exports = EnableHttpsBtn; 18 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/js/events.js: -------------------------------------------------------------------------------- 1 | var $ = require('jquery'); 2 | 3 | module.exports = $({}); 4 | -------------------------------------------------------------------------------- /biz/webui/htdocs/src/js/iframe.js: -------------------------------------------------------------------------------- 1 | require('../css/iframe.css'); 2 | var React = require('react'); 3 | var ReactDOM = require('react-dom'); 4 | 5 | var IFrame = React.createClass({ 6 | getWindow: function() { 7 | return ReactDOM.findDOMNode(this.refs.iframe).contentWindow; 8 | }, 9 | render: function() { 10 | var props = this.props; 11 | var className = props.className; 12 | return ( 13 |
14 |