├── README.md ├── common ├── pom.xml ├── src │ └── main │ │ └── java │ │ └── com.weasel.penetrate.common │ │ ├── ansi │ │ ├── AnsiColor.java │ │ ├── AnsiElement.java │ │ ├── AnsiOutput.java │ │ └── AnsiStyle.java │ │ ├── banner │ │ ├── AbstractBanner.java │ │ └── Banner.java │ │ ├── helper │ │ ├── EnvironmentHelper.java │ │ ├── GsonHelper.java │ │ ├── IniHeler.java │ │ └── SystemHelper.java │ │ └── package-info.java └── target │ └── classes │ └── com │ └── weasel │ └── penetrate │ └── common │ └── helper │ ├── GsonHelper.class │ ├── IniHeler.class │ ├── SystemHelper$Platform.class │ └── SystemHelper.class ├── manager ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── weasel │ │ │ └── penetrate │ │ │ └── manager │ │ │ ├── ApplicationLauncher.java │ │ │ ├── domain │ │ │ ├── AbstractEntity.java │ │ │ ├── Common.java │ │ │ ├── IniConfig.java │ │ │ ├── Page.java │ │ │ ├── Role.java │ │ │ ├── User.java │ │ │ └── device │ │ │ │ └── Device.java │ │ │ ├── infrastructure │ │ │ ├── EventPublisher.java │ │ │ ├── Frp.java │ │ │ ├── annotation │ │ │ │ └── JQGridId.java │ │ │ ├── config │ │ │ │ ├── PenetrateConfiguration.java │ │ │ │ ├── ShiroConfiguration.java │ │ │ │ ├── SpringBootConfiguration.java │ │ │ │ └── ThymeleafConfig.java │ │ │ ├── exception │ │ │ │ ├── DevicePortBindedException.java │ │ │ │ ├── DevicePortUsedUpException.java │ │ │ │ ├── DeviceSubDomainUsedException.java │ │ │ │ ├── LockAccountException.java │ │ │ │ └── UserExistException.java │ │ │ ├── formatter │ │ │ │ ├── JQGridIdFormatter.java │ │ │ │ └── factory │ │ │ │ │ └── JQGridIdFormatAnnotationFormatterFactory.java │ │ │ ├── helper │ │ │ │ ├── PasswordHelper.java │ │ │ │ ├── SecurityHelper.java │ │ │ │ └── SpringBeanHolder.java │ │ │ ├── ini │ │ │ │ ├── IniHandler.java │ │ │ │ ├── IniReader.java │ │ │ │ ├── IniWriter.java │ │ │ │ └── section │ │ │ │ │ ├── ListSection.java │ │ │ │ │ └── OneSection.java │ │ │ ├── listener │ │ │ │ ├── ApplicationStartOverListener.java │ │ │ │ ├── DeviceCreateListener.java │ │ │ │ ├── DeviceUpdateListener.java │ │ │ │ └── event │ │ │ │ │ ├── AbstractCommonEvent.java │ │ │ │ │ ├── DeviceCreateEvent.java │ │ │ │ │ └── DeviceUpdateEvent.java │ │ │ ├── repository │ │ │ │ ├── CommonRepository.java │ │ │ │ ├── DeviceRepository.java │ │ │ │ ├── MybatisDaoSupport.java │ │ │ │ ├── UserRepository.java │ │ │ │ └── impl │ │ │ │ │ ├── CommonRepositoryImpl.java │ │ │ │ │ ├── DeviceRepositoryImpl.java │ │ │ │ │ └── UserRepositoryImpl.java │ │ │ ├── shiro │ │ │ │ └── ShiroRealm.java │ │ │ └── task │ │ │ │ ├── ReloadFrpConfigQueue.java │ │ │ │ └── ReloadFrpConfigScheduled.java │ │ │ ├── interfaces │ │ │ ├── controller │ │ │ │ ├── AdminController.java │ │ │ │ ├── DeviceController.java │ │ │ │ ├── HomeController.java │ │ │ │ ├── ManagerController.java │ │ │ │ └── UserController.java │ │ │ └── vo │ │ │ │ └── ResponseMessage.java │ │ │ └── service │ │ │ ├── CommonService.java │ │ │ ├── DeviceService.java │ │ │ ├── FrpConfigService.java │ │ │ ├── UserService.java │ │ │ └── impl │ │ │ ├── CommonServiceImpl.java │ │ │ ├── DeviceServiceImpl.java │ │ │ ├── FrpConfigServiceImpl.java │ │ │ └── UserServiceImpl.java │ └── resources │ │ ├── application-dev.yml │ │ ├── application-prod.yml │ │ ├── application.yml │ │ ├── banner.txt │ │ ├── database-initialize.sql │ │ ├── mybatis │ │ ├── mappers │ │ │ ├── common.xml │ │ │ ├── device.xml │ │ │ ├── role.xml │ │ │ └── user.xml │ │ └── mybatis-config.xml │ │ ├── start_linux.sh │ │ ├── static │ │ ├── css │ │ │ ├── animate.css │ │ │ ├── bootstrap-rtl.css │ │ │ ├── bootstrap.min.css │ │ │ ├── demo │ │ │ │ └── webuploader-demo.css │ │ │ ├── font-awesome.min.css │ │ │ ├── home │ │ │ │ ├── font-awesome.min.css │ │ │ │ ├── frp │ │ │ │ │ ├── bootstrap.min.css │ │ │ │ │ └── iconfont.css │ │ │ │ ├── main.css │ │ │ │ └── style.css │ │ │ ├── login.css │ │ │ ├── patterns │ │ │ │ ├── header-profile-skin-1.png │ │ │ │ ├── header-profile-skin-3.png │ │ │ │ ├── header-profile.png │ │ │ │ └── shattered.png │ │ │ ├── plugins │ │ │ │ ├── awesome-bootstrap-checkbox │ │ │ │ │ └── awesome-bootstrap-checkbox.css │ │ │ │ ├── blueimp │ │ │ │ │ ├── css │ │ │ │ │ │ ├── blueimp-gallery-indicator.css │ │ │ │ │ │ ├── blueimp-gallery-video.css │ │ │ │ │ │ ├── blueimp-gallery.css │ │ │ │ │ │ ├── blueimp-gallery.min.css │ │ │ │ │ │ └── demo.css │ │ │ │ │ └── img │ │ │ │ │ │ ├── error.png │ │ │ │ │ │ ├── error.svg │ │ │ │ │ │ ├── loading.gif │ │ │ │ │ │ ├── play-pause.png │ │ │ │ │ │ ├── play-pause.svg │ │ │ │ │ │ ├── video-play.png │ │ │ │ │ │ └── video-play.svg │ │ │ │ ├── bootstrap-table │ │ │ │ │ └── bootstrap-table.min.css │ │ │ │ ├── chosen │ │ │ │ │ ├── chosen-sprite.png │ │ │ │ │ ├── chosen-sprite@2x.png │ │ │ │ │ └── chosen.css │ │ │ │ ├── clockpicker │ │ │ │ │ └── clockpicker.css │ │ │ │ ├── codemirror │ │ │ │ │ ├── ambiance.css │ │ │ │ │ └── codemirror.css │ │ │ │ ├── colorpicker │ │ │ │ │ ├── css │ │ │ │ │ │ └── bootstrap-colorpicker.min.css │ │ │ │ │ └── img │ │ │ │ │ │ └── bootstrap-colorpicker │ │ │ │ │ │ ├── alpha-horizontal.png │ │ │ │ │ │ ├── alpha.png │ │ │ │ │ │ ├── hue-horizontal.png │ │ │ │ │ │ ├── hue.png │ │ │ │ │ │ └── saturation.png │ │ │ │ ├── cropper │ │ │ │ │ └── cropper.min.css │ │ │ │ ├── dataTables │ │ │ │ │ └── dataTables.bootstrap.css │ │ │ │ ├── datapicker │ │ │ │ │ └── datepicker3.css │ │ │ │ ├── dropzone │ │ │ │ │ ├── basic.css │ │ │ │ │ └── dropzone.css │ │ │ │ ├── duallistbox │ │ │ │ │ └── bootstrap-duallistbox.css │ │ │ │ ├── footable │ │ │ │ │ ├── fonts │ │ │ │ │ │ ├── footable.eot │ │ │ │ │ │ ├── footable.svg │ │ │ │ │ │ ├── footable.ttf │ │ │ │ │ │ └── footable.woff │ │ │ │ │ └── footable.core.css │ │ │ │ ├── fullcalendar │ │ │ │ │ ├── fullcalendar.css │ │ │ │ │ └── fullcalendar.print.css │ │ │ │ ├── iCheck │ │ │ │ │ ├── custom.css │ │ │ │ │ ├── green.png │ │ │ │ │ └── green@2x.png │ │ │ │ ├── images │ │ │ │ │ ├── sort_asc.png │ │ │ │ │ ├── sort_desc.png │ │ │ │ │ ├── sprite-skin-flat.png │ │ │ │ │ ├── spritemap.png │ │ │ │ │ └── spritemap@2x.png │ │ │ │ ├── ionRangeSlider │ │ │ │ │ ├── ion.rangeSlider.css │ │ │ │ │ └── ion.rangeSlider.skinFlat.css │ │ │ │ ├── jQueryUI │ │ │ │ │ ├── images │ │ │ │ │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ │ │ │ │ │ ├── ui-bg_flat_75_ffffff_40x100.png │ │ │ │ │ │ ├── ui-icons_222222_256x240.png │ │ │ │ │ │ ├── ui-icons_454545_256x240.png │ │ │ │ │ │ └── ui-icons_888888_256x240.png │ │ │ │ │ └── jquery-ui-1.10.4.custom.min.css │ │ │ │ ├── jasny │ │ │ │ │ └── jasny-bootstrap.min.css │ │ │ │ ├── jqgrid │ │ │ │ │ └── ui.jqgrid.css │ │ │ │ ├── jsTree │ │ │ │ │ ├── 32px.png │ │ │ │ │ ├── style.min.css │ │ │ │ │ └── throbber.gif │ │ │ │ ├── markdown │ │ │ │ │ └── bootstrap-markdown.min.css │ │ │ │ ├── morris │ │ │ │ │ └── morris-0.4.3.min.css │ │ │ │ ├── multiselect │ │ │ │ │ └── bootstrap-multiselect.css │ │ │ │ ├── nouslider │ │ │ │ │ └── jquery.nouislider.css │ │ │ │ ├── plyr │ │ │ │ │ ├── plyr.css │ │ │ │ │ └── sprite.svg │ │ │ │ ├── simditor │ │ │ │ │ └── simditor.css │ │ │ │ ├── steps │ │ │ │ │ └── jquery.steps.css │ │ │ │ ├── summernote │ │ │ │ │ ├── summernote-bs3.css │ │ │ │ │ └── summernote.css │ │ │ │ ├── sweetalert │ │ │ │ │ └── sweetalert.css │ │ │ │ ├── switchery │ │ │ │ │ └── switchery.css │ │ │ │ ├── toastr │ │ │ │ │ └── toastr.min.css │ │ │ │ ├── treeview │ │ │ │ │ └── bootstrap-treeview.css │ │ │ │ └── webuploader │ │ │ │ │ └── webuploader.css │ │ │ └── style.css │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ ├── fontawesome-webfont.woff2 │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ ├── images │ │ │ ├── 0.jpg │ │ │ ├── 1.png │ │ │ ├── a1.jpg │ │ │ ├── a2.jpg │ │ │ ├── a3.jpg │ │ │ ├── a4.jpg │ │ │ ├── a5.jpg │ │ │ ├── a6.jpg │ │ │ ├── a7.jpg │ │ │ ├── a8.jpg │ │ │ ├── a9.jpg │ │ │ ├── alipay.jpg │ │ │ ├── banner.jpg │ │ │ ├── bg.png │ │ │ ├── browser.png │ │ │ ├── favicon.ico │ │ │ ├── home.png │ │ │ ├── iconfont-logo.png │ │ │ ├── icons.png │ │ │ ├── linux.png │ │ │ ├── loading-upload.gif │ │ │ ├── locked.png │ │ │ ├── login-background.jpg │ │ │ ├── mac.png │ │ │ ├── manager.png │ │ │ ├── p1.jpg │ │ │ ├── p2.jpg │ │ │ ├── p3.jpg │ │ │ ├── profile.jpg │ │ │ ├── profile_small.jpg │ │ │ ├── progress.png │ │ │ ├── qq.png │ │ │ ├── qq1.png │ │ │ ├── qq2.png │ │ │ ├── sprite-skin-flat.png │ │ │ ├── success.png │ │ │ ├── user.png │ │ │ ├── webuploader.png │ │ │ ├── wenku_logo.png │ │ │ ├── windows.png │ │ │ └── wxpay.png │ │ └── js │ │ │ ├── bootstrap.min.js │ │ │ ├── content.js │ │ │ ├── frp │ │ │ ├── angular.min.js │ │ │ ├── bootstrap.min.js │ │ │ ├── echarts.min.js │ │ │ └── jquery.min.js │ │ │ ├── hAdmin.js │ │ │ ├── index.js │ │ │ ├── jquery-ui-1.10.4.min.js │ │ │ ├── jquery-ui.custom.min.js │ │ │ ├── jquery.min.js │ │ │ ├── jquery.min.map │ │ │ ├── main.js │ │ │ ├── plugins │ │ │ ├── beautifyhtml │ │ │ │ └── beautifyhtml.js │ │ │ ├── blueimp │ │ │ │ └── jquery.blueimp-gallery.min.js │ │ │ ├── bootstrap-table │ │ │ │ ├── bootstrap-table-mobile.min.js │ │ │ │ ├── bootstrap-table.min.js │ │ │ │ └── locale │ │ │ │ │ ├── bootstrap-table-zh-CN.js │ │ │ │ │ └── bootstrap-table-zh-CN.min.js │ │ │ ├── chartJs │ │ │ │ └── Chart.min.js │ │ │ ├── chosen │ │ │ │ └── chosen.jquery.js │ │ │ ├── cropper │ │ │ │ └── cropper.min.js │ │ │ ├── dataTables │ │ │ │ ├── dataTables.bootstrap.js │ │ │ │ └── jquery.dataTables.js │ │ │ ├── datapicker │ │ │ │ └── bootstrap-datepicker.js │ │ │ ├── duallistbox │ │ │ │ └── jquery.bootstrap-duallistbox.js │ │ │ ├── echarts │ │ │ │ └── echarts-all.js │ │ │ ├── flot │ │ │ │ ├── curvedLines.js │ │ │ │ ├── jquery.flot.js │ │ │ │ ├── jquery.flot.pie.js │ │ │ │ ├── jquery.flot.resize.js │ │ │ │ ├── jquery.flot.spline.js │ │ │ │ ├── jquery.flot.symbol.js │ │ │ │ └── jquery.flot.tooltip.min.js │ │ │ ├── footable │ │ │ │ └── footable.all.min.js │ │ │ ├── fullcalendar │ │ │ │ ├── fullcalendar.min.js │ │ │ │ └── moment.min.js │ │ │ ├── gritter │ │ │ │ ├── images │ │ │ │ │ ├── gritter-light.png │ │ │ │ │ ├── gritter.png │ │ │ │ │ └── ie-spacer.gif │ │ │ │ ├── jquery.gritter.css │ │ │ │ └── jquery.gritter.min.js │ │ │ ├── iCheck │ │ │ │ └── icheck.min.js │ │ │ ├── ionRangeSlider │ │ │ │ ├── ion.rangeSlider.min.js │ │ │ │ └── jasny │ │ │ │ │ └── jasny-bootstrap.min.js │ │ │ ├── jasny │ │ │ │ └── jasny-bootstrap.min.js │ │ │ ├── jeditable │ │ │ │ └── jquery.jeditable.js │ │ │ ├── jqgrid │ │ │ │ ├── i18n │ │ │ │ │ └── grid.locale-cn.js │ │ │ │ └── jquery.jqGrid.min.js │ │ │ ├── jquery-ui │ │ │ │ └── jquery-ui.min.js │ │ │ ├── jsTree │ │ │ │ ├── jstree.js │ │ │ │ └── jstree.min.js │ │ │ ├── layer │ │ │ │ ├── extend │ │ │ │ │ └── layer.ext.js │ │ │ │ ├── laydate │ │ │ │ │ ├── laydate.js │ │ │ │ │ ├── need │ │ │ │ │ │ └── laydate.css │ │ │ │ │ └── skins │ │ │ │ │ │ └── default │ │ │ │ │ │ ├── icon.png │ │ │ │ │ │ └── laydate.css │ │ │ │ ├── layer.min.js │ │ │ │ ├── layim │ │ │ │ │ ├── data │ │ │ │ │ │ ├── chatlog.json │ │ │ │ │ │ ├── friend.json │ │ │ │ │ │ ├── group.json │ │ │ │ │ │ └── groups.json │ │ │ │ │ ├── layim.css │ │ │ │ │ ├── layim.js │ │ │ │ │ └── loading.gif │ │ │ │ └── skin │ │ │ │ │ ├── default │ │ │ │ │ ├── icon-ext.png │ │ │ │ │ ├── icon.png │ │ │ │ │ ├── icon_ext.png │ │ │ │ │ ├── loading-0.gif │ │ │ │ │ ├── loading-1.gif │ │ │ │ │ ├── loading-2.gif │ │ │ │ │ ├── textbg.png │ │ │ │ │ ├── xubox_ico0.png │ │ │ │ │ ├── xubox_loading0.gif │ │ │ │ │ ├── xubox_loading1.gif │ │ │ │ │ ├── xubox_loading2.gif │ │ │ │ │ ├── xubox_loading3.gif │ │ │ │ │ └── xubox_title0.png │ │ │ │ │ ├── layer.css │ │ │ │ │ ├── layer.ext.css │ │ │ │ │ └── moon │ │ │ │ │ ├── default.png │ │ │ │ │ └── style.css │ │ │ ├── markdown │ │ │ │ ├── bootstrap-markdown.js │ │ │ │ ├── bootstrap-markdown.zh.js │ │ │ │ ├── markdown.js │ │ │ │ └── to-markdown.js │ │ │ ├── metisMenu │ │ │ │ └── jquery.metisMenu.js │ │ │ ├── multiselect │ │ │ │ └── bootstrap-multiselect.js │ │ │ ├── pace │ │ │ │ └── pace.min.js │ │ │ ├── peity │ │ │ │ └── jquery.peity.min.js │ │ │ ├── plyr │ │ │ │ └── plyr.js │ │ │ ├── preetyTextDiff │ │ │ │ └── jquery.pretty-text-diff.min.js │ │ │ ├── prettyfile │ │ │ │ └── bootstrap-prettyfile.js │ │ │ ├── slimscroll │ │ │ │ └── jquery.slimscroll.min.js │ │ │ ├── sparkline │ │ │ │ └── jquery.sparkline.min.js │ │ │ ├── suggest │ │ │ │ ├── bootstrap-suggest.min.js │ │ │ │ └── data.json │ │ │ ├── toastr │ │ │ │ └── toastr.min.js │ │ │ ├── treeview │ │ │ │ └── bootstrap-treeview.js │ │ │ └── validate │ │ │ │ ├── additional-methods.min.js │ │ │ │ ├── jquery.validate.min.js │ │ │ │ └── messages_zh.min.js │ │ │ ├── skel.min.js │ │ │ └── util.js │ │ ├── templates │ │ ├── course.html │ │ ├── elements.html │ │ ├── footer.html │ │ ├── frp_status.html │ │ ├── generic.html │ │ ├── home.html │ │ └── manager │ │ │ ├── common.html │ │ │ ├── device.html │ │ │ ├── home.html │ │ │ ├── login.html │ │ │ ├── register.html │ │ │ ├── user.html │ │ │ └── welcome.html │ │ └── www-kisme-org.jks │ └── test │ └── java │ └── com │ └── weasel │ └── penetrate │ └── manager │ └── JasyptTest.java ├── monitor ├── pom.xml └── src │ └── main │ └── java │ └── com.weasel.penetrate.monitor │ ├── DeviceStatus.java │ └── FrpMonitor.java └── pom.xml /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | **一 什么是penetrate** 4 | 5 | penetrate是一个java语言开发针对frp进行管理的项目。在v0.9.3及以前的版本,并没有一个可用的管理系统。 6 | 开特权模式,又怕被别人滥用。不开特权模式,每添加一个设置,要我去修改配置文件,重新加载或重启,比较麻烦。 7 | 还是比较适合自用或者朋友之间使用。penetrate是通过后台添加设置的形式,自动修改配置文件,并自动重新加载配置。 8 | 9 | 10 | 11 | **二 penetrate线上运行的产品** 12 | 13 | http://tun.gogl.top/home 是penetrate的一个线上运行的例子,并提供免费的穿透服务。 14 | 15 | ![enter image description here](https://github.com/pickear/penetrate/blob/master/manager/src/main/resources/static/images/home.png?raw=true) 16 | 17 | ![enter image description here](https://github.com/pickear/penetrate/blob/master/manager/src/main/resources/static/images/manager.png?raw=true) 18 | 19 | **三 penetrate使用** 20 | 21 | 1 penetrate模块 22 | 主要有两个模块。home模块是一个对产品前端展示的模块,manager模块是一个对frp管理的模块。 23 | 24 | 2 使用 25 | 首先下载源代码并编译成jar,执行jar manager.jar -Dfrp.home=xxxx,其中xxxx为你的frp安装目录。 26 | 27 | 四 交流 28 | 如遇到什么问题,可以加企鹅群:372831385交流。 29 | 30 | 31 | 32 | 如果你觉得对你有帮助,可以请作者喝杯咖啡。 33 | 34 | 35 |
36 |
37 |
38 |
39 | 支付宝二维码 40 |
41 |
42 |
43 |
44 | 微信二维码 45 |
46 |
47 |
48 |
49 | 50 | 51 | -------------------------------------------------------------------------------- /common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | penetrate 7 | com.weasel.penetrate 8 | 0.2.0 9 | 10 | 4.0.0 11 | 12 | common 13 | jar 14 | 15 | 16 | 17 | com.google.code.gson 18 | gson 19 | 20 | 21 | joda-time 22 | joda-time 23 | 24 | 25 | org.apache.commons 26 | commons-lang3 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /common/src/main/java/com.weasel.penetrate.common/ansi/AnsiColor.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.common.ansi; 2 | 3 | /** 4 | * @author dylan 5 | * @time 2017/4/20 6 | */ 7 | public enum AnsiColor implements AnsiElement { 8 | 9 | DEFAULT("39"), 10 | 11 | BLACK("30"), 12 | 13 | RED("31"), 14 | 15 | GREEN("32"), 16 | 17 | YELLOW("33"), 18 | 19 | BLUE("34"), 20 | 21 | MAGENTA("35"), 22 | 23 | CYAN("36"), 24 | 25 | WHITE("37"), 26 | 27 | BRIGHT_BLACK("90"), 28 | 29 | BRIGHT_RED("91"), 30 | 31 | BRIGHT_GREEN("92"), 32 | 33 | BRIGHT_YELLOW("93"), 34 | 35 | BRIGHT_BLUE("94"), 36 | 37 | BRIGHT_MAGENTA("95"), 38 | 39 | BRIGHT_CYAN("96"), 40 | 41 | BRIGHT_WHITE("97"); 42 | 43 | private final String code; 44 | 45 | AnsiColor(String code) { 46 | this.code = code; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return this.code; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /common/src/main/java/com.weasel.penetrate.common/ansi/AnsiElement.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.common.ansi; 2 | 3 | /** 4 | * @author dylan 5 | * @time 2017/4/20 6 | */ 7 | public interface AnsiElement { 8 | 9 | /** 10 | * @return the ANSI escape code 11 | */ 12 | @Override 13 | String toString(); 14 | 15 | /** 16 | * Internal default {@link AnsiElement} implementation. 17 | */ 18 | class DefaultAnsiElement implements AnsiElement { 19 | 20 | private final String code; 21 | 22 | DefaultAnsiElement(String code) { 23 | this.code = code; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return this.code; 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/src/main/java/com.weasel.penetrate.common/ansi/AnsiStyle.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.common.ansi; 2 | 3 | /** 4 | * @author dylan 5 | * @time 2017/4/20 6 | */ 7 | public enum AnsiStyle implements AnsiElement { 8 | 9 | NORMAL("0"), 10 | 11 | BOLD("1"), 12 | 13 | FAINT("2"), 14 | 15 | ITALIC("3"), 16 | 17 | UNDERLINE("4"); 18 | 19 | private final String code; 20 | 21 | AnsiStyle(String code) { 22 | this.code = code; 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return this.code; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /common/src/main/java/com.weasel.penetrate.common/banner/AbstractBanner.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.common.banner; 2 | 3 | import com.weasel.penetrate.common.ansi.AnsiColor; 4 | import com.weasel.penetrate.common.ansi.AnsiOutput; 5 | import com.weasel.penetrate.common.ansi.AnsiStyle; 6 | 7 | /** 8 | * @author dylan 9 | * @time 2017/4/20 10 | */ 11 | public abstract class AbstractBanner implements Banner{ 12 | 13 | protected static final int STRAP_LINE_SIZE = 42; 14 | 15 | @Override 16 | public void printBanner(String name,String version) { 17 | 18 | for (String line : banner()) { 19 | System.out.println(line); 20 | } 21 | version = (version == null ? "" : " (v" + version + ")"); 22 | String padding = ""; 23 | while (padding.length() < STRAP_LINE_SIZE 24 | - (version.length() + name.length())) { 25 | padding += " "; 26 | } 27 | 28 | System.out.println(AnsiOutput.toString(AnsiColor.GREEN, name, 29 | AnsiColor.DEFAULT, padding, AnsiStyle.FAINT, version)); 30 | System.out.println(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/src/main/java/com.weasel.penetrate.common/banner/Banner.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.common.banner; 2 | 3 | 4 | /** 5 | * @author dylan 6 | * @time 2017/4/20 7 | */ 8 | public interface Banner { 9 | 10 | /** 11 | * 12 | */ 13 | void printBanner(String name,String version); 14 | 15 | /** 16 | * 17 | * @return 18 | */ 19 | String [] banner(); 20 | } 21 | -------------------------------------------------------------------------------- /common/src/main/java/com.weasel.penetrate.common/helper/EnvironmentHelper.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.common.helper; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | 5 | /** 6 | * Created by dylan on 17-3-14. 7 | */ 8 | public final class EnvironmentHelper { 9 | 10 | public static String getEnv(){ 11 | return System.getProperty("spring.profiles.active"); 12 | } 13 | 14 | public static boolean isProd(){ 15 | return StringUtils.equalsIgnoreCase("prod",getEnv()); 16 | } 17 | 18 | public static boolean isDev(){ 19 | return StringUtils.equalsIgnoreCase("dev",getEnv()); 20 | } 21 | 22 | public static boolean idTest(){ 23 | return StringUtils.equalsIgnoreCase("test",getEnv()); 24 | } 25 | 26 | private EnvironmentHelper(){} 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/java/com.weasel.penetrate.common/helper/GsonHelper.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.common.helper; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | 6 | /** 7 | * Created by dypan on 2017/2/21. 8 | */ 9 | public final class GsonHelper { 10 | 11 | private final static Gson GSON = new GsonBuilder().serializeNulls().create(); 12 | 13 | 14 | public static String toGson(Object obj){ 15 | return GSON.toJson(obj); 16 | } 17 | 18 | private GsonHelper(){} 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com.weasel.penetrate.common/helper/IniHeler.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.common.helper; 2 | 3 | /** 4 | * @author Dylan 5 | * @date 2017/1/18. 6 | */ 7 | public final class IniHeler { 8 | 9 | 10 | 11 | private IniHeler(){} 12 | } 13 | -------------------------------------------------------------------------------- /common/src/main/java/com.weasel.penetrate.common/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by dell on 2017/2/22. 3 | */ 4 | package com.weasel.penetrate.common; -------------------------------------------------------------------------------- /common/target/classes/com/weasel/penetrate/common/helper/GsonHelper.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/common/target/classes/com/weasel/penetrate/common/helper/GsonHelper.class -------------------------------------------------------------------------------- /common/target/classes/com/weasel/penetrate/common/helper/IniHeler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/common/target/classes/com/weasel/penetrate/common/helper/IniHeler.class -------------------------------------------------------------------------------- /common/target/classes/com/weasel/penetrate/common/helper/SystemHelper$Platform.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/common/target/classes/com/weasel/penetrate/common/helper/SystemHelper$Platform.class -------------------------------------------------------------------------------- /common/target/classes/com/weasel/penetrate/common/helper/SystemHelper.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/common/target/classes/com/weasel/penetrate/common/helper/SystemHelper.class -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/ApplicationLauncher.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager; 2 | 3 | import com.weasel.penetrate.manager.infrastructure.listener.ApplicationStartOverListener; 4 | import com.weasel.penetrate.manager.infrastructure.listener.DeviceCreateListener; 5 | import com.weasel.penetrate.manager.infrastructure.listener.DeviceUpdateListener; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.boot.SpringApplication; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | 12 | /** 13 | * @author Dylan 14 | * @date 2016/7/20. 15 | */ 16 | @SpringBootApplication 17 | public class ApplicationLauncher { 18 | 19 | private final static Logger log = LoggerFactory.getLogger(ApplicationLauncher.class); 20 | 21 | private final static String DEFAULT_ENV = "dev"; 22 | 23 | public static void main(String[] args) { 24 | 25 | String runtimeEnv = System.getProperty("spring.profiles.active"); 26 | if(StringUtils.isBlank(runtimeEnv)){ 27 | log.warn("找不到环境参数设置,使用默认环境[{}],如果需要设置环境参数,在启动脚本加上如:[{}],如:{}",DEFAULT_ENV,"-Dspring.profiles.active=dev|test|prod","java -Dspring.profiles.active=test -jar xxx.jar"); 28 | System.setProperty("spring.profiles.active",DEFAULT_ENV); 29 | } 30 | SpringApplication application = new SpringApplication(ApplicationLauncher.class); 31 | //application.setBannerMode(Banner.Mode.OFF); 32 | application.addListeners(new ApplicationStartOverListener(),new DeviceCreateListener(),new DeviceUpdateListener()); 33 | application.run(args); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/domain/AbstractEntity.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.domain; 2 | 3 | import com.weasel.penetrate.manager.infrastructure.helper.SpringBeanHolder; 4 | 5 | import java.io.Serializable; 6 | import java.lang.reflect.ParameterizedType; 7 | import java.lang.reflect.Type; 8 | 9 | /** 10 | * @author dylan 11 | * @time 2017/6/7 12 | */ 13 | public abstract class AbstractEntity implements Serializable { 14 | 15 | protected transient Class repoClass; 16 | 17 | public AbstractEntity() { 18 | Type type = getClass().getGenericSuperclass(); 19 | repoClass = (Class)((ParameterizedType)type).getActualTypeArguments()[0]; 20 | } 21 | 22 | protected T repo(){ 23 | return SpringBeanHolder.getBean(repoClass); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/domain/IniConfig.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.domain; 2 | 3 | 4 | import com.weasel.penetrate.manager.domain.device.Device; 5 | 6 | import java.util.Set; 7 | 8 | /** 9 | * @author Dylan 10 | * @date 2017/1/22. 11 | */ 12 | public class IniConfig { 13 | 14 | /** 15 | * 通用配置 16 | */ 17 | private Common common; 18 | 19 | /** 20 | * ssh配置 21 | */ 22 | private Set devices; 23 | 24 | 25 | public Common getCommon() { 26 | return common; 27 | } 28 | 29 | public void setCommon(Common common) { 30 | this.common = common; 31 | } 32 | 33 | public Set getDevices() { 34 | return devices; 35 | } 36 | 37 | public void setDevices(Set devices) { 38 | this.devices = devices; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/domain/Page.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.domain; 2 | 3 | import com.google.common.collect.Lists; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by dypan on 2017/2/18. 9 | */ 10 | public class Page { 11 | 12 | private List result = Lists.newArrayList(); 13 | 14 | 15 | public List getResult() { 16 | return result; 17 | } 18 | 19 | public void setResult(List result) { 20 | this.result = result; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/domain/Role.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package com.weasel.penetrate.manager.domain; 20 | 21 | /** 22 | * @author Dylan 23 | * @time 2013-8-5 24 | */ 25 | public class Role{ 26 | 27 | private long id; 28 | 29 | private String code; 30 | 31 | private String name; 32 | 33 | 34 | public Role(){} 35 | 36 | public Role(String name) { 37 | this.name = name; 38 | } 39 | 40 | public long getId() { 41 | return id; 42 | } 43 | 44 | public void setId(long id) { 45 | this.id = id; 46 | } 47 | 48 | public String getName() { 49 | return name; 50 | } 51 | 52 | public void setName(String name) { 53 | this.name = name; 54 | } 55 | 56 | public String getCode() { 57 | return code; 58 | } 59 | 60 | public void setCode(String code) { 61 | this.code = code; 62 | } 63 | 64 | } 65 | 66 | 67 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/EventPublisher.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | import org.springframework.context.ApplicationEventPublisher; 5 | import org.springframework.context.ApplicationEventPublisherAware; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * Created by dell on 2017/3/29. 10 | */ 11 | @Component 12 | public class EventPublisher implements ApplicationEventPublisherAware { 13 | 14 | private static ApplicationEventPublisher applicationEventPublisher; 15 | @Override 16 | public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { 17 | this.applicationEventPublisher = applicationEventPublisher; 18 | } 19 | 20 | public static void publishEvent(ApplicationEvent event){ 21 | applicationEventPublisher.publishEvent(event); 22 | } 23 | 24 | public static void publishEvent(Object event){ 25 | applicationEventPublisher.publishEvent(event); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/Frp.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure; 2 | 3 | /** 4 | * @author Dylan 5 | * @date 2017/1/22. 6 | */ 7 | public class Frp { 8 | 9 | private static String home; 10 | 11 | public static String getHome() { 12 | return home; 13 | } 14 | 15 | public static void setHome(String home) { 16 | Frp.home = home; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/annotation/JQGridId.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by dell on 2017/3/14. 10 | */ 11 | @Target(ElementType.FIELD) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface JQGridId { 14 | } 15 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/config/PenetrateConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | /** 7 | * Created by picke on 2017/5/14. 8 | */ 9 | @Configuration 10 | @ConfigurationProperties(prefix = "penetrate") 11 | public class PenetrateConfiguration { 12 | 13 | private String domain; 14 | 15 | public String getDomain() { 16 | return domain; 17 | } 18 | 19 | public void setDomain(String domain) { 20 | this.domain = domain; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/config/SpringBootConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.config; 2 | 3 | import com.weasel.penetrate.manager.infrastructure.formatter.factory.JQGridIdFormatAnnotationFormatterFactory; 4 | import com.weasel.penetrate.manager.infrastructure.helper.SpringBeanHolder; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.format.FormatterRegistry; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 9 | 10 | /** 11 | * Created by dell on 2017/3/14. 12 | */ 13 | @Configuration 14 | public class SpringBootConfiguration extends WebMvcConfigurerAdapter { 15 | 16 | @Override 17 | public void addFormatters(FormatterRegistry registry) { 18 | registry.addFormatterForFieldAnnotation(new JQGridIdFormatAnnotationFormatterFactory()); 19 | } 20 | 21 | @Bean 22 | public SpringBeanHolder beanHolder(){ 23 | return new SpringBeanHolder(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/config/ThymeleafConfig.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.config; 2 | 3 | import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.web.servlet.ViewResolver; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 9 | import org.thymeleaf.TemplateEngine; 10 | import org.thymeleaf.spring4.SpringTemplateEngine; 11 | import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver; 12 | import org.thymeleaf.spring4.view.ThymeleafViewResolver; 13 | import org.thymeleaf.templatemode.TemplateMode; 14 | import org.thymeleaf.templateresolver.ITemplateResolver; 15 | 16 | /*@Configuration 17 | @EnableWebMvc 18 | @ComponentScan("com.weasel.penetrate.manager")*/ 19 | @Deprecated 20 | public class ThymeleafConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware { 21 | 22 | private ApplicationContext applicationContext; 23 | 24 | public void setApplicationContext(ApplicationContext applicationContext) { 25 | this.applicationContext = applicationContext; 26 | } 27 | 28 | @Bean 29 | public ViewResolver viewResolver() { 30 | ThymeleafViewResolver resolver = new ThymeleafViewResolver(); 31 | resolver.setTemplateEngine(templateEngine()); 32 | resolver.setCharacterEncoding("UTF-8"); 33 | return resolver; 34 | } 35 | 36 | @Bean 37 | public TemplateEngine templateEngine() { 38 | SpringTemplateEngine engine = new SpringTemplateEngine(); 39 | engine.setEnableSpringELCompiler(true); 40 | engine.setTemplateResolver(templateResolver()); 41 | engine.addDialect(new ShiroDialect()); 42 | return engine; 43 | } 44 | 45 | private ITemplateResolver templateResolver() { 46 | SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); 47 | resolver.setApplicationContext(applicationContext); 48 | resolver.setPrefix("/templates/"); 49 | resolver.setTemplateMode(TemplateMode.HTML); 50 | return resolver; 51 | } 52 | } -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/exception/DevicePortBindedException.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.exception; 2 | 3 | /** 4 | * Created by dell on 2017/3/20. 5 | */ 6 | public class DevicePortBindedException extends Exception { 7 | 8 | public DevicePortBindedException() { 9 | super(); 10 | } 11 | 12 | public DevicePortBindedException(String s) { 13 | super(s); 14 | } 15 | 16 | public DevicePortBindedException(String s, Throwable throwable) { 17 | super(s, throwable); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/exception/DevicePortUsedUpException.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.exception; 2 | 3 | /** 4 | * Created by dell on 2017/3/20. 5 | */ 6 | public class DevicePortUsedUpException extends Exception { 7 | 8 | public DevicePortUsedUpException() { 9 | super(); 10 | } 11 | 12 | public DevicePortUsedUpException(String s) { 13 | super(s); 14 | } 15 | 16 | public DevicePortUsedUpException(String s, Throwable throwable) { 17 | super(s, throwable); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/exception/DeviceSubDomainUsedException.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.exception; 2 | 3 | /** 4 | * Created by dell on 2017/3/20. 5 | */ 6 | public class DeviceSubDomainUsedException extends Exception { 7 | 8 | public DeviceSubDomainUsedException() { 9 | super(); 10 | } 11 | 12 | public DeviceSubDomainUsedException(String s) { 13 | super(s); 14 | } 15 | 16 | public DeviceSubDomainUsedException(String s, Throwable throwable) { 17 | super(s, throwable); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/exception/LockAccountException.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.exception; 2 | 3 | /** 4 | * 用户同时在线异常 5 | * @author Dylan 6 | * @time 2013-8-12 7 | */ 8 | public class LockAccountException extends RuntimeException { 9 | 10 | /** 11 | * 12 | */ 13 | private static final long serialVersionUID = 7510980789927862457L; 14 | 15 | public LockAccountException(){ 16 | super(); 17 | } 18 | 19 | public LockAccountException(String message){ 20 | super(message); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/exception/UserExistException.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.exception; 2 | 3 | /** 4 | * @author Dylan 5 | * @date 2017/2/6. 6 | */ 7 | public class UserExistException extends Exception { 8 | 9 | public UserExistException(String s) { 10 | super(s); 11 | } 12 | 13 | public UserExistException(String s, Throwable throwable) { 14 | super(s, throwable); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/formatter/JQGridIdFormatter.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.formatter; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.springframework.format.Formatter; 5 | 6 | import java.io.Serializable; 7 | import java.text.ParseException; 8 | import java.util.Locale; 9 | 10 | /** 11 | * Created by dell on 2017/3/14. 12 | */ 13 | public class JQGridIdFormatter implements Formatter,Serializable { 14 | 15 | @Override 16 | public Long parse(String value, Locale locale) throws ParseException { 17 | if(StringUtils.isBlank(value) || StringUtils.equals(value,"_empty")){ 18 | return new Long(-1); 19 | } 20 | return Long.valueOf(value); 21 | } 22 | 23 | @Override 24 | public String print(Long value, Locale locale) { 25 | if(value == null) { 26 | return ""; 27 | } 28 | return value.toString(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/formatter/factory/JQGridIdFormatAnnotationFormatterFactory.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.formatter.factory; 2 | 3 | import com.google.common.collect.Sets; 4 | import com.weasel.penetrate.manager.infrastructure.annotation.JQGridId; 5 | import com.weasel.penetrate.manager.infrastructure.formatter.JQGridIdFormatter; 6 | import org.springframework.format.AnnotationFormatterFactory; 7 | import org.springframework.format.Parser; 8 | import org.springframework.format.Printer; 9 | 10 | import java.util.Set; 11 | 12 | /** 13 | * Created by dell on 2017/3/14. 14 | */ 15 | public class JQGridIdFormatAnnotationFormatterFactory implements AnnotationFormatterFactory { 16 | 17 | private final Set> fieldTypes = Sets.newHashSet(Long.class); 18 | private final JQGridIdFormatter formatter = new JQGridIdFormatter(); 19 | 20 | @Override 21 | public Set> getFieldTypes() { 22 | return fieldTypes; 23 | } 24 | 25 | @Override 26 | public Printer getPrinter(JQGridId jqGridId, Class aClass) { 27 | return formatter; 28 | } 29 | 30 | @Override 31 | public Parser getParser(JQGridId jqGridId, Class aClass) { 32 | return formatter; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/helper/PasswordHelper.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.helper; 2 | 3 | import org.apache.shiro.crypto.RandomNumberGenerator; 4 | import org.apache.shiro.crypto.SecureRandomNumberGenerator; 5 | import org.apache.shiro.crypto.hash.SimpleHash; 6 | import org.apache.shiro.util.ByteSource; 7 | 8 | 9 | /** 10 | * @author Dylan 11 | * @time 2013-8-8 12 | */ 13 | public class PasswordHelper { 14 | 15 | private final static RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator(); 16 | 17 | 18 | public static String createSalt(){ 19 | 20 | return randomNumberGenerator.nextBytes() 21 | .toHex(); 22 | } 23 | 24 | /** 25 | * 26 | * @param password 27 | * @param credentialsSalt 28 | * @param algorithn 29 | * @param hashIterations 30 | * @return 31 | */ 32 | public static String encrypt(String password,String credentialsSalt,AlgorithnEnum algorithn,int hashIterations){ 33 | 34 | return new SimpleHash( 35 | algorithn.name(), 36 | password, 37 | ByteSource.Util.bytes(credentialsSalt), 38 | hashIterations 39 | ).toHex(); 40 | } 41 | 42 | /** 43 | * 44 | * @param password 45 | * @param credentialsSalt 46 | * @param algorithn 47 | * @return 48 | */ 49 | public static String encrypt(String password,String credentialsSalt,AlgorithnEnum algorithn){ 50 | 51 | return encrypt(password,credentialsSalt,algorithn,1); 52 | } 53 | 54 | /** 55 | * 56 | * @param password 57 | * @param credentialsSalt 58 | * @return 59 | */ 60 | public static String encrypt(String password,String credentialsSalt){ 61 | 62 | return encrypt(password,credentialsSalt,AlgorithnEnum.MD5,1); 63 | } 64 | 65 | public static enum AlgorithnEnum{ 66 | 67 | MD2("MD2"),MD5("MD5"),SHA512("SHA-512"),SHA384("SHA-384"),SHA256("SHA-256"),SHA1("SHA-1"); 68 | 69 | private String name; 70 | 71 | AlgorithnEnum(String name) { 72 | this.name = name; 73 | } 74 | 75 | public String getName() { 76 | return name; 77 | } 78 | 79 | public void setName(String name) { 80 | this.name = name; 81 | } 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/helper/SecurityHelper.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.helper; 2 | 3 | import com.weasel.penetrate.manager.domain.User; 4 | import org.apache.shiro.SecurityUtils; 5 | import org.apache.shiro.subject.Subject; 6 | 7 | /** 8 | * Created by dell on 2017/2/24. 9 | */ 10 | public final class SecurityHelper { 11 | 12 | public static User getCurrentUser(){ 13 | 14 | Subject currentUser = SecurityUtils.getSubject(); 15 | if(currentUser.isAuthenticated()){ 16 | return (User)currentUser.getPrincipal(); 17 | } 18 | 19 | return null; 20 | } 21 | 22 | public static boolean isAdmin(){ 23 | return SecurityUtils.getSubject().hasRole("ADMIN"); 24 | } 25 | 26 | private SecurityHelper(){} 27 | } 28 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/helper/SpringBeanHolder.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.helper; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.BeansException; 6 | import org.springframework.context.ApplicationContext; 7 | import org.springframework.context.ApplicationContextAware; 8 | 9 | /** 10 | * Created by dylan on 17-3-19. 11 | */ 12 | public class SpringBeanHolder implements ApplicationContextAware { 13 | 14 | private static ApplicationContext context; 15 | private final static Logger log = LoggerFactory.getLogger(SpringBeanHolder.class); 16 | 17 | @Override 18 | public void setApplicationContext(ApplicationContext _context) 19 | throws BeansException { 20 | context = _context; 21 | } 22 | 23 | public static ApplicationContext getContext() { 24 | if (null == context) 25 | throw new RuntimeException( 26 | "please register the SpringBeanHolder bean to spring..."); 27 | return context; 28 | } 29 | 30 | /** 31 | * 32 | * @param clazz 33 | * @return 34 | */ 35 | public static T getBean(Class clazz) { 36 | try { 37 | return getContext().getBean(clazz); 38 | } catch (BeansException e) { 39 | log.warn("can not found bean " + clazz.getName()); 40 | } 41 | return null; 42 | } 43 | 44 | /** 45 | * 46 | * @param beanName 47 | * @return 48 | */ 49 | public static Object getBean(String beanName) { 50 | try { 51 | return getContext().getBean(beanName); 52 | } catch (BeansException e) { 53 | log.warn("can not found bean " + beanName); 54 | } 55 | return null; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/ini/IniHandler.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.ini; 2 | 3 | import org.ini4j.Config; 4 | import org.ini4j.Ini; 5 | 6 | /** 7 | * @author Dylan 8 | * @date 2017/1/18. 9 | */ 10 | public abstract class IniHandler { 11 | 12 | protected final Config iniCfg = new Config(); 13 | protected final Ini ini = new Ini(); 14 | { 15 | iniCfg.setMultiSection(true); 16 | ini.setConfig(iniCfg); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/ini/IniReader.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.ini; 2 | 3 | import com.google.common.io.Resources; 4 | import com.weasel.penetrate.manager.infrastructure.ini.section.ListSection; 5 | import com.weasel.penetrate.manager.infrastructure.ini.section.OneSection; 6 | import org.ini4j.Profile; 7 | import org.springframework.util.Assert; 8 | 9 | import java.io.IOException; 10 | import java.net.URL; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.Set; 14 | import java.util.regex.Pattern; 15 | 16 | import static java.util.stream.Collectors.toList; 17 | 18 | /** 19 | * @author Dylan 20 | * @date 2017/1/18. 21 | */ 22 | public class IniReader extends IniHandler{ 23 | 24 | private IniReader(){} 25 | 26 | public static IniReader create(){ 27 | return new IniReader(); 28 | } 29 | 30 | public IniReader load(String file) throws IOException { 31 | URL url = Resources.getResource(file); 32 | ini.load(url); 33 | return this; 34 | } 35 | 36 | public IniReader load(URL url) throws IOException { 37 | ini.load(url); 38 | return this; 39 | } 40 | 41 | public OneSection readOne(String sectionName){ 42 | 43 | Assert.hasText(sectionName,"sectionName can not be empty"); 44 | 45 | Profile.Section section = ini.get(sectionName); 46 | 47 | Assert.notNull(section,"no section name ["+sectionName+"] found"); 48 | return new OneSection(section); 49 | } 50 | 51 | 52 | public ListSection readList(String sectionName){ 53 | 54 | Assert.hasText(sectionName,"sectionName can not be empty"); 55 | 56 | List sections = ini.getAll(sectionName); 57 | Assert.notEmpty(sections,"no section name ["+sectionName+"] found"); 58 | return new ListSection(sections); 59 | } 60 | 61 | public ListSection readRegular(String regular){ 62 | 63 | Pattern pattern = Pattern.compile(regular); 64 | 65 | Set> set = ini.entrySet(); 66 | 67 | List sections = set.stream() 68 | .filter(entry -> pattern.matcher(entry.getKey()).find()) 69 | .map(entry -> entry.getValue()) 70 | .collect(toList()); 71 | return new ListSection(sections); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/ini/IniWriter.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.ini; 2 | 3 | import com.weasel.penetrate.manager.domain.Common; 4 | import com.weasel.penetrate.manager.domain.IniConfig; 5 | import com.weasel.penetrate.manager.domain.device.Device; 6 | import org.apache.commons.lang3.StringUtils; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.util.Set; 11 | 12 | /** 13 | * @author Dylan 14 | * @date 2017/1/18. 15 | */ 16 | public class IniWriter extends IniHandler{ 17 | 18 | private IniWriter(){} 19 | 20 | public static IniWriter create(){ 21 | return new IniWriter(); 22 | } 23 | 24 | public IniWriter load(IniConfig config){ 25 | 26 | Common common = config.getCommon(); 27 | write("common","bind_addr",common.getBindAddr()); 28 | write("common","bind_port",common.getBindPort()); 29 | write("common","log_file",common.getLogFile()); 30 | write("common","log_level",common.getLogLevel()); 31 | write("common","log_max_days",common.getLogMaxDays()); 32 | write("common","vhost_http_port",common.getVhostHttpPort()); 33 | write("common","vhost_https_port",common.getVhostHttpsPort()); 34 | write("common","dashboard_port",common.getDashboardPort()); 35 | write("common","dashboard_user",common.getDashboardUser()); 36 | write("common","dashboard_pwd",common.getDashboardPwd()); 37 | write("common","privilege_mode",common.isPrivilegeMode()); 38 | write("common","privilege_token",common.getPrivilegeToken()); 39 | write("common","privilege_allow_ports",common.getPrivilegeAllowPorts()); 40 | write("common","max_pool_count",common.getMaxPoolCount()); 41 | write("common","authentication_timeout",common.getAuthenticationTimeout()); 42 | write("common","subdomain_host",common.getSubdomainHost()); 43 | Set devices = config.getDevices(); 44 | devices.forEach(device -> { 45 | write(device.getNumber(),"type",device.getProtocolType().getValue()); 46 | write(device.getNumber(),"auth_token",device.getAuthToken()); 47 | write(device.getNumber(),"bind_addr",device.getBindAddr()); 48 | write(device.getNumber(),"listen_port",device.getListenPort()); 49 | write(device.getNumber(),"custom_domains",device.getCustomDomains()); 50 | write(device.getNumber(),"locations",device.getLocations()); 51 | }); 52 | 53 | return this; 54 | } 55 | public IniWriter write(String section,String key,Object value){ 56 | if(null != value){ 57 | if(value instanceof String && StringUtils.isEmpty(String.valueOf(value))){ 58 | return this; 59 | } 60 | ini.put(section,key,value); 61 | } 62 | return this; 63 | } 64 | 65 | public void store(File file) throws IOException { 66 | ini.store(file); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/ini/section/ListSection.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.ini.section; 2 | 3 | import com.google.common.collect.Lists; 4 | import org.ini4j.Profile; 5 | import org.springframework.util.Assert; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Dylan 11 | * @date 2017/1/18. 12 | */ 13 | public class ListSection { 14 | 15 | private List sections = Lists.newArrayList(); 16 | 17 | 18 | public ListSection(List sections) { 19 | Assert.notEmpty(sections,"sections can not be null and empty"); 20 | this.sections = sections; 21 | } 22 | 23 | public List to(Class clazz){ 24 | 25 | List objects = Lists.newArrayList(); 26 | sections.forEach(section -> { 27 | try { 28 | T object = clazz.newInstance(); 29 | section.to(object); 30 | objects.add(object); 31 | } catch (InstantiationException e) { 32 | e.printStackTrace(); 33 | } catch (IllegalAccessException e) { 34 | e.printStackTrace(); 35 | } 36 | }); 37 | return objects; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/ini/section/OneSection.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.ini.section; 2 | 3 | import org.ini4j.Profile; 4 | import org.springframework.util.Assert; 5 | 6 | /** 7 | * @author Dylan 8 | * @date 2017/1/18. 9 | */ 10 | public class OneSection { 11 | 12 | private Profile.Section section = null; 13 | 14 | public OneSection(Profile.Section section) { 15 | Assert.notNull(section,"section can not be null"); 16 | this.section = section; 17 | } 18 | 19 | public T to(Class clazz) throws IllegalAccessException, InstantiationException { 20 | T object = clazz.newInstance(); 21 | section.to(clazz); 22 | return object; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/listener/ApplicationStartOverListener.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.listener; 2 | 3 | import com.weasel.penetrate.common.helper.SystemHelper; 4 | import com.weasel.penetrate.manager.infrastructure.Frp; 5 | import com.weasel.penetrate.manager.service.FrpConfigService; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.context.ApplicationListener; 10 | import org.springframework.context.event.ContextRefreshedEvent; 11 | 12 | import java.io.IOException; 13 | 14 | /**应用启动完监听器 15 | * Created by dylan on 17-3-12. 16 | */ 17 | public class ApplicationStartOverListener implements ApplicationListener { 18 | 19 | private final Logger logger = LoggerFactory.getLogger(ApplicationStartOverListener.class); 20 | 21 | @Override 22 | public void onApplicationEvent(ContextRefreshedEvent event) { 23 | 24 | String runtimeEnv = System.getProperty("spring.profiles.active"); 25 | logger.info("当前运行环境是[{}]",runtimeEnv); 26 | String frpHome = System.getProperty("frp.home"); 27 | if(StringUtils.isEmpty(frpHome)){ 28 | throw new RuntimeException("请在启动时传入frp.home参数,例如:java -Dfrp.home=/usr/local/softwares/frp_0.9.3_windows_amd64 -jar xxx.jar"); 29 | } 30 | logger.info("当前frp目录是:" + frpHome); 31 | Frp.setHome(frpHome); 32 | logger.info("当前操作系统[{}]", SystemHelper.getOSname()); 33 | 34 | //防止重复执行。 35 | if(event.getApplicationContext().getParent() == null){ 36 | FrpConfigService frpConfigService = event.getApplicationContext().getBean(FrpConfigService.class); 37 | try { 38 | frpConfigService.reloadConfig(Frp.getHome()); 39 | } catch (IOException e) { 40 | logger.error(e.getMessage()); 41 | } catch (InterruptedException e) { 42 | logger.error(e.getMessage()); 43 | } 44 | 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/listener/DeviceCreateListener.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.listener; 2 | 3 | import com.weasel.penetrate.manager.domain.device.Device; 4 | import com.weasel.penetrate.manager.infrastructure.listener.event.DeviceCreateEvent; 5 | import com.weasel.penetrate.manager.infrastructure.task.ReloadFrpConfigQueue; 6 | import com.weasel.penetrate.manager.infrastructure.task.ReloadFrpConfigScheduled; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.context.ApplicationListener; 10 | 11 | /** 12 | * Created by dell on 2017/3/29. 13 | */ 14 | public class DeviceCreateListener implements ApplicationListener { 15 | 16 | private final static Logger logger = LoggerFactory.getLogger(DeviceCreateListener.class); 17 | 18 | @Override 19 | public void onApplicationEvent(DeviceCreateEvent event) { 20 | 21 | Device device = event.getMessage(); 22 | logger.info("device [{}] create event happend.",device.getNumber()); 23 | ReloadFrpConfigScheduled.submitTask(new ReloadFrpConfigQueue.ReloadFrpConfigTask()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/listener/DeviceUpdateListener.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.listener; 2 | 3 | import com.weasel.penetrate.manager.domain.device.Device; 4 | import com.weasel.penetrate.manager.infrastructure.listener.event.DeviceUpdateEvent; 5 | import com.weasel.penetrate.manager.infrastructure.task.ReloadFrpConfigQueue; 6 | import com.weasel.penetrate.manager.infrastructure.task.ReloadFrpConfigScheduled; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.context.ApplicationListener; 10 | 11 | /** 12 | * Created by dell on 2017/3/29. 13 | */ 14 | public class DeviceUpdateListener implements ApplicationListener { 15 | 16 | private final static Logger logger = LoggerFactory.getLogger(DeviceUpdateListener.class); 17 | 18 | 19 | @Override 20 | public void onApplicationEvent(DeviceUpdateEvent event) { 21 | 22 | Device device = event.getMessage(); 23 | logger.info("device [{}] update event happend.",device.getNumber()); 24 | ReloadFrpConfigScheduled.submitTask(new ReloadFrpConfigQueue.ReloadFrpConfigTask()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/listener/event/AbstractCommonEvent.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.listener.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | /** 6 | * Created by dell on 2017/3/29. 7 | */ 8 | public abstract class AbstractCommonEvent extends ApplicationEvent { 9 | 10 | private T message; 11 | /** 12 | * Create a new ApplicationEvent. 13 | * 14 | * @param source the object on which the event initially occurred (never {@code null}) 15 | */ 16 | public AbstractCommonEvent(Object source,T message) { 17 | super(source); 18 | this.message = message; 19 | } 20 | 21 | public T getMessage() { 22 | return message; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/listener/event/DeviceCreateEvent.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.listener.event; 2 | 3 | import com.weasel.penetrate.manager.domain.device.Device; 4 | 5 | /** 6 | * Created by dell on 2017/3/29. 7 | */ 8 | public class DeviceCreateEvent extends AbstractCommonEvent { 9 | 10 | public DeviceCreateEvent(Object source, Device message) { 11 | super(source, message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/listener/event/DeviceUpdateEvent.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.listener.event; 2 | 3 | import com.weasel.penetrate.manager.domain.device.Device; 4 | 5 | /** 6 | * Created by dell on 2017/3/29. 7 | */ 8 | public class DeviceUpdateEvent extends AbstractCommonEvent { 9 | 10 | public DeviceUpdateEvent(Object source, Device message) { 11 | super(source, message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/repository/CommonRepository.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.repository; 2 | 3 | 4 | import com.weasel.penetrate.manager.domain.Common; 5 | 6 | /** 7 | * @author Dylan 8 | * @date 2017/2/6. 9 | */ 10 | public interface CommonRepository { 11 | 12 | Common get(); 13 | } 14 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/repository/DeviceRepository.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.repository; 2 | 3 | 4 | import com.weasel.penetrate.manager.domain.device.Device; 5 | import com.weasel.penetrate.manager.infrastructure.exception.DevicePortUsedUpException; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Dylan 11 | * @date 2017/1/22. 12 | */ 13 | public interface DeviceRepository { 14 | 15 | /** 16 | * 添加设备 17 | * @param device 18 | * @return 19 | */ 20 | Device add(Device device); 21 | 22 | /** 23 | * 更新设备 24 | * @param device 25 | * @return 26 | */ 27 | int update(Device device); 28 | 29 | /** 30 | * 查询设备 31 | * @param device 32 | * @return 33 | */ 34 | List query(Device device); 35 | 36 | /** 37 | * 删除设备 38 | * @param device 39 | * @return 40 | */ 41 | int delete(Device device); 42 | 43 | /** 44 | * 45 | * @param listenPort 46 | * @return 47 | */ 48 | int countByPort(String listenPort); 49 | 50 | /** 51 | * @param subdomain 52 | * @return 53 | */ 54 | int countBySubDomain(String subdomain); 55 | 56 | /** 57 | * 58 | * @return 59 | */ 60 | int getMaxDistributedPort() throws DevicePortUsedUpException; 61 | 62 | /** 63 | * 64 | * @param name 65 | * @return 66 | */ 67 | int deleteByUsername(String name); 68 | } 69 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/repository/MybatisDaoSupport.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.repository; 2 | 3 | import org.apache.ibatis.session.SqlSessionFactory; 4 | import org.mybatis.spring.support.SqlSessionDaoSupport; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | 7 | /** 8 | * Created by dypan on 2017/2/18. 9 | */ 10 | public abstract class MybatisDaoSupport extends SqlSessionDaoSupport { 11 | 12 | 13 | 14 | @Autowired 15 | public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { 16 | super.setSqlSessionFactory(sqlSessionFactory); 17 | } 18 | 19 | 20 | protected abstract String namespace(); 21 | } 22 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.repository; 2 | 3 | 4 | import com.weasel.penetrate.manager.domain.Page; 5 | import com.weasel.penetrate.manager.domain.User; 6 | 7 | /** 8 | * @author Dylan 9 | * @date 2017/2/6. 10 | */ 11 | public interface UserRepository { 12 | 13 | /** 14 | * 15 | * @param name 16 | * @return 17 | */ 18 | User getUserByName(String name); 19 | 20 | /** 21 | * 22 | * @param id 23 | * @return 24 | */ 25 | User getUserById(long id); 26 | 27 | /** 28 | * 29 | * @param email 30 | * @return 31 | */ 32 | User getUserByEmail(String email); 33 | 34 | /** 35 | * 36 | * @param page 37 | * @return 38 | */ 39 | Page queryPage(Page page); 40 | 41 | /** 42 | * 43 | * @param user 44 | * @return 45 | */ 46 | int update(User user); 47 | 48 | /** 49 | * 50 | * @param user 51 | * @return 52 | */ 53 | int insert(User user); 54 | 55 | /** 56 | * 57 | * @param id 58 | * @return 59 | */ 60 | int delete(long id); 61 | } 62 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/repository/impl/CommonRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.repository.impl; 2 | 3 | import com.weasel.penetrate.manager.domain.Common; 4 | import com.weasel.penetrate.manager.infrastructure.repository.CommonRepository; 5 | import com.weasel.penetrate.manager.infrastructure.repository.MybatisDaoSupport; 6 | import org.springframework.stereotype.Repository; 7 | 8 | /** 9 | * @author Dylan 10 | * @date 2017/1/22. 11 | */ 12 | @Repository 13 | public class CommonRepositoryImpl extends MybatisDaoSupport implements CommonRepository { 14 | 15 | @Override 16 | public Common get() { 17 | return getSqlSession().selectOne(namespace().concat(".get")); 18 | } 19 | 20 | @Override 21 | protected String namespace() { 22 | return Common.class.getName(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/repository/impl/DeviceRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.repository.impl; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.weasel.penetrate.manager.domain.device.Device; 5 | import com.weasel.penetrate.manager.infrastructure.exception.DevicePortUsedUpException; 6 | import com.weasel.penetrate.manager.infrastructure.repository.DeviceRepository; 7 | import com.weasel.penetrate.manager.infrastructure.repository.MybatisDaoSupport; 8 | import org.apache.commons.lang3.StringUtils; 9 | import org.springframework.stereotype.Repository; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author Dylan 15 | * @date 2017/1/22. 16 | */ 17 | @Repository 18 | public class DeviceRepositoryImpl extends MybatisDaoSupport implements DeviceRepository { 19 | 20 | private final static int minPort = 8000; 21 | private final static int maxPort = 9999; 22 | 23 | @Override 24 | public Device add(Device device) { 25 | getSqlSession().insert(namespace().concat(".insert"),device); 26 | return device; 27 | } 28 | 29 | @Override 30 | public int update(Device device) { 31 | return getSqlSession().update(namespace().concat(".update"),device); 32 | } 33 | 34 | @Override 35 | public List query(Device device) { 36 | 37 | List devices = getSqlSession().selectList(namespace().concat(".query"),device); 38 | return null != device ? devices : Lists.newArrayList(); 39 | } 40 | 41 | @Override 42 | public int delete(Device device) { 43 | return getSqlSession().delete(namespace().concat(".deleteById"),device); 44 | } 45 | 46 | @Override 47 | public int countByPort(String listenPort) { 48 | if(StringUtils.isBlank(listenPort)){ 49 | return 0; 50 | } 51 | return getSqlSession().selectOne(namespace().concat(".countByPort"),listenPort); 52 | } 53 | 54 | @Override 55 | public int countBySubDomain(String subdomain) { 56 | if(StringUtils.isBlank(subdomain)){ 57 | return 0; 58 | } 59 | return getSqlSession().selectOne(namespace().concat(".countBySubDomain"),subdomain); 60 | } 61 | 62 | @Override 63 | public int getMaxDistributedPort() throws DevicePortUsedUpException { 64 | Integer port = getSqlSession().selectOne(namespace().concat(".getMaxDistributedPort")); 65 | if(null != port && port > maxPort){ 66 | throw new DevicePortUsedUpException("["+minPort+"]-["+maxPort+"]之间的端口已被用完"); 67 | } 68 | return (null != port &&port >=minPort) ? port : minPort; 69 | } 70 | 71 | @Override 72 | public int deleteByUsername(String name) { 73 | return getSqlSession().delete(namespace().concat(".deleteByUsername"),name); 74 | } 75 | 76 | @Override 77 | protected String namespace() { 78 | return Device.class.getName(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/repository/impl/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.repository.impl; 2 | 3 | import com.weasel.penetrate.manager.domain.Page; 4 | import com.weasel.penetrate.manager.domain.User; 5 | import com.weasel.penetrate.manager.infrastructure.repository.DeviceRepository; 6 | import com.weasel.penetrate.manager.infrastructure.repository.MybatisDaoSupport; 7 | import com.weasel.penetrate.manager.infrastructure.repository.UserRepository; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Repository; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author Dylan 15 | * @date 2017/2/6. 16 | */ 17 | @Repository 18 | public class UserRepositoryImpl extends MybatisDaoSupport implements UserRepository { 19 | 20 | 21 | @Autowired 22 | private DeviceRepository deviceRepository; 23 | 24 | @Override 25 | public User getUserByName(String name) { 26 | return getSqlSession().selectOne(namespace().concat(".getUserByName"),name); 27 | } 28 | 29 | @Override 30 | public User getUserById(long id) { 31 | return getSqlSession().selectOne(namespace().concat(".getUserById"),id); 32 | } 33 | 34 | @Override 35 | public User getUserByEmail(String email) { 36 | return getSqlSession().selectOne(namespace().concat(".getUserByEmail"),email); 37 | } 38 | 39 | @Override 40 | public Page queryPage(Page page) { 41 | 42 | List users = getSqlSession().selectList(namespace().concat(".queryPage"),page); 43 | page.setResult(users); 44 | return page; 45 | } 46 | 47 | @Override 48 | public int update(User user) { 49 | return getSqlSession().update(namespace().concat(".update"),user); 50 | } 51 | 52 | @Override 53 | public int insert(User user) { 54 | return getSqlSession().insert(namespace().concat(".insert"),user); 55 | } 56 | 57 | @Override 58 | public int delete(long id) { 59 | 60 | User user = getUserById(id); 61 | int result = getSqlSession().delete(namespace().concat(".deleteById"),id); 62 | if(0 == result){ 63 | return result; 64 | } 65 | 66 | return deviceRepository.deleteByUsername(user.getName()); 67 | } 68 | 69 | @Override 70 | protected String namespace() { 71 | return User.class.getName(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/task/ReloadFrpConfigQueue.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.task; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.util.concurrent.LinkedBlockingQueue; 7 | 8 | /** 9 | * Created by dylan on 17-3-19. 10 | */ 11 | public class ReloadFrpConfigQueue { 12 | 13 | private final static Logger logger = LoggerFactory.getLogger(ReloadFrpConfigQueue.class); 14 | 15 | private final LinkedBlockingQueue queue = new LinkedBlockingQueue(); 16 | 17 | public synchronized void addIfEmpty(T obj){ 18 | if(null == queue.peek()){ 19 | logger.info("更新配置文件任务为空,往队列添加任务。"); 20 | queue.offer(obj); 21 | } 22 | } 23 | 24 | public T get() throws InterruptedException { 25 | return queue.poll(); 26 | } 27 | 28 | public static class ReloadFrpConfigTask{ 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/infrastructure/task/ReloadFrpConfigScheduled.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.infrastructure.task; 2 | 3 | import com.weasel.penetrate.manager.infrastructure.Frp; 4 | import com.weasel.penetrate.manager.infrastructure.helper.SpringBeanHolder; 5 | import com.weasel.penetrate.manager.service.FrpConfigService; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.io.IOException; 11 | import java.util.concurrent.Executors; 12 | import java.util.concurrent.ScheduledExecutorService; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | /** 16 | * Created by dylan on 17-3-19. 17 | */ 18 | @Component 19 | public class ReloadFrpConfigScheduled { 20 | 21 | private final static Logger logger = LoggerFactory.getLogger(ReloadFrpConfigScheduled.class); 22 | 23 | private final static ReloadFrpConfigQueue queue = new ReloadFrpConfigQueue<>(); 24 | private final static ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); 25 | 26 | static { 27 | service.scheduleWithFixedDelay(new Runnable() { 28 | @Override 29 | public void run() { 30 | try { 31 | if(logger.isDebugEnabled()){ 32 | logger.debug("重新加载FRP配置文件任务执行..."); 33 | } 34 | ReloadFrpConfigQueue.ReloadFrpConfigTask _task = queue.get(); 35 | if(null != _task){ 36 | FrpConfigService frpConfigService = SpringBeanHolder.getBean(FrpConfigService.class); 37 | frpConfigService.reloadConfig(Frp.getHome()); 38 | } 39 | } catch (InterruptedException e) { 40 | e.printStackTrace(); 41 | } catch (IOException e) { 42 | e.printStackTrace(); 43 | } 44 | } 45 | }, 0, 30, TimeUnit.SECONDS); 46 | } 47 | public synchronized static void submitTask(ReloadFrpConfigQueue.ReloadFrpConfigTask task){ 48 | queue.addIfEmpty(task); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/interfaces/controller/AdminController.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.interfaces.controller; 2 | 3 | import com.weasel.penetrate.manager.infrastructure.Frp; 4 | import com.weasel.penetrate.manager.interfaces.vo.ResponseMessage; 5 | import com.weasel.penetrate.manager.service.FrpConfigService; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | 13 | import java.io.IOException; 14 | 15 | import static org.springframework.web.bind.annotation.RequestMethod.GET; 16 | 17 | /** 18 | * @author Dylan 19 | * @date 2017/1/22. 20 | */ 21 | @Controller 22 | @RequestMapping(value = "/manager/admin") 23 | public class AdminController{ 24 | 25 | private final static Logger logger = LoggerFactory.getLogger(AdminController.class); 26 | 27 | @Autowired 28 | private FrpConfigService frpConfigService; 29 | 30 | @ResponseBody 31 | @RequestMapping(value = "/reload_config",method = GET) 32 | public ResponseMessage reload(){ 33 | 34 | try { 35 | frpConfigService.reloadConfig(Frp.getHome()); 36 | return ResponseMessage.success(); 37 | } catch (IOException e) { 38 | e.printStackTrace(); 39 | } catch (InterruptedException e) { 40 | e.printStackTrace(); 41 | } 42 | return ResponseMessage.error().setMessage("加载frp配置文件失败"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/interfaces/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.interfaces.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.ui.Model; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | 7 | import static org.springframework.web.bind.annotation.RequestMethod.GET; 8 | 9 | /** 10 | * @author Dylan 11 | * @date 2017/1/20. 12 | */ 13 | @Controller 14 | public class HomeController { 15 | 16 | @RequestMapping(value = {"/","/home","/index"},method = GET) 17 | public String home(Model model){ 18 | 19 | return "home"; 20 | } 21 | 22 | @RequestMapping(value = {"/course"},method = GET) 23 | public String course(Model model){ 24 | 25 | return "course"; 26 | } 27 | 28 | @RequestMapping(value = {"/frp-status"},method = GET) 29 | public String frpStatus(){ 30 | 31 | return "frp_status"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/interfaces/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.interfaces.controller; 2 | 3 | import com.weasel.penetrate.common.helper.GsonHelper; 4 | import com.weasel.penetrate.manager.domain.Page; 5 | import com.weasel.penetrate.manager.domain.User; 6 | import com.weasel.penetrate.manager.infrastructure.helper.SecurityHelper; 7 | import com.weasel.penetrate.manager.interfaces.vo.ResponseMessage; 8 | import com.weasel.penetrate.manager.service.UserService; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Controller; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.ResponseBody; 13 | 14 | import static org.springframework.web.bind.annotation.RequestMethod.*; 15 | 16 | /** 17 | * @author Dylan 18 | * @date 2017/1/22. 19 | */ 20 | @Controller 21 | @RequestMapping(value = "/manager/user") 22 | public class UserController{ 23 | 24 | @Autowired 25 | private UserService service; 26 | 27 | 28 | @ResponseBody 29 | @RequestMapping(value = "/list",method = GET) 30 | public String list(){ 31 | 32 | Page page = service.queryPage(new Page<>()); 33 | 34 | String gson = GsonHelper.toGson(page.getResult()); 35 | return gson; 36 | } 37 | 38 | @RequestMapping(value = "/list_view",method = GET) 39 | public String listView(){ 40 | 41 | return "manager/user"; 42 | } 43 | 44 | @ResponseBody 45 | @RequestMapping(value= "/save", method= {POST}) 46 | public ResponseMessage save(User user){ 47 | 48 | user = user.createSalt().encodePassword(); 49 | service.save(user); 50 | return ResponseMessage.success(); 51 | } 52 | 53 | @ResponseBody 54 | @RequestMapping(value= "/delete", method= {POST,DELETE}) 55 | public ResponseMessage delete(long id){ 56 | 57 | if(SecurityHelper.isAdmin()){ 58 | int result = service.delete(id); 59 | if(1 == result){ 60 | return ResponseMessage.success(); 61 | } 62 | } 63 | 64 | return ResponseMessage.error(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/interfaces/vo/ResponseMessage.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.interfaces.vo; 2 | 3 | /** 4 | * Created by dylan on 2017/3/4. 5 | */ 6 | public class ResponseMessage { 7 | 8 | private boolean success; 9 | private String message; 10 | 11 | public ResponseMessage() { 12 | } 13 | 14 | public ResponseMessage(boolean success) { 15 | this.success = success; 16 | } 17 | 18 | public ResponseMessage(boolean success, String message) { 19 | this.success = success; 20 | this.message = message; 21 | } 22 | 23 | public boolean isSuccess() { 24 | return success; 25 | } 26 | 27 | public ResponseMessage setSuccess(boolean success) { 28 | this.success = success; 29 | return this; 30 | } 31 | 32 | public String getMessage() { 33 | return message; 34 | } 35 | 36 | public ResponseMessage setMessage(String message) { 37 | this.message = message; 38 | return this; 39 | } 40 | 41 | public static ResponseMessage success(){ 42 | 43 | return new ResponseMessage(true,"成功"); 44 | } 45 | 46 | public static ResponseMessage error(){ 47 | return new ResponseMessage(false); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/service/CommonService.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.service; 2 | 3 | 4 | import com.weasel.penetrate.manager.domain.Common; 5 | 6 | /** 7 | * 8 | */ 9 | public interface CommonService { 10 | 11 | 12 | Common get(); 13 | } 14 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/service/DeviceService.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.service; 2 | 3 | 4 | import com.weasel.penetrate.manager.domain.device.Device; 5 | import com.weasel.penetrate.manager.infrastructure.exception.DevicePortBindedException; 6 | import com.weasel.penetrate.manager.infrastructure.exception.DevicePortUsedUpException; 7 | import com.weasel.penetrate.manager.infrastructure.exception.DeviceSubDomainUsedException; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author Dylan 13 | * @date 2017/1/22. 14 | */ 15 | public interface DeviceService { 16 | 17 | 18 | /** 19 | * 20 | * @param device 21 | * @return 22 | */ 23 | List query(Device device); 24 | 25 | /** 26 | * 27 | * @param device 28 | * @return 29 | */ 30 | Device save(Device device) throws DevicePortBindedException, DeviceSubDomainUsedException, DevicePortUsedUpException; 31 | 32 | /** 33 | * 34 | * @return 35 | */ 36 | int distributePort() throws DevicePortUsedUpException; 37 | 38 | /** 39 | * 40 | * @param id 41 | * @return 42 | */ 43 | int delete(long id); 44 | } 45 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/service/FrpConfigService.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.service; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * @author Dylan 7 | * @date 2017/1/23. 8 | */ 9 | public interface FrpConfigService { 10 | 11 | int reloadConfig(String frpHome) throws IOException, InterruptedException; 12 | } 13 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.service; 2 | 3 | 4 | import com.weasel.penetrate.manager.domain.Page; 5 | import com.weasel.penetrate.manager.domain.User; 6 | import com.weasel.penetrate.manager.infrastructure.exception.UserExistException; 7 | 8 | /** 9 | * @author Dylan 10 | * @date 2017/2/6. 11 | */ 12 | public interface UserService { 13 | 14 | /** 15 | * 16 | * @param user 17 | * @return 18 | */ 19 | User save(User user); 20 | 21 | /** 22 | * 23 | * @param user 24 | * @return 25 | * @throws UserExistException 26 | */ 27 | boolean notExist(User user)throws UserExistException; 28 | 29 | /** 30 | * 31 | * @param page 32 | * @return 33 | */ 34 | Page queryPage(Page page); 35 | 36 | /** 37 | * 38 | * @param id 39 | * @return 40 | */ 41 | int delete(long id); 42 | } 43 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/service/impl/CommonServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.service.impl; 2 | 3 | import com.weasel.penetrate.manager.domain.Common; 4 | import com.weasel.penetrate.manager.infrastructure.repository.CommonRepository; 5 | import com.weasel.penetrate.manager.service.CommonService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author Dylan 11 | * @date 2017/1/22. 12 | */ 13 | @Service 14 | public class CommonServiceImpl implements CommonService { 15 | 16 | @Autowired 17 | private CommonRepository repository; 18 | 19 | @Override 20 | public Common get() { 21 | return repository.get(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/service/impl/FrpConfigServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.service.impl; 2 | 3 | import com.weasel.penetrate.common.helper.SystemHelper; 4 | import com.weasel.penetrate.manager.domain.Common; 5 | import com.weasel.penetrate.manager.domain.IniConfig; 6 | import com.weasel.penetrate.manager.domain.device.Device; 7 | import com.weasel.penetrate.manager.infrastructure.Frp; 8 | import com.weasel.penetrate.manager.infrastructure.ini.IniWriter; 9 | import com.weasel.penetrate.manager.service.CommonService; 10 | import com.weasel.penetrate.manager.service.DeviceService; 11 | import com.weasel.penetrate.manager.service.FrpConfigService; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.stereotype.Service; 16 | import org.springframework.util.Assert; 17 | 18 | import java.io.File; 19 | import java.io.IOException; 20 | import java.util.HashSet; 21 | import java.util.List; 22 | 23 | /** 24 | * @author Dylan 25 | * @date 2017/1/23. 26 | */ 27 | @Service 28 | public class FrpConfigServiceImpl implements FrpConfigService { 29 | 30 | private final static Logger log = LoggerFactory.getLogger(FrpConfigServiceImpl.class); 31 | 32 | @Autowired 33 | private DeviceService deviceService; 34 | 35 | @Autowired 36 | private CommonService commonService; 37 | 38 | 39 | @Override 40 | public int reloadConfig(String frpHome) throws IOException, InterruptedException { 41 | 42 | Assert.hasText(frpHome,"frp目录没指定,请在启动系统的时候将frp所在目录作为启动参数..."); 43 | 44 | IniConfig config = new IniConfig(); 45 | List devices = deviceService.query(new Device()); 46 | Common common = commonService.get(); 47 | config.setDevices(new HashSet<>(devices)); 48 | config.setCommon(common); 49 | 50 | IniWriter.create() 51 | .load(config) 52 | .store(new File(Frp.getHome()+File.separatorChar+"frps.ini")); 53 | 54 | String reloadCommand; 55 | 56 | if(SystemHelper.isWindows()){ 57 | reloadCommand = Frp.getHome()+File.separatorChar+"frps.exe -c "+Frp.getHome()+File.separatorChar+"frps.ini --reload"; 58 | }else { 59 | reloadCommand = Frp.getHome()+File.separatorChar+"frps -c "+Frp.getHome()+File.separatorChar+"frps.ini --reload"; 60 | } 61 | 62 | log.info("重新加载配置文件,执行以下命令[{}]",reloadCommand); 63 | Runtime.getRuntime().exec(reloadCommand).waitFor(); 64 | log.info("重新加载配置文件成功"); 65 | return 0; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /manager/src/main/java/com/weasel/penetrate/manager/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager.service.impl; 2 | 3 | import com.google.common.base.Preconditions; 4 | import com.weasel.penetrate.manager.domain.Page; 5 | import com.weasel.penetrate.manager.domain.User; 6 | import com.weasel.penetrate.manager.infrastructure.exception.UserExistException; 7 | import com.weasel.penetrate.manager.infrastructure.repository.UserRepository; 8 | import com.weasel.penetrate.manager.service.UserService; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Service; 13 | 14 | /** 15 | * @author Dylan 16 | * @date 2017/2/6. 17 | */ 18 | @Service 19 | public class UserServiceImpl implements UserService { 20 | 21 | private final static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class); 22 | 23 | @Autowired 24 | private UserRepository repository; 25 | 26 | @Override 27 | public User save(User user) { 28 | 29 | Preconditions.checkNotNull(user,"user can not be null"); 30 | return user.save(); 31 | } 32 | 33 | @Override 34 | public boolean notExist(User user) throws UserExistException { 35 | return user.notExist(); 36 | } 37 | 38 | @Override 39 | public Page queryPage(Page page) { 40 | return repository.queryPage(page); 41 | } 42 | 43 | 44 | @Override 45 | public int delete(long id) { 46 | return repository.delete(id); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /manager/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | schema: classpath:database-initialize.sql 4 | name: dev 5 | url: jdbc:mysql://127.0.0.1:3306/frp?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC 6 | username: root 7 | password: ENC(SrpFBcVD89eTQ2icOD0TMg==) 8 | # 使用druid数据源 9 | ##type: com.mchange.v2.c3p0.ComboPooledDataSource 10 | driver-class-name: com.mysql.cj.jdbc.Driver 11 | filters: stat 12 | maxActive: 20 13 | initialSize: 1 14 | maxWait: 60000 15 | minIdle: 1 16 | timeBetweenEvictionRunsMillis: 60000 17 | minEvictableIdleTimeMillis: 300000 18 | validationQuery: select 'x' 19 | testWhileIdle: true 20 | testOnBorrow: false 21 | testOnReturn: false 22 | poolPreparedStatements: true 23 | maxOpenPreparedStatements: 20 24 | 25 | logging: 26 | level: 27 | root: info 28 | org: 29 | springframework: warn 30 | hibernate: warn 31 | eclipse: warn 32 | apache: warn 33 | com: 34 | weasel: info 35 | file: "logs/application.log" 36 | -------------------------------------------------------------------------------- /manager/src/main/resources/application-prod.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | name: dev 4 | url: jdbc:mysql://127.0.0.1:3306/frp?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC 5 | username: root 6 | password: ENC(SrpFBcVD89eTQ2icOD0TMg==) 7 | # 使用druid数据源 8 | ##type: com.mchange.v2.c3p0.ComboPooledDataSource 9 | driver-class-name: com.mysql.cj.jdbc.Driver 10 | filters: stat 11 | maxActive: 20 12 | initialSize: 1 13 | maxWait: 60000 14 | minIdle: 1 15 | timeBetweenEvictionRunsMillis: 60000 16 | minEvictableIdleTimeMillis: 300000 17 | validationQuery: select 'x' 18 | testWhileIdle: true 19 | testOnBorrow: false 20 | testOnReturn: false 21 | poolPreparedStatements: true 22 | maxOpenPreparedStatements: 20 23 | 24 | logging: 25 | level: 26 | root: info 27 | org: 28 | springframework: warn 29 | hibernate: warn 30 | eclipse: warn 31 | apache: warn 32 | com: 33 | weasel: info 34 | file: "logs/application.log" 35 | -------------------------------------------------------------------------------- /manager/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | ###jetty 2 | server: 3 | port: 7999 4 | contextPath: / 5 | ## ssl: 6 | ## key-store: classpath:www-kisme-org.jks 7 | ## key-password: ENC(+r7LBLwX7duNyPs4wSgkhTOHbyaWD8Ii) 8 | ## key-store-password: ENC(+r7LBLwX7duNyPs4wSgkhTOHbyaWD8Ii) 9 | 10 | jasypt: 11 | encryptor: 12 | password: 666 13 | 14 | spring: 15 | thymeleaf: 16 | enabled: true 17 | cache: false 18 | check-template: true 19 | check-template-location: true 20 | content-type: text/html 21 | encoding: UTF-8 22 | prefix: classpath:/templates/ 23 | suffix: .html 24 | mode: HTML5 25 | http: 26 | encoding: 27 | charset: UTF-8 28 | enabled: true 29 | force: true 30 | 31 | mybatis: 32 | # type-aliases-package: com.weasel.frp.domain.device 33 | mapper-locations: classpath:mybatis/mappers/*.xml 34 | config-location: classpath:mybatis/mybatis-config.xml 35 | 36 | penetrate: 37 | domain: tun.gogl.top -------------------------------------------------------------------------------- /manager/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | ,:::::.................................. 2 | ::::...........#........................ 3 | ::............###....................... 4 | :.............K #.. ............. 5 | ..............#### ........ 6 | ........... .#### ..... 7 | ........K# ,#### # .. 8 | ....... j# ###### ; . 9 | ..... ########### 10 | .... t##########. #### ## 11 | .. ################ # 12 | . .################# 13 | ########D####### 14 | ####### ####### 15 | ####### ###### # 16 | ############# # 17 | ##########: K 18 | ##########. # 19 | ## t####### # 20 | ###j ########### ## 21 | ### ######### K#### ## 22 | ## ######### E ###G ## 23 | ## ######### ##### 24 | ### ########## ### 25 | ############### ##W # 26 | ##############W ## 27 | ###### #####iK##### 28 | ##t L######## 29 | #### 30 | ### 31 | ## 32 | : , ,, , . :..: -------------------------------------------------------------------------------- /manager/src/main/resources/mybatis/mappers/common.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | SELECT c.bind_addr as c_bind_addr, 28 | c.bind_port as c_bind_port, 29 | c.vhost_http_port as c_vhost_http_port, 30 | c.vhost_https_port as c_vhost_https_port, 31 | c.dashboard_port as c_dashboard_port, 32 | c.dashboard_user as c_dashboard_user, 33 | c.dashboard_pwd as c_dashboard_pwd, 34 | c.log_file as c_log_file, 35 | c.log_level as c_log_level, 36 | c.log_max_days as c_log_max_days, 37 | c.privilege_mode as c_privilege_mode, 38 | c.privilege_token as c_privilege_token, 39 | c.privilege_allow_ports as c_privilege_allow_ports, 40 | c.max_pool_count as c_max_pool_count, 41 | c.authentication_timeout as c_authentication_timeout, 42 | c.subdomain_host as c_subdomain_host 43 | FROM common c 44 | 45 | 46 | 50 | -------------------------------------------------------------------------------- /manager/src/main/resources/mybatis/mappers/device.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | SELECT d.id as d_id, 21 | d.number as d_number, 22 | d.username as d_username, 23 | d.protocol_type as d_protocol_type, 24 | d.auth_token as d_auth_token, 25 | d.bind_addr as d_bind_addr, 26 | d.listen_port as d_listen_port, 27 | d.custom_domains as d_custom_domains, 28 | d.locations as d_locations 29 | FROM device d 30 | 31 | 32 | 40 | 41 | 42 | INSERT INTO device(number,username,protocol_type,auth_token,bind_addr,listen_port,custom_domains,locations) 43 | VALUE (#{number},#{username},#{protocolType},#{authToken},#{bindAddr},#{listenPort},#{customDomains},#{locations}) 44 | 45 | SELECT LAST_INSERT_ID() AS ID 46 | 47 | 48 | 49 | 50 | UPDATE device 51 | 52 | 53 | protocol_type = #{protocolType}, 54 | 55 | 56 | auth_token = #{authToken}, 57 | 58 | 59 | custom_domains = #{customDomains}, 60 | 61 | 62 | locations = #{locations} 63 | 64 | 65 | 66 | id = #{id} 67 | 68 | 69 | 70 | 73 | 74 | 77 | 78 | 79 | DELETE FROM device 80 | 81 | id=#{id} 82 | 83 | and username=#{username} 84 | 85 | 86 | 87 | 88 | 93 | 94 | 95 | DELETE FROM device 96 | WHERE username=#{username} 97 | 98 | -------------------------------------------------------------------------------- /manager/src/main/resources/mybatis/mappers/role.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | SELECT r.id as r_id, 16 | r.code as r_code, 17 | r.name as r_name 18 | FROM role r 19 | 20 | 21 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /manager/src/main/resources/mybatis/mybatis-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | -------------------------------------------------------------------------------- /manager/src/main/resources/start_linux.sh: -------------------------------------------------------------------------------- 1 | java -Dspring.profiles.active=prod -Dfrp.home=/usr/local/application/frp -jar penetrate-manager.jar& -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/home/frp/iconfont.css: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | @font-face {font-family: "iconfont"; 4 | src: url('/static/font/iconfont.eot'); !* IE9*! 5 | src: url('/static/font/iconfont.eot#iefix') format('embedded-opentype'), !* IE6-IE8 *! 6 | url('/static/font/iconfont.woff') format('woff'), !* chrome, firefox *! 7 | url('/static/font/iconfont.ttf') format('truetype'), !* chrome, firefox, opera, Safari, Android, iOS 4.2+*! 8 | url('/static/font/iconfont.svg#iconfont') format('svg'); !* iOS 4.1- *! 9 | } 10 | */ 11 | 12 | .iconfont { 13 | font-family:"iconfont" !important; 14 | font-size:16px; 15 | font-style:normal; 16 | -webkit-font-smoothing: antialiased; 17 | -webkit-text-stroke-width: 0.2px; 18 | -moz-osx-font-smoothing: grayscale; 19 | } 20 | .icon-sort:before { content: "\e66d"; } 21 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/login.css: -------------------------------------------------------------------------------- 1 | html{height: 100%;} 2 | body.signin { 3 | background: #18c8f6; 4 | height: auto; 5 | background:url("../img/login-background.jpg") no-repeat center fixed; 6 | -webkit-background-size: cover; 7 | -moz-background-size: cover; 8 | -o-background-size: cover; 9 | background-size: cover; 10 | color: rgba(255,255,255,.95); 11 | } 12 | 13 | .signinpanel { 14 | width: 320px; 15 | margin: 10% auto 0 auto; 16 | } 17 | 18 | .signinpanel .logopanel { 19 | float: none; 20 | width: auto; 21 | padding: 0; 22 | background: none; 23 | } 24 | 25 | .signinpanel .signin-info ul { 26 | list-style: none; 27 | padding: 0; 28 | margin: 20px 0; 29 | } 30 | 31 | .signinpanel .form-control { 32 | display: block; 33 | margin-top: 15px; 34 | } 35 | 36 | .signinpanel .uname { 37 | background: #fff url(../img/user.png) no-repeat 95% center;color:#333; 38 | } 39 | 40 | .signinpanel .pword { 41 | background: #fff url(../img/locked.png) no-repeat 95% center;color:#333; 42 | } 43 | 44 | .signinpanel .btn { 45 | margin-top: 15px; 46 | } 47 | 48 | .signinpanel form { 49 | background: rgba(255, 255, 255, 0.2); 50 | border: 1px solid rgba(255,255,255,.3); 51 | -moz-box-shadow: 0 3px 0 rgba(12, 12, 12, 0.03); 52 | -webkit-box-shadow: 0 3px 0 rgba(12, 12, 12, 0.03); 53 | box-shadow: 0 3px 0 rgba(12, 12, 12, 0.03); 54 | -moz-border-radius: 3px; 55 | -webkit-border-radius: 3px; 56 | border-radius: 3px; 57 | padding: 30px; 58 | } 59 | 60 | .signup-footer{border-top: solid 1px rgba(255,255,255,.3);margin:20px 0;padding-top: 15px;} 61 | 62 | @media screen and (max-width: 768px) { 63 | .signinpanel, 64 | .signuppanel { 65 | margin: 0 auto; 66 | width: 420px!important; 67 | padding: 20px; 68 | } 69 | .signinpanel form { 70 | margin-top: 20px; 71 | } 72 | .signup-footer { 73 | margin-bottom: 10px; 74 | } 75 | .signuppanel .form-control { 76 | margin-bottom: 10px; 77 | } 78 | .signup-footer .pull-left, 79 | .signup-footer .pull-right { 80 | float: none !important; 81 | text-align: center; 82 | } 83 | .signinpanel .signin-info ul { 84 | display: none; 85 | } 86 | } 87 | @media screen and (max-width: 320px) { 88 | .signinpanel, 89 | .signuppanel { 90 | margin:0 20px; 91 | width:auto; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/patterns/header-profile-skin-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/patterns/header-profile-skin-1.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/patterns/header-profile-skin-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/patterns/header-profile-skin-3.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/patterns/header-profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/patterns/header-profile.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/patterns/shattered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/patterns/shattered.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/blueimp/css/blueimp-gallery-indicator.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /* 3 | * blueimp Gallery Indicator CSS 1.1.0 4 | * https://github.com/blueimp/Gallery 5 | * 6 | * Copyright 2013, Sebastian Tschan 7 | * https://blueimp.net 8 | * 9 | * Licensed under the MIT license: 10 | * http://www.opensource.org/licenses/MIT 11 | */ 12 | 13 | .blueimp-gallery > .indicator { 14 | position: absolute; 15 | top: auto; 16 | right: 15px; 17 | bottom: 15px; 18 | left: 15px; 19 | margin: 0 40px; 20 | padding: 0; 21 | list-style: none; 22 | text-align: center; 23 | line-height: 10px; 24 | display: none; 25 | } 26 | .blueimp-gallery > .indicator > li { 27 | display: inline-block; 28 | width: 9px; 29 | height: 9px; 30 | margin: 6px 3px 0 3px; 31 | -webkit-box-sizing: content-box; 32 | -moz-box-sizing: content-box; 33 | box-sizing: content-box; 34 | border: 1px solid transparent; 35 | background: #ccc; 36 | background: rgba(255, 255, 255, 0.25) center no-repeat; 37 | border-radius: 5px; 38 | box-shadow: 0 0 2px #000; 39 | opacity: 0.5; 40 | cursor: pointer; 41 | } 42 | .blueimp-gallery > .indicator > li:hover, 43 | .blueimp-gallery > .indicator > .active { 44 | background-color: #fff; 45 | border-color: #fff; 46 | opacity: 1; 47 | } 48 | .blueimp-gallery-controls > .indicator { 49 | display: block; 50 | /* Fix z-index issues (controls behind slide element) on Android: */ 51 | -webkit-transform: translateZ(0); 52 | -moz-transform: translateZ(0); 53 | -ms-transform: translateZ(0); 54 | -o-transform: translateZ(0); 55 | transform: translateZ(0); 56 | } 57 | .blueimp-gallery-single > .indicator { 58 | display: none; 59 | } 60 | .blueimp-gallery > .indicator { 61 | -webkit-user-select: none; 62 | -khtml-user-select: none; 63 | -moz-user-select: none; 64 | -ms-user-select: none; 65 | user-select: none; 66 | } 67 | 68 | /* IE7 fixes */ 69 | *+html .blueimp-gallery > .indicator > li { 70 | display: inline; 71 | } 72 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/blueimp/css/blueimp-gallery-video.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /* 3 | * blueimp Gallery Video Factory CSS 1.3.0 4 | * https://github.com/blueimp/Gallery 5 | * 6 | * Copyright 2013, Sebastian Tschan 7 | * https://blueimp.net 8 | * 9 | * Licensed under the MIT license: 10 | * http://www.opensource.org/licenses/MIT 11 | */ 12 | 13 | .blueimp-gallery > .slides > .slide > .video-content > img { 14 | position: absolute; 15 | top: 0; 16 | right: 0; 17 | bottom: 0; 18 | left: 0; 19 | margin: auto; 20 | width: auto; 21 | height: auto; 22 | max-width: 100%; 23 | max-height: 100%; 24 | /* Prevent artifacts in Mozilla Firefox: */ 25 | -moz-backface-visibility: hidden; 26 | } 27 | .blueimp-gallery > .slides > .slide > .video-content > video { 28 | position: absolute; 29 | top: 0; 30 | left: 0; 31 | width: 100%; 32 | height: 100%; 33 | } 34 | .blueimp-gallery > .slides > .slide > .video-content > iframe { 35 | position: absolute; 36 | top: 100%; 37 | left: 0; 38 | width: 100%; 39 | height: 100%; 40 | border: none; 41 | } 42 | .blueimp-gallery > .slides > .slide > .video-playing > iframe { 43 | top: 0; 44 | } 45 | .blueimp-gallery > .slides > .slide > .video-content > a { 46 | position: absolute; 47 | top: 50%; 48 | right: 0; 49 | left: 0; 50 | margin: -64px auto 0; 51 | width: 128px; 52 | height: 128px; 53 | background: url(../img/video-play.png) center no-repeat; 54 | opacity: 0.8; 55 | cursor: pointer; 56 | } 57 | .blueimp-gallery > .slides > .slide > .video-content > a:hover { 58 | opacity: 1; 59 | } 60 | .blueimp-gallery > .slides > .slide > .video-playing > a, 61 | .blueimp-gallery > .slides > .slide > .video-playing > img { 62 | display: none; 63 | } 64 | .blueimp-gallery > .slides > .slide > .video-content > video { 65 | display: none; 66 | } 67 | .blueimp-gallery > .slides > .slide > .video-playing > video { 68 | display: block; 69 | } 70 | .blueimp-gallery > .slides > .slide > .video-loading > a { 71 | background: url(../img/loading.gif) center no-repeat; 72 | background-size: 64px 64px; 73 | } 74 | 75 | /* Replace PNGs with SVGs for capable browsers (excluding IE<9) */ 76 | body:last-child .blueimp-gallery > .slides > .slide > .video-content:not(.video-loading) > a { 77 | background-image: url(../img/video-play.svg); 78 | } 79 | 80 | /* IE7 fixes */ 81 | *+html .blueimp-gallery > .slides > .slide > .video-content { 82 | height: 100%; 83 | } 84 | *+html .blueimp-gallery > .slides > .slide > .video-content > a { 85 | left: 50%; 86 | margin-left: -64px; 87 | } 88 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/blueimp/css/demo.css: -------------------------------------------------------------------------------- 1 | /* 2 | * blueimp Gallery Demo CSS 2.0.0 3 | * https://github.com/blueimp/Gallery 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * http://www.opensource.org/licenses/MIT 10 | */ 11 | 12 | body { 13 | max-width: 750px; 14 | margin: 0 auto; 15 | padding: 1em; 16 | font-family: 'Lucida Grande', 'Lucida Sans Unicode', Arial, sans-serif; 17 | font-size: 1em; 18 | line-height: 1.4em; 19 | background: #222; 20 | color: #fff; 21 | -webkit-text-size-adjust: 100%; 22 | -ms-text-size-adjust: 100%; 23 | } 24 | a { 25 | color: orange; 26 | text-decoration: none; 27 | } 28 | img { 29 | border: 0; 30 | vertical-align: middle; 31 | } 32 | h1 { 33 | line-height: 1em; 34 | } 35 | h2, 36 | .links { 37 | text-align: center; 38 | } 39 | 40 | @media (min-width: 481px) { 41 | .navigation { 42 | list-style: none; 43 | padding: 0; 44 | } 45 | .navigation li { 46 | display: inline-block; 47 | } 48 | .navigation li:not(:first-child):before { 49 | content: '| '; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/blueimp/img/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/blueimp/img/error.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/blueimp/img/error.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/blueimp/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/blueimp/img/loading.gif -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/blueimp/img/play-pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/blueimp/img/play-pause.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/blueimp/img/play-pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/blueimp/img/video-play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/blueimp/img/video-play.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/blueimp/img/video-play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/chosen/chosen-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/chosen/chosen-sprite.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/chosen/chosen-sprite@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/chosen/chosen-sprite@2x.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/colorpicker/css/bootstrap-colorpicker.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Colorpicker 3 | * http://mjolnic.github.io/bootstrap-colorpicker/ 4 | * 5 | * Originally written by (c) 2012 Stefan Petre 6 | * Licensed under the Apache License v2.0 7 | * http://www.apache.org/licenses/LICENSE-2.0.txt 8 | * 9 | */.colorpicker-saturation{float:left;width:100px;height:100px;cursor:crosshair;background-image:url("../img/bootstrap-colorpicker/saturation.png")} .colorpicker-saturation i{position:absolute;top:0;left:0;display:block;width:5px;height:5px;margin:-4px 0 0 -4px;border:1px solid #000;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px} .colorpicker-saturation i b{display:block;width:5px;height:5px;border:1px solid #fff;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px} .colorpicker-hue,.colorpicker-alpha{float:left;width:15px;height:100px;margin-bottom:4px;margin-left:4px;cursor:row-resize} .colorpicker-hue i,.colorpicker-alpha i{position:absolute;top:0;left:0;display:block;width:100%;height:1px;margin-top:-1px;background:#000;border-top:1px solid #fff} .colorpicker-hue{background-image:url("../img/bootstrap-colorpicker/hue.png")} .colorpicker-alpha{display:none;background-image:url("../img/bootstrap-colorpicker/alpha.png")} .colorpicker{top:0;left:0;z-index:25000!important;min-width:130px;padding:4px;margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1} .colorpicker:before,.colorpicker:after{display:table;line-height:0;content:""} .colorpicker:after{clear:both} .colorpicker:before{position:absolute;top:-7px;left:6px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''} .colorpicker:after{position:absolute;top:-6px;left:7px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''} .colorpicker div{position:relative} .colorpicker.colorpicker-with-alpha{min-width:140px} .colorpicker.colorpicker-with-alpha .colorpicker-alpha{display:block} .colorpicker-color{height:10px;margin-top:5px;clear:both;background-image:url("../img/bootstrap-colorpicker/alpha.png");background-position:0 100%} .colorpicker-color div{height:10px} .colorpicker-element .input-group-addon i,.colorpicker-element .add-on i{display:inline-block;width:16px;height:16px;vertical-align:text-top;cursor:pointer} .colorpicker.colorpicker-inline{position:relative;z-index:auto;display:inline-block;float:none} .colorpicker.colorpicker-horizontal{width:110px;height:auto;min-width:110px} .colorpicker.colorpicker-horizontal .colorpicker-saturation{margin-bottom:4px} .colorpicker.colorpicker-horizontal .colorpicker-color{width:100px} .colorpicker.colorpicker-horizontal .colorpicker-hue,.colorpicker.colorpicker-horizontal .colorpicker-alpha{float:left;width:100px;height:15px;margin-bottom:4px;margin-left:0;cursor:col-resize} .colorpicker.colorpicker-horizontal .colorpicker-hue i,.colorpicker.colorpicker-horizontal .colorpicker-alpha i{position:absolute;top:0;left:0;display:block;width:1px;height:15px;margin-top:0;background:#fff;border:0} .colorpicker.colorpicker-horizontal .colorpicker-hue{background-image:url("../img/bootstrap-colorpicker/hue-horizontal.png")} .colorpicker.colorpicker-horizontal .colorpicker-alpha{background-image:url("../img/bootstrap-colorpicker/alpha-horizontal.png")} .colorpicker.colorpicker-hidden{display:none} .colorpicker.colorpicker-visible{display:block} .colorpicker-inline.colorpicker-visible{display:inline-block} 10 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/colorpicker/img/bootstrap-colorpicker/alpha-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/colorpicker/img/bootstrap-colorpicker/alpha-horizontal.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/colorpicker/img/bootstrap-colorpicker/alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/colorpicker/img/bootstrap-colorpicker/alpha.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/colorpicker/img/bootstrap-colorpicker/hue-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/colorpicker/img/bootstrap-colorpicker/hue-horizontal.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/colorpicker/img/bootstrap-colorpicker/hue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/colorpicker/img/bootstrap-colorpicker/hue.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/colorpicker/img/bootstrap-colorpicker/saturation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/colorpicker/img/bootstrap-colorpicker/saturation.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/cropper/cropper.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Cropper v0.7.6-beta 3 | * https://github.com/fengyuanchen/cropper 4 | * 5 | * Copyright 2014 Fengyuan Chen 6 | * Released under the MIT license 7 | */ 8 | 9 | .cropper-container{position:relative;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.cropper-container img{width:100%;height:100%;min-width:0!important;min-height:0!important;max-width:none!important;max-height:none!important}.cropper-modal,.cropper-canvas{position:absolute;top:0;right:0;bottom:0;left:0}.cropper-canvas{background-color:#fff;opacity:0;filter:alpha(opacity=0)}.cropper-modal{background-color:#000;opacity:.5;filter:alpha(opacity=50)}.cropper-dragger{position:absolute;top:10%;left:10%;width:80%;height:80%}.cropper-viewer{display:block;width:100%;height:100%;overflow:hidden;outline-width:1px;outline-style:solid;outline-color:#69f;outline-color:rgba(51,102,255,.75)}.cropper-dashed{position:absolute;display:block;border:0 dashed #fff;opacity:.5;filter:alpha(opacity=50)}.cropper-dashed.dashed-h{top:33.3%;left:0;width:100%;height:33.3%;border-top-width:1px;border-bottom-width:1px}.cropper-dashed.dashed-v{top:0;left:33.3%;width:33.3%;height:100%;border-right-width:1px;border-left-width:1px}.cropper-face,.cropper-line,.cropper-point{position:absolute;display:block;width:100%;height:100%;opacity:.1;filter:alpha(opacity=10)}.cropper-face{top:0;left:0;cursor:move;background-color:#fff}.cropper-line{background-color:#69f}.cropper-line.line-e{top:0;right:-3px;width:5px;cursor:e-resize}.cropper-line.line-n{top:-3px;left:0;height:5px;cursor:n-resize}.cropper-line.line-w{top:0;left:-3px;width:5px;cursor:w-resize}.cropper-line.line-s{bottom:-3px;left:0;height:5px;cursor:s-resize}.cropper-point{width:5px;height:5px;background-color:#69f;opacity:.75;filter:alpha(opacity=75)}.cropper-point.point-e{top:50%;right:-3px;margin-top:-3px;cursor:e-resize}.cropper-point.point-n{top:-3px;left:50%;margin-left:-3px;cursor:n-resize}.cropper-point.point-w{top:50%;left:-3px;margin-top:-3px;cursor:w-resize}.cropper-point.point-s{bottom:-3px;left:50%;margin-left:-3px;cursor:s-resize}.cropper-point.point-ne{top:-3px;right:-3px;cursor:ne-resize}.cropper-point.point-nw{top:-3px;left:-3px;cursor:nw-resize}.cropper-point.point-sw{bottom:-3px;left:-3px;cursor:sw-resize}.cropper-point.point-se{right:-3px;bottom:-3px;width:20px;height:20px;cursor:se-resize;opacity:1;filter:alpha(opacity=100)}.cropper-point.point-se:before{position:absolute;right:-50%;bottom:-50%;display:block;width:200%;height:200%;content:" ";background-color:#69f;opacity:0;filter:alpha(opacity=0)}@media (min-width:768px){.cropper-point.point-se{width:15px;height:15px}}@media (min-width:992px){.cropper-point.point-se{width:10px;height:10px}}@media (min-width:1200px){.cropper-point.point-se{width:5px;height:5px;opacity:.75;filter:alpha(opacity=75)}}.cropper-hidden{display:none!important}.cropper-invisible{position:fixed;top:0;left:0;z-index:-1;width:auto!important;max-width:none!important;height:auto!important;max-height:none!important;opacity:0;filter:alpha(opacity=0)}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-canvas,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed} 10 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/duallistbox/bootstrap-duallistbox.css: -------------------------------------------------------------------------------- 1 | .bootstrap-duallistbox-container .buttons { 2 | width:calc(100% + 1px); 3 | margin-bottom: -6px; 4 | box-sizing: border-box; 5 | } 6 | 7 | .bootstrap-duallistbox-container label { 8 | display: block; 9 | } 10 | 11 | .bootstrap-duallistbox-container .info { 12 | display: inline-block; 13 | margin-bottom: 5px; 14 | } 15 | 16 | .bootstrap-duallistbox-container .clear1, 17 | .bootstrap-duallistbox-container .clear2 { 18 | display: none; 19 | font-size: 10px; 20 | } 21 | 22 | .bootstrap-duallistbox-container .box1.filtered .clear1, 23 | .bootstrap-duallistbox-container .box2.filtered .clear2 { 24 | display: inline-block; 25 | } 26 | 27 | .bootstrap-duallistbox-container .move, 28 | .bootstrap-duallistbox-container .remove { 29 | width: 50%;box-sizing: border-box; 30 | } 31 | 32 | .bootstrap-duallistbox-container .btn-group .btn { 33 | border-bottom-left-radius: 0; 34 | border-bottom-right-radius: 0; 35 | } 36 | .bootstrap-duallistbox-container select { 37 | border-top-left-radius: 0; 38 | border-top-right-radius: 0; 39 | } 40 | 41 | .bootstrap-duallistbox-container .moveall, 42 | .bootstrap-duallistbox-container .removeall { 43 | width: 50%;box-sizing: border-box; 44 | } 45 | 46 | .bootstrap-duallistbox-container.bs2compatible .btn-group > .btn + .btn { 47 | margin-left: 0; 48 | } 49 | 50 | .bootstrap-duallistbox-container select { 51 | height: 300px; 52 | box-sizing: border-box; 53 | } 54 | .bootstrap-duallistbox-container select:focus{ 55 | border-color: #e5e6e7!important; 56 | } 57 | 58 | .bootstrap-duallistbox-container .filter { 59 | display: inline-block; 60 | width: 100%; 61 | height: 31px;margin-bottom:-1px; 62 | -webkit-box-sizing: border-box; 63 | -moz-box-sizing: border-box; 64 | } 65 | 66 | .bootstrap-duallistbox-container .filter.placeholder { 67 | color: #aaa; 68 | } 69 | 70 | .bootstrap-duallistbox-container.moveonselect .move, 71 | .bootstrap-duallistbox-container.moveonselect .remove { 72 | display:none; 73 | } 74 | 75 | .bootstrap-duallistbox-container.moveonselect .moveall, 76 | .bootstrap-duallistbox-container.moveonselect .removeall { 77 | width: 100%; 78 | } 79 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/footable/fonts/footable.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/footable/fonts/footable.eot -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/footable/fonts/footable.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/footable/fonts/footable.ttf -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/footable/fonts/footable.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/footable/fonts/footable.woff -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/fullcalendar/fullcalendar.print.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * FullCalendar v1.6.4 Print Stylesheet 3 | * Docs & License: http://arshaw.com/fullcalendar/ 4 | * (c) 2013 Adam Shaw 5 | */ 6 | 7 | /* 8 | * Include this stylesheet on your page to get a more printer-friendly calendar. 9 | * When including this stylesheet, use the media='print' attribute of the tag. 10 | * Make sure to include this stylesheet IN ADDITION to the regular fullcalendar.css. 11 | */ 12 | 13 | 14 | /* Events 15 | -----------------------------------------------------*/ 16 | 17 | .fc-event { 18 | background: #fff !important; 19 | color: #000 !important; 20 | } 21 | 22 | /* for vertical events */ 23 | 24 | .fc-event-bg { 25 | display: none !important; 26 | } 27 | 28 | .fc-event .ui-resizable-handle { 29 | display: none !important; 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/iCheck/custom.css: -------------------------------------------------------------------------------- 1 | /* iCheck plugin Square skin, green 2 | ----------------------------------- */ 3 | .icheckbox_square-green, 4 | .iradio_square-green { 5 | display: inline-block; 6 | *display: inline; 7 | vertical-align: middle; 8 | margin: 0; 9 | padding: 0; 10 | width: 22px; 11 | height: 22px; 12 | background: url(green.png) no-repeat; 13 | border: none; 14 | cursor: pointer; 15 | } 16 | 17 | .icheckbox_square-green { 18 | background-position: 0 0; 19 | } 20 | .icheckbox_square-green.hover { 21 | background-position: -24px 0; 22 | } 23 | .icheckbox_square-green.checked { 24 | background-position: -48px 0; 25 | } 26 | .icheckbox_square-green.disabled { 27 | background-position: -72px 0; 28 | cursor: default; 29 | } 30 | .icheckbox_square-green.checked.disabled { 31 | background-position: -96px 0; 32 | } 33 | 34 | .iradio_square-green { 35 | background-position: -120px 0; 36 | } 37 | .iradio_square-green.hover { 38 | background-position: -144px 0; 39 | } 40 | .iradio_square-green.checked { 41 | background-position: -168px 0; 42 | } 43 | .iradio_square-green.disabled { 44 | background-position: -192px 0; 45 | cursor: default; 46 | } 47 | .iradio_square-green.checked.disabled { 48 | background-position: -216px 0; 49 | } 50 | 51 | /* HiDPI support */ 52 | @media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) { 53 | .icheckbox_square-green, 54 | .iradio_square-green { 55 | background-image: url(green@2x.png); 56 | -webkit-background-size: 240px 24px; 57 | background-size: 240px 24px; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/iCheck/green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/iCheck/green.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/iCheck/green@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/iCheck/green@2x.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/images/sort_asc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/images/sort_asc.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/images/sort_desc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/images/sort_desc.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/images/sprite-skin-flat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/images/sprite-skin-flat.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/images/spritemap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/images/spritemap.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/images/spritemap@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/images/spritemap@2x.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/ionRangeSlider/ion.rangeSlider.skinFlat.css: -------------------------------------------------------------------------------- 1 | /* Ion.RangeSlider, Flat UI Skin 2 | // css version 1.8.5 3 | // by Denis Ineshin | ionden.com 4 | // ===================================================================================================================*/ 5 | 6 | /* ===================================================================================================================== 7 | // Skin details */ 8 | 9 | .irs-line-mid, 10 | .irs-line-left, 11 | .irs-line-right, 12 | .irs-diapason, 13 | .irs-slider { 14 | background: url(../images/sprite-skin-flat.png) repeat-x; 15 | } 16 | 17 | .irs { 18 | height: 40px; 19 | } 20 | .irs-with-grid { 21 | height: 60px; 22 | } 23 | .irs-line { 24 | height: 12px; top: 25px; 25 | } 26 | .irs-line-left { 27 | height: 12px; 28 | background-position: 0 -30px; 29 | } 30 | .irs-line-mid { 31 | height: 12px; 32 | background-position: 0 0; 33 | } 34 | .irs-line-right { 35 | height: 12px; 36 | background-position: 100% -30px; 37 | } 38 | 39 | .irs-diapason { 40 | height: 12px; top: 25px; 41 | background-position: 0 -60px; 42 | } 43 | 44 | .irs-slider { 45 | width: 16px; height: 18px; 46 | top: 22px; 47 | background-position: 0 -90px; 48 | } 49 | #irs-active-slider, .irs-slider:hover { 50 | background-position: 0 -120px; 51 | } 52 | 53 | .irs-min, .irs-max { 54 | color: #999; 55 | font-size: 10px; line-height: 1.333; 56 | text-shadow: none; 57 | top: 0; padding: 1px 3px; 58 | background: #e1e4e9; 59 | border-radius: 4px; 60 | } 61 | 62 | .irs-from, .irs-to, .irs-single { 63 | color: #fff; 64 | font-size: 10px; line-height: 1.333; 65 | text-shadow: none; 66 | padding: 1px 5px; 67 | background: #ed5565; 68 | border-radius: 4px; 69 | } 70 | .irs-from:after, .irs-to:after, .irs-single:after { 71 | position: absolute; display: block; content: ""; 72 | bottom: -6px; left: 50%; 73 | width: 0; height: 0; 74 | margin-left: -3px; 75 | overflow: hidden; 76 | border: 3px solid transparent; 77 | border-top-color: #ed5565; 78 | } 79 | 80 | 81 | .irs-grid-pol { 82 | background: #e1e4e9; 83 | } 84 | .irs-grid-text { 85 | color: #999; 86 | } 87 | 88 | .irs-disabled { 89 | } 90 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/jQueryUI/images/ui-bg_flat_0_aaaaaa_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/jQueryUI/images/ui-bg_flat_0_aaaaaa_40x100.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/jQueryUI/images/ui-bg_flat_75_ffffff_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/jQueryUI/images/ui-bg_flat_75_ffffff_40x100.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/jQueryUI/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/jQueryUI/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/jQueryUI/images/ui-icons_454545_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/jQueryUI/images/ui-icons_454545_256x240.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/jQueryUI/images/ui-icons_888888_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/jQueryUI/images/ui-icons_888888_256x240.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/jsTree/32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/jsTree/32px.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/jsTree/throbber.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/css/plugins/jsTree/throbber.gif -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/markdown/bootstrap-markdown.min.css: -------------------------------------------------------------------------------- 1 | .md-editor{display:block;border:1px solid #ddd}.md-editor .md-footer,.md-editor>.md-header{display:block;padding:6px 4px;background:#f5f5f5}.md-editor>.md-header{margin:0}.md-editor>.md-preview{background:#fff;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;min-height:10px;overflow:auto}.md-editor>textarea{font-family:Menlo, Monaco, Consolas, "Courier New", monospace;font-size:14px;outline:0;margin:0;display:block;padding:15px;width:100%;border:0;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;border-radius:0;box-shadow:none;background:#fafafa}.md-editor>textarea:focus{box-shadow:none;background:#fff}.md-editor.active{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);box-shadow:inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6)}.md-editor .md-controls{float:right;padding:3px}.md-editor .md-controls .md-control{right:5px;color:#bebebe;padding:3px 3px 3px 10px}.md-editor .md-controls .md-control:hover{color:#333}.md-editor.md-fullscreen-mode{width:100%;height:100%;position:fixed;top:0;left:0;z-index:99999;padding:60px 30px 15px;background:#fff!important;border:0!important}.md-editor.md-fullscreen-mode .md-footer{display:none}.md-editor.md-fullscreen-mode .md-input,.md-editor.md-fullscreen-mode .md-preview{margin:0 auto!important;height:100%!important;font-size:20px!important;padding:20px!important;color:#999;line-height:1.6em!important;resize:none!important;box-shadow:none!important;background:#fff!important;border:0!important}.md-editor.md-fullscreen-mode .md-preview{color:#333;overflow:auto}.md-editor.md-fullscreen-mode .md-input:focus,.md-editor.md-fullscreen-mode .md-input:hover{color:#333;background:#fff!important}.md-editor.md-fullscreen-mode .md-header{background:0 0;text-align:center;position:fixed;width:100%;top:20px}.md-editor.md-fullscreen-mode .btn-group{float:none}.md-editor.md-fullscreen-mode .btn{border:0;background:0 0;color:#b3b3b3}.md-editor.md-fullscreen-mode .btn.active,.md-editor.md-fullscreen-mode .btn:active,.md-editor.md-fullscreen-mode .btn:focus,.md-editor.md-fullscreen-mode .btn:hover{box-shadow:none;color:#333}.md-editor.md-fullscreen-mode .md-fullscreen-controls{position:absolute;top:20px;right:20px;text-align:right;z-index:1002;display:block}.md-editor.md-fullscreen-mode .md-fullscreen-controls a{color:#b3b3b3;clear:right;margin:10px;width:30px;height:30px;text-align:center}.md-editor.md-fullscreen-mode .md-fullscreen-controls a:hover{color:#333;text-decoration:none}.md-editor.md-fullscreen-mode .md-editor{height:100%!important;position:relative}.md-editor .md-fullscreen-controls{display:none}.md-nooverflow{overflow:hidden;position:fixed;width:100%} 2 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/morris/morris-0.4.3.min.css: -------------------------------------------------------------------------------- 1 | .morris-hover{position:absolute;z-index:1000;}.morris-hover.morris-default-style{border-radius:10px;padding:6px;color:#666;background:rgba(255, 255, 255, 0.8);border:solid 2px rgba(230, 230, 230, 0.8);font-family:sans-serif;font-size:12px;text-align:center;}.morris-hover.morris-default-style .morris-hover-row-label{font-weight:bold;margin:0.25em 0;} 2 | .morris-hover.morris-default-style .morris-hover-point{white-space:nowrap;margin:0.1em 0;} 3 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/multiselect/bootstrap-multiselect.css: -------------------------------------------------------------------------------- 1 | .multiselect-container{position:absolute;list-style-type:none;margin:0;padding:0}.multiselect-container .input-group{margin:5px}.multiselect-container>li{padding:0}.multiselect-container>li>a.multiselect-all label{font-weight:700}.multiselect-container>li.multiselect-group label{margin:0;padding:3px 20px 3px 20px;height:100%;font-weight:700}.multiselect-container>li.multiselect-group-clickable label{cursor:pointer}.multiselect-container>li>a{padding:0}.multiselect-container>li>a>label{margin:0;height:100%;cursor:pointer;font-weight:400;padding:3px 20px 3px 40px}.multiselect-container>li>a>label.radio,.multiselect-container>li>a>label.checkbox{margin:0}.multiselect-container>li>a>label>input[type=checkbox]{margin-bottom:5px}.btn-group>.btn-group:nth-child(2)>.multiselect.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.form-inline .multiselect-container label.checkbox,.form-inline .multiselect-container label.radio{padding:3px 20px 3px 40px}.form-inline .multiselect-container li a label.checkbox input[type=checkbox],.form-inline .multiselect-container li a label.radio input[type=radio]{margin-left:-20px;margin-right:0} 2 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/switchery/switchery.css: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Main stylesheet for Switchery. 4 | * http://abpetkov.github.io/switchery/ 5 | * 6 | */ 7 | 8 | .switchery { 9 | background-color: #fff; 10 | border: 1px solid #dfdfdf; 11 | border-radius: 20px; 12 | cursor: pointer; 13 | display: inline-block; 14 | height: 30px; 15 | position: relative; 16 | vertical-align: middle; 17 | width: 50px; 18 | 19 | -webkit-box-sizing: content-box; 20 | -moz-box-sizing: content-box; 21 | box-sizing: content-box; 22 | } 23 | 24 | .switchery > small { 25 | background: #fff; 26 | border-radius: 100%; 27 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); 28 | height: 30px; 29 | position: absolute; 30 | top: 0; 31 | width: 30px; 32 | } 33 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/treeview/bootstrap-treeview.css: -------------------------------------------------------------------------------- 1 | /* ========================================================= 2 | * bootstrap-treeview.css v1.0.0 3 | * ========================================================= 4 | * Copyright 2013 Jonathan Miles 5 | * Project URL : http://www.jondmiles.com/bootstrap-treeview 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================= */ 19 | 20 | .list-group-item { 21 | cursor: pointer; 22 | } 23 | 24 | /*.list-group-item:hover { 25 | background-color: #f5f5f5; 26 | }*/ 27 | 28 | span.indent { 29 | margin-left: 10px; 30 | margin-right: 10px; 31 | } 32 | 33 | span.icon { 34 | margin-right: 5px; 35 | } 36 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/css/plugins/webuploader/webuploader.css: -------------------------------------------------------------------------------- 1 | .webuploader-container { 2 | position: relative; 3 | } 4 | .webuploader-element-invisible { 5 | position: absolute !important; 6 | clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ 7 | clip: rect(1px,1px,1px,1px); 8 | } 9 | .webuploader-pick { 10 | position: relative; 11 | display: inline-block; 12 | cursor: pointer; 13 | background: #00b7ee; 14 | padding: 10px 15px; 15 | color: #fff; 16 | text-align: center; 17 | border-radius: 3px; 18 | overflow: hidden; 19 | } 20 | .webuploader-pick-hover { 21 | background: #00a2d4; 22 | } 23 | 24 | .webuploader-pick-disable { 25 | opacity: 0.6; 26 | pointer-events:none; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /manager/src/main/resources/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /manager/src/main/resources/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /manager/src/main/resources/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /manager/src/main/resources/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /manager/src/main/resources/static/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /manager/src/main/resources/static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /manager/src/main/resources/static/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /manager/src/main/resources/static/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/0.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/1.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/a1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/a1.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/a2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/a2.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/a3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/a3.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/a4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/a4.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/a5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/a5.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/a6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/a6.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/a7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/a7.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/a8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/a8.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/a9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/a9.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/alipay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/alipay.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/banner.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/bg.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/browser.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/favicon.ico -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/home.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/iconfont-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/iconfont-logo.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/icons.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/linux.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/loading-upload.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/loading-upload.gif -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/locked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/locked.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/login-background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/login-background.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/mac.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/manager.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/p1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/p1.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/p2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/p2.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/p3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/p3.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/profile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/profile.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/profile_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/profile_small.jpg -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/progress.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/qq.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/qq1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/qq1.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/qq2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/qq2.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/sprite-skin-flat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/sprite-skin-flat.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/success.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/user.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/webuploader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/webuploader.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/wenku_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/wenku_logo.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/windows.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/images/wxpay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/images/wxpay.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/content.js: -------------------------------------------------------------------------------- 1 | // var $parentNode = window.parent.document; 2 | 3 | // function $childNode(name) { 4 | // return window.frames[name] 5 | // } 6 | 7 | // // tooltips 8 | // $('.tooltip-demo').tooltip({ 9 | // selector: "[data-toggle=tooltip]", 10 | // container: "body" 11 | // }); 12 | 13 | // // 使用animation.css修改Bootstrap Modal 14 | // $('.modal').appendTo("body"); 15 | 16 | // $("[data-toggle=popover]").popover(); 17 | 18 | 19 | //判断当前页面是否在iframe中 20 | if (top == this) { 21 | var gohome = '
'; 22 | $('body').append(gohome); 23 | } 24 | 25 | //animation.css 26 | function animationHover(element, animation) { 27 | element = $(element); 28 | element.hover( 29 | function () { 30 | element.addClass('animated ' + animation); 31 | }, 32 | function () { 33 | //动画完成之前移除class 34 | window.setTimeout(function () { 35 | element.removeClass('animated ' + animation); 36 | }, 2000); 37 | }); 38 | } 39 | 40 | //拖动面板 41 | function WinMove() { 42 | var element = "[class*=col]"; 43 | var handle = ".ibox-title"; 44 | var connect = "[class*=col]"; 45 | $(element).sortable({ 46 | handle: handle, 47 | connectWith: connect, 48 | tolerance: 'pointer', 49 | forcePlaceholderSize: true, 50 | opacity: 0.8, 51 | }) 52 | .disableSelection(); 53 | }; 54 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/hAdmin.js: -------------------------------------------------------------------------------- 1 | 2 | //自定义js 3 | 4 | //公共配置 5 | 6 | 7 | $(document).ready(function () { 8 | 9 | // MetsiMenu 10 | $('#side-menu').metisMenu(); 11 | 12 | // 打开右侧边栏 13 | $('.right-sidebar-toggle').click(function () { 14 | $('#right-sidebar').toggleClass('sidebar-open'); 15 | }); 16 | 17 | //固定菜单栏 18 | $(function () { 19 | $('.sidebar-collapse').slimScroll({ 20 | height: '100%', 21 | railOpacity: 0.9, 22 | alwaysVisible: false 23 | }); 24 | }); 25 | 26 | 27 | // 菜单切换 28 | $('.navbar-minimalize').click(function () { 29 | $("body").toggleClass("mini-navbar"); 30 | SmoothlyMenu(); 31 | }); 32 | 33 | 34 | // 侧边栏高度 35 | function fix_height() { 36 | var heightWithoutNavbar = $("body > #wrapper").height() - 61; 37 | $(".sidebard-panel").css("min-height", heightWithoutNavbar + "px"); 38 | } 39 | fix_height(); 40 | 41 | $(window).bind("load resize click scroll", function () { 42 | if (!$("body").hasClass('body-small')) { 43 | fix_height(); 44 | } 45 | }); 46 | 47 | //侧边栏滚动 48 | $(window).scroll(function () { 49 | if ($(window).scrollTop() > 0 && !$('body').hasClass('fixed-nav')) { 50 | $('#right-sidebar').addClass('sidebar-top'); 51 | } else { 52 | $('#right-sidebar').removeClass('sidebar-top'); 53 | } 54 | }); 55 | 56 | $('.full-height-scroll').slimScroll({ 57 | height: '100%' 58 | }); 59 | 60 | $('#side-menu>li').click(function () { 61 | if ($('body').hasClass('mini-navbar')) { 62 | NavToggle(); 63 | } 64 | }); 65 | $('#side-menu>li li a').click(function () { 66 | if ($(window).width() < 769) { 67 | NavToggle(); 68 | } 69 | }); 70 | 71 | $('.nav-close').click(NavToggle); 72 | 73 | //ios浏览器兼容性处理 74 | if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) { 75 | $('#content-main').css('overflow-y', 'auto'); 76 | } 77 | 78 | }); 79 | 80 | $(window).bind("load resize", function () { 81 | if ($(this).width() < 769) { 82 | $('body').addClass('mini-navbar'); 83 | $('.navbar-static-side').fadeIn(); 84 | } 85 | }); 86 | 87 | function NavToggle() { 88 | $('.navbar-minimalize').trigger('click'); 89 | } 90 | 91 | function SmoothlyMenu() { 92 | if (!$('body').hasClass('mini-navbar')) { 93 | $('#side-menu').hide(); 94 | setTimeout( 95 | function () { 96 | $('#side-menu').fadeIn(500); 97 | }, 100); 98 | } else if ($('body').hasClass('fixed-sidebar')) { 99 | $('#side-menu').hide(); 100 | setTimeout( 101 | function () { 102 | $('#side-menu').fadeIn(500); 103 | }, 300); 104 | } else { 105 | $('#side-menu').removeAttr('style'); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/index.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | //菜单点击 3 | J_iframe 4 | $(".J_menuItem").on('click',function(){ 5 | var url = $(this).attr('href'); 6 | $("#J_iframe").attr('src',url); 7 | return false; 8 | }); 9 | }); -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | Projection by TEMPLATED 3 | templated.co @templatedco 4 | Released for free under the Creative Commons Attribution 3.0 license (templated.co/license) 5 | */ 6 | 7 | (function($) { 8 | 9 | // Breakpoints. 10 | skel.breakpoints({ 11 | xlarge: '(max-width: 1680px)', 12 | large: '(max-width: 1280px)', 13 | medium: '(max-width: 980px)', 14 | small: '(max-width: 736px)', 15 | xsmall: '(max-width: 480px)' 16 | }); 17 | 18 | $(function() { 19 | 20 | var $window = $(window), 21 | $body = $('body'); 22 | 23 | // Disable animations/transitions until the page has loaded. 24 | $body.addClass('is-loading'); 25 | 26 | $window.on('load', function() { 27 | window.setTimeout(function() { 28 | $body.removeClass('is-loading'); 29 | }, 100); 30 | }); 31 | 32 | // Prioritize "important" elements on medium. 33 | skel.on('+medium -medium', function() { 34 | $.prioritize( 35 | '.important\\28 medium\\29', 36 | skel.breakpoint('medium').active 37 | ); 38 | }); 39 | 40 | // Off-Canvas Navigation. 41 | 42 | // Navigation Panel. 43 | $( 44 | '' 48 | ) 49 | .appendTo($body) 50 | .panel({ 51 | delay: 500, 52 | hideOnClick: true, 53 | hideOnSwipe: true, 54 | resetScroll: true, 55 | resetForms: true, 56 | side: 'left' 57 | }); 58 | 59 | // Fix: Remove transitions on WP<10 (poor/buggy performance). 60 | if (skel.vars.os == 'wp' && skel.vars.osVersion < 10) 61 | $('#navPanel') 62 | .css('transition', 'none'); 63 | 64 | }); 65 | 66 | })(jQuery); 67 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/bootstrap-table/bootstrap-table-mobile.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * bootstrap-table - v1.9.0 - 2015-09-30 3 | * https://github.com/wenzhixin/bootstrap-table 4 | * Copyright (c) 2015 zhixin wen 5 | * Licensed MIT License 6 | */ 7 | !function(a){"use strict";var b=function(b,c){b.options.columnsHidden.length>0&&a.each(b.columns,function(d,e){-1!==b.options.columnsHidden.indexOf(e.field)&&e.visible!==c&&b.toggleColumn(a.fn.bootstrapTable.utils.getFieldIndex(b.columns,e.field),c,!0)})},c=function(a){(a.options.height||a.options.showFooter)&&setTimeout(a.resetView,1)},d=function(a,b,d){a.options.minHeight?b<=a.options.minWidth&&d<=a.options.minHeight?e(a):b>a.options.minWidth&&d>a.options.minHeight&&f(a):b<=a.options.minWidth?e(a):b>a.options.minWidth&&f(a),c(a)},e=function(a){g(a,!1),b(a,!1)},f=function(a){g(a,!0),b(a,!0)},g=function(a,b){a.options.cardView=b,a.toggleView()},h=function(a,b){var c;return function(){var d=this,e=arguments,f=function(){c=null,a.apply(d,e)};clearTimeout(c),c=setTimeout(f,b)}};a.extend(a.fn.bootstrapTable.defaults,{mobileResponsive:!1,minWidth:562,minHeight:void 0,heightThreshold:100,checkOnInit:!0,columnsHidden:[]});var i=a.fn.bootstrapTable.Constructor,j=i.prototype.init;i.prototype.init=function(){if(j.apply(this,Array.prototype.slice.apply(arguments)),this.options.mobileResponsive&&this.options.minWidth){var b=this,c={width:a(window).width(),height:a(window).height()};if(a(window).on("resize orientationchange",h(function(){var e=a(this).height(),f=a(this).width();(Math.abs(c.height-e)>b.options.heightThreshold||c.width!=f)&&(d(b,f,e),c={width:f,height:e})},200)),this.options.checkOnInit){var e=a(window).height(),f=a(window).width();d(this,f,e),c={width:f,height:e}}}}}(jQuery); 8 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Bootstrap Table Chinese translation 3 | * Author: Zhixin Wen 4 | */ 5 | (function ($) { 6 | 'use strict'; 7 | 8 | $.fn.bootstrapTable.locales['zh-CN'] = { 9 | formatLoadingMessage: function () { 10 | return '正在努力地加载数据中,请稍候……'; 11 | }, 12 | formatRecordsPerPage: function (pageNumber) { 13 | return '每页显示 ' + pageNumber + ' 条记录'; 14 | }, 15 | formatShowingRows: function (pageFrom, pageTo, totalRows) { 16 | return '显示第 ' + pageFrom + ' 到第 ' + pageTo + ' 条记录,总共 ' + totalRows + ' 条记录'; 17 | }, 18 | formatSearch: function () { 19 | return '搜索'; 20 | }, 21 | formatNoMatches: function () { 22 | return '没有找到匹配的记录'; 23 | }, 24 | formatPaginationSwitch: function () { 25 | return '隐藏/显示分页'; 26 | }, 27 | formatRefresh: function () { 28 | return '刷新'; 29 | }, 30 | formatToggle: function () { 31 | return '切换'; 32 | }, 33 | formatColumns: function () { 34 | return '列'; 35 | } 36 | }; 37 | 38 | $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales['zh-CN']); 39 | 40 | })(jQuery); 41 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * bootstrap-table - v1.9.0 - 2015-09-30 3 | * https://github.com/wenzhixin/bootstrap-table 4 | * Copyright (c) 2015 zhixin wen 5 | * Licensed MIT License 6 | */ 7 | !function(a){"use strict";a.fn.bootstrapTable.locales["zh-CN"]={formatLoadingMessage:function(){return"正在努力地加载数据中,请稍候……"},formatRecordsPerPage:function(a){return"每页显示 "+a+" 条记录"},formatShowingRows:function(a,b,c){return"显示第 "+a+" 到第 "+b+" 条记录,总共 "+c+" 条记录"},formatSearch:function(){return"搜索"},formatNoMatches:function(){return"没有找到匹配的记录"},formatPaginationSwitch:function(){return"隐藏/显示分页"},formatRefresh:function(){return"刷新"},formatToggle:function(){return"切换"},formatColumns:function(){return"列"}},a.extend(a.fn.bootstrapTable.defaults,a.fn.bootstrapTable.locales["zh-CN"])}(jQuery); 8 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/flot/jquery.flot.resize.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin for automatically redrawing plots as the placeholder resizes. 2 | 3 | Copyright (c) 2007-2013 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | It works by listening for changes on the placeholder div (through the jQuery 7 | resize event plugin) - if the size changes, it will redraw the plot. 8 | 9 | There are no options. If you need to disable the plugin for some plots, you 10 | can just fix the size of their placeholders. 11 | 12 | */ 13 | 14 | /* Inline dependency: 15 | * jQuery resize event - v1.1 - 3/14/2010 16 | * http://benalman.com/projects/jquery-resize-plugin/ 17 | * 18 | * Copyright (c) 2010 "Cowboy" Ben Alman 19 | * Dual licensed under the MIT and GPL licenses. 20 | * http://benalman.com/about/license/ 21 | */ 22 | 23 | (function($,h,c){var a=$([]),e=$.resize=$.extend($.resize,{}),i,k="setTimeout",j="resize",d=j+"-special-event",b="delay",f="throttleWindow";e[b]=250;e[f]=true;$.event.special[j]={setup:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.add(l);$.data(this,d,{w:l.width(),h:l.height()});if(a.length===1){g()}},teardown:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.not(l);l.removeData(d);if(!a.length){clearTimeout(i)}},add:function(l){if(!e[f]&&this[k]){return false}var n;function m(s,o,p){var q=$(this),r=$.data(this,d);r.w=o!==c?o:q.width();r.h=p!==c?p:q.height();n.apply(this,arguments)}if($.isFunction(l)){n=l;return m}else{n=l.handler;l.handler=m}}};function g(){i=h[k](function(){a.each(function(){var n=$(this),m=n.width(),l=n.height(),o=$.data(this,d);if(m!==o.w||l!==o.h){n.trigger(j,[o.w=m,o.h=l])}});g()},e[b])}})(jQuery,this); 24 | 25 | (function ($) { 26 | var options = { }; // no options 27 | 28 | function init(plot) { 29 | function onResize() { 30 | var placeholder = plot.getPlaceholder(); 31 | 32 | // somebody might have hidden us and we can't plot 33 | // when we don't have the dimensions 34 | if (placeholder.width() == 0 || placeholder.height() == 0) 35 | return; 36 | 37 | plot.resize(); 38 | plot.setupGrid(); 39 | plot.draw(); 40 | } 41 | 42 | function bindEvents(plot, eventHolder) { 43 | plot.getPlaceholder().resize(onResize); 44 | } 45 | 46 | function shutdown(plot, eventHolder) { 47 | plot.getPlaceholder().unbind("resize", onResize); 48 | } 49 | 50 | plot.hooks.bindEvents.push(bindEvents); 51 | plot.hooks.shutdown.push(shutdown); 52 | } 53 | 54 | $.plot.plugins.push({ 55 | init: init, 56 | options: options, 57 | name: 'resize', 58 | version: '1.0' 59 | }); 60 | })(jQuery); 61 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/flot/jquery.flot.symbol.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin that adds some extra symbols for plotting points. 2 | 3 | Copyright (c) 2007-2014 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | The symbols are accessed as strings through the standard symbol options: 7 | 8 | series: { 9 | points: { 10 | symbol: "square" // or "diamond", "triangle", "cross" 11 | } 12 | } 13 | 14 | */ 15 | 16 | (function ($) { 17 | function processRawData(plot, series, datapoints) { 18 | // we normalize the area of each symbol so it is approximately the 19 | // same as a circle of the given radius 20 | 21 | var handlers = { 22 | square: function (ctx, x, y, radius, shadow) { 23 | // pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2 24 | var size = radius * Math.sqrt(Math.PI) / 2; 25 | ctx.rect(x - size, y - size, size + size, size + size); 26 | }, 27 | diamond: function (ctx, x, y, radius, shadow) { 28 | // pi * r^2 = 2s^2 => s = r * sqrt(pi/2) 29 | var size = radius * Math.sqrt(Math.PI / 2); 30 | ctx.moveTo(x - size, y); 31 | ctx.lineTo(x, y - size); 32 | ctx.lineTo(x + size, y); 33 | ctx.lineTo(x, y + size); 34 | ctx.lineTo(x - size, y); 35 | }, 36 | triangle: function (ctx, x, y, radius, shadow) { 37 | // pi * r^2 = 1/2 * s^2 * sin (pi / 3) => s = r * sqrt(2 * pi / sin(pi / 3)) 38 | var size = radius * Math.sqrt(2 * Math.PI / Math.sin(Math.PI / 3)); 39 | var height = size * Math.sin(Math.PI / 3); 40 | ctx.moveTo(x - size/2, y + height/2); 41 | ctx.lineTo(x + size/2, y + height/2); 42 | if (!shadow) { 43 | ctx.lineTo(x, y - height/2); 44 | ctx.lineTo(x - size/2, y + height/2); 45 | } 46 | }, 47 | cross: function (ctx, x, y, radius, shadow) { 48 | // pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2 49 | var size = radius * Math.sqrt(Math.PI) / 2; 50 | ctx.moveTo(x - size, y - size); 51 | ctx.lineTo(x + size, y + size); 52 | ctx.moveTo(x - size, y + size); 53 | ctx.lineTo(x + size, y - size); 54 | } 55 | }; 56 | 57 | var s = series.points.symbol; 58 | if (handlers[s]) 59 | series.points.symbol = handlers[s]; 60 | } 61 | 62 | function init(plot) { 63 | plot.hooks.processDatapoints.push(processRawData); 64 | } 65 | 66 | $.plot.plugins.push({ 67 | init: init, 68 | name: 'symbols', 69 | version: '1.0' 70 | }); 71 | })(jQuery); 72 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/gritter/images/gritter-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/gritter/images/gritter-light.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/gritter/images/gritter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/gritter/images/gritter.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/gritter/images/ie-spacer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/gritter/images/ie-spacer.gif -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/gritter/jquery.gritter.css: -------------------------------------------------------------------------------- 1 | /* the norm */ 2 | #gritter-notice-wrapper { 3 | position:fixed; 4 | top:40px; 5 | right:20px; 6 | width:301px; 7 | z-index:9999; 8 | 9 | -webkit-animation-duration: 1s; 10 | animation-duration: 1s; 11 | -webkit-animation-fill-mode: both; 12 | animation-fill-mode: both; 13 | 14 | -webkit-animation-name: bounceIn; 15 | animation-name: bounceIn; 16 | } 17 | @keyframes bounceIn { 18 | 0% { 19 | opacity: 0; 20 | -webkit-transform: scale(.3); 21 | -ms-transform: scale(.3); 22 | transform: scale(.3); 23 | } 24 | 25 | 50% { 26 | opacity: 1; 27 | -webkit-transform: scale(1.05); 28 | -ms-transform: scale(1.05); 29 | transform: scale(1.05); 30 | } 31 | 32 | 70% { 33 | -webkit-transform: scale(.9); 34 | -ms-transform: scale(.9); 35 | transform: scale(.9); 36 | } 37 | 38 | 100% { 39 | opacity: 1; 40 | -webkit-transform: scale(1); 41 | -ms-transform: scale(1); 42 | transform: scale(1); 43 | } 44 | } 45 | #gritter-notice-wrapper.top-left { 46 | left: 20px; 47 | right: auto; 48 | } 49 | #gritter-notice-wrapper.bottom-right { 50 | top: auto; 51 | left: auto; 52 | bottom: 20px; 53 | right: 20px; 54 | } 55 | #gritter-notice-wrapper.bottom-left { 56 | top: auto; 57 | right: auto; 58 | bottom: 20px; 59 | left: 20px; 60 | } 61 | .gritter-item-wrapper { 62 | position:relative; 63 | margin:0 0 10px 0; 64 | background:url('images/ie-spacer.gif'); /* ie7/8 fix */ 65 | } 66 | 67 | .hover .gritter-top { 68 | /*background-position:right -30px;*/ 69 | } 70 | .gritter-bottom { 71 | height:8px; 72 | margin:0; 73 | } 74 | 75 | .gritter-item { 76 | display:block; 77 | background-color: rgba(39,58,75,0.8); 78 | border-radius: 4px; 79 | color:#eee; 80 | padding:10px 11px 10px 11px; 81 | font-size: 11px; 82 | font-family:verdana; 83 | } 84 | .hover .gritter-item { 85 | background-position:right -40px; 86 | } 87 | .gritter-item p { 88 | padding:0; 89 | margin:0; 90 | word-wrap:break-word; 91 | } 92 | 93 | .gritter-item a:hover { 94 | color: #f8ac59; 95 | text-decoration: underline; 96 | } 97 | .gritter-close { 98 | display:none; 99 | position:absolute; 100 | top:5px; 101 | right:3px; 102 | background:url(images/gritter.png) no-repeat left top; 103 | cursor:pointer; 104 | width:30px; 105 | height:30px; 106 | text-indent:-9999em; 107 | } 108 | .gritter-title { 109 | font-size:12px; 110 | font-weight:bold; 111 | padding:0 0 7px 0; 112 | display:block; 113 | text-transform: uppercase; 114 | } 115 | .gritter-image { 116 | width:48px; 117 | height:48px; 118 | float:left; 119 | } 120 | .gritter-with-image, 121 | .gritter-without-image { 122 | padding:0; 123 | } 124 | .gritter-with-image { 125 | width:220px; 126 | float:right; 127 | } 128 | /* for the light (white) version of the gritter notice */ 129 | .gritter-light .gritter-item, 130 | .gritter-light .gritter-bottom, 131 | .gritter-light .gritter-top, 132 | .gritter-light .gritter-close { 133 | background-image: url(images/gritter-light.png); 134 | color: #222; 135 | } 136 | .gritter-light .gritter-title { 137 | text-shadow: none; 138 | } 139 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/laydate/skins/default/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/laydate/skins/default/icon.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/laydate/skins/default/laydate.css: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | @Name: laydate皮肤:墨绿 4 | @Author:贤心 5 | @Site:http://sentsin.com/layui/laydate 6 | 7 | **/ 8 | 9 | .laydate-icon{border:1px solid #ccc; background-image:url(icon.png)} 10 | 11 | .laydate_body .laydate_bottom #laydate_hms, 12 | .laydate_body .laydate_time{border:1px solid #ccc;} 13 | 14 | .laydate_body .laydate_box, 15 | .laydate_body .laydate_ym .laydate_yms, 16 | .laydate_body .laydate_time{box-shadow: 2px 2px 5px rgba(0,0,0,.1);} 17 | 18 | .laydate_body .laydate_box{border-top:none; border-bottom:none; background-color:#fff; color:#00625A;} 19 | .laydate_body .laydate_box input{background:none!important; color:#fff;} 20 | .laydate_body .laydate_box .laydate_void{color:#00E8D7!important;} 21 | .laydate_body .laydate_box a, .laydate_body .laydate_box a:hover{color:#00625A;} 22 | .laydate_body .laydate_box a:hover{color:#666;} 23 | .laydate_body .laydate_click{background-color:#009F95!important; color:#fff!important;} 24 | .laydate_body .laydate_top{border-top:1px solid #009F95; background-color:#009F95} 25 | .laydate_body .laydate_ym{border:1px solid #009F95; background-color:#009F95;} 26 | .laydate_body .laydate_ym .laydate_yms{border:1px solid #009F95; background-color:#009F95; color:#fff;} 27 | .laydate_body .laydate_y .laydate_yms a{border-bottom:1px solid #009F95;} 28 | .laydate_body .laydate_y .laydate_yms .laydate_chdown{border-top:1px solid #009F95; border-bottom:none;} 29 | .laydate_body .laydate_choose{border-left:1px solid #009F95;} 30 | .laydate_body .laydate_chprev{border-left:none; border-right:1px solid #009F95;} 31 | .laydate_body .laydate_choose:hover, 32 | .laydate_body .laydate_y .laydate_yms a:hover{background-color:#00C1B3;} 33 | .laydate_body .laydate_chtop cite{border-bottom-color:#fff;} 34 | .laydate_body .laydate_chdown cite, .laydate_body .laydate_ym label{border-top-color:#fff;} 35 | .laydate_body .laydate_chprev cite{border-right-style:solid; border-right-color:#fff;} 36 | .laydate_body .laydate_chnext cite{border-left-style:solid; border-left-color:#fff;} 37 | .laydate_body .laydate_table{width: 240px!important; margin: 0!important; border:1px solid #ccc; border-top:none; border-bottom:none;} 38 | .laydate_body .laydate_table td{border:none; height:21px!important; line-height:21px!important; background-color:#fff; color:#00625A;} 39 | .laydate_body .laydate_table .laydate_nothis{color:#999;} 40 | .laydate_body .laydate_table thead{border-bottom:1px solid #ccc; height:21px!important; line-height:21px!important;} 41 | .laydate_body .laydate_table thead th{} 42 | .laydate_body .laydate_bottom{border:1px solid #ccc; border-top:none;} 43 | .laydate_body .laydate_bottom #laydate_hms{background-color:#fff;} 44 | .laydate_body .laydate_time{background-color:#fff;} 45 | .laydate_body .laydate_time1{width: 226px!important; height: 152px!important;} 46 | .laydate_body .laydate_bottom .laydate_sj{width:31px!important; border-right:1px solid #ccc; background-color:#fff;} 47 | .laydate_body .laydate_bottom input{background-color:#fff; color:#00625A;} 48 | .laydate_body .laydate_bottom .laydte_hsmtex{border-bottom:1px solid #ccc;} 49 | .laydate_body .laydate_bottom .laydate_btn{border-right:1px solid #ccc;} 50 | .laydate_body .laydate_bottom .laydate_v{color:#999} 51 | .laydate_body .laydate_bottom .laydate_btn a{border: 1px solid #ccc; border-right:none; background-color:#fff;} 52 | .laydate_body .laydate_bottom .laydate_btn a:hover{background-color:#F6F6F6; color:#00625A;} 53 | 54 | .laydate_body .laydate_m .laydate_yms span:hover, 55 | .laydate_body .laydate_time .laydate_hmsno span:hover, 56 | .laydate_body .laydate_y .laydate_yms ul li:hover, 57 | .laydate_body .laydate_table td:hover{background-color:#00C1B3; color:#fff;} 58 | 59 | 60 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/layim/data/chatlog.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 1, 3 | "msg": "ok", 4 | "data": [ 5 | { 6 | "id": "100001", 7 | "name": "Beaut-zihan", 8 | "time": "10:23", 9 | "face": "img/a1.jpg" 10 | }, 11 | { 12 | "id": "100002", 13 | "name": "慕容晓晓", 14 | "time": "昨天", 15 | "face": "img/a2.jpg" 16 | }, 17 | { 18 | "id": "1000033", 19 | "name": "乔峰", 20 | "time": "2014-4.22", 21 | "face": "img/a3.jpg" 22 | }, 23 | { 24 | "id": "10000333", 25 | "name": "高圆圆", 26 | "time": "2014-4.21", 27 | "face": "img/a4.jpg" 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/layim/data/friend.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 1, 3 | "msg": "ok", 4 | "data": [ 5 | { 6 | "name": "销售部", 7 | "nums": 36, 8 | "id": 1, 9 | "item": [ 10 | { 11 | "id": "100001", 12 | "name": "郭敬明", 13 | "face": "img/a5.jpg" 14 | }, 15 | { 16 | "id": "100002", 17 | "name": "作家崔成浩", 18 | "face": "img/a6.jpg" 19 | }, 20 | { 21 | "id": "1000022", 22 | "name": "韩寒", 23 | "face": "img/a7.jpg" 24 | }, 25 | { 26 | "id": "10000222", 27 | "name": "范爷", 28 | "face": "img/a8.jpg" 29 | }, 30 | { 31 | "id": "100002222", 32 | "name": "小马哥", 33 | "face": "img/a9.jpg" 34 | } 35 | ] 36 | }, 37 | { 38 | "name": "大学同窗", 39 | "nums": 16, 40 | "id": 2, 41 | "item": [ 42 | { 43 | "id": "1000033", 44 | "name": "苏醒", 45 | "face": "img/a9.jpg" 46 | }, 47 | { 48 | "id": "10000333", 49 | "name": "马云", 50 | "face": "img/a8.jpg" 51 | }, 52 | { 53 | "id": "100003", 54 | "name": "鬼脚七", 55 | "face": "img/a7.jpg" 56 | }, 57 | { 58 | "id": "100004", 59 | "name": "谢楠", 60 | "face": "img/a6.jpg" 61 | }, 62 | { 63 | "id": "100005", 64 | "name": "徐峥", 65 | "face": "img/a5.jpg" 66 | } 67 | ] 68 | }, 69 | { 70 | "name": "H+后台主题", 71 | "nums": 38, 72 | "id": 3, 73 | "item": [ 74 | { 75 | "id": "100006", 76 | "name": "柏雪近在它香", 77 | "face": "img/a4.jpg" 78 | }, 79 | { 80 | "id": "100007", 81 | "name": "罗昌平", 82 | "face": "img/a3.jpg" 83 | }, 84 | { 85 | "id": "100008", 86 | "name": "Crystal影子", 87 | "face": "img/a2.jpg" 88 | }, 89 | { 90 | "id": "100009", 91 | "name": "艺小想", 92 | "face": "img/a1.jpg" 93 | }, 94 | { 95 | "id": "100010", 96 | "name": "天猫", 97 | "face": "img/a8.jpg" 98 | }, 99 | { 100 | "id": "100011", 101 | "name": "张泉灵", 102 | "face": "img/a7.jpg" 103 | } 104 | ] 105 | } 106 | ] 107 | } 108 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/layim/data/group.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 1, 3 | "msg": "ok", 4 | "data": [ 5 | { 6 | "name": "H+交流群", 7 | "nums": 36, 8 | "id": 1, 9 | "item": [ 10 | { 11 | "id": "101", 12 | "name": "H+ Bug反馈", 13 | "face": "http://tp2.sinaimg.cn/2211874245/180/40050524279/0" 14 | }, 15 | { 16 | "id": "102", 17 | "name": "H+ 技术交流", 18 | "face": "http://tp3.sinaimg.cn/1820711170/180/1286855219/1" 19 | } 20 | ] 21 | }, 22 | { 23 | "name": "Bootstrap", 24 | "nums": 16, 25 | "id": 2, 26 | "item": [ 27 | { 28 | "id": "103", 29 | "name": "Bootstrap中文", 30 | "face": "http://tp2.sinaimg.cn/2211874245/180/40050524279/0" 31 | }, 32 | { 33 | "id": "104", 34 | "name": "Bootstrap资源", 35 | "face": "http://tp3.sinaimg.cn/1820711170/180/1286855219/1" 36 | } 37 | ] 38 | }, 39 | { 40 | "name": "WebApp", 41 | "nums": 106, 42 | "id": 3, 43 | "item": [ 44 | { 45 | "id": "105", 46 | "name": "移动开发", 47 | "face": "http://tp2.sinaimg.cn/2211874245/180/40050524279/0" 48 | }, 49 | { 50 | "id": "106", 51 | "name": "H5前言", 52 | "face": "http://tp3.sinaimg.cn/1820711170/180/1286855219/1" 53 | } 54 | ] 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/layim/data/groups.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 1, 3 | "msg": "ok", 4 | "data": [ 5 | { 6 | "id": "100001", 7 | "name": "無言的蒁説", 8 | "face": "img/a1.jpg" 9 | }, 10 | { 11 | "id": "100002", 12 | "name": "婷宝奢侈品", 13 | "face": "img/a2.jpg" 14 | }, 15 | { 16 | "id": "100003", 17 | "name": "忆恨思爱", 18 | "face": "img/a3.jpg" 19 | }, 20 | { 21 | "id": "100004", 22 | "name": "天涯奥拓慢", 23 | "face": "img/a4.jpg" 24 | }, 25 | { 26 | "id": "100005", 27 | "name": "雨落无声的天空", 28 | "face": "img/a5.jpg" 29 | }, 30 | { 31 | "id": "100006", 32 | "name": "李越LycorisRadiate", 33 | "face": "img/a6.jpg" 34 | }, 35 | { 36 | "id": "100007", 37 | "name": "冯胖妞张直丑", 38 | "face": "img/a7.jpg" 39 | }, 40 | { 41 | "id": "100008", 42 | "name": "陈龙hmmm", 43 | "face": "img/a8.jpg" 44 | }, 45 | { 46 | "id": "100009", 47 | "name": "别闹哥胆儿小", 48 | "face": "img/a9.jpg" 49 | }, 50 | { 51 | "id": "100010", 52 | "name": "锅锅锅锅萌哒哒 ", 53 | "face": "img/a10.jpg" 54 | } 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/layim/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/layim/loading.gif -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/default/icon-ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/default/icon-ext.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/default/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/default/icon.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/default/icon_ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/default/icon_ext.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/default/loading-0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/default/loading-0.gif -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/default/loading-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/default/loading-1.gif -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/default/loading-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/default/loading-2.gif -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/default/textbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/default/textbg.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/default/xubox_ico0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/default/xubox_ico0.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/default/xubox_loading0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/default/xubox_loading0.gif -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/default/xubox_loading1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/default/xubox_loading1.gif -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/default/xubox_loading2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/default/xubox_loading2.gif -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/default/xubox_loading3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/default/xubox_loading3.gif -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/default/xubox_title0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/default/xubox_title0.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/layer.ext.css: -------------------------------------------------------------------------------- 1 | /*! 2 | 3 | @Name: layer拓展样式 4 | @Date: 2012.12.13 5 | @Author: 贤心 6 | @blog: sentsin.com 7 | 8 | */.layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span{text-overflow:ellipsis;white-space:nowrap}.layui-layer-iconext{background:url(default/icon-ext.png) no-repeat} html #layui_layer_skinlayerextcss{display:none;position:absolute;width:1989px} .layui-layer-prompt .layui-layer-input{display:block;width:220px;height:30px;margin:0 auto;line-height:30px;padding:0 5px;border:1px solid #ccc;box-shadow:1px 1px 5px rgba(0,0,0,.1) inset;color:#333} .layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px} .layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)} .layui-layer-tab .layui-layer-title{padding-left:0;border-bottom:1px solid #ccc;background-color:#eee;overflow:visible} .layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:260px;padding:0 20px;text-align:center;cursor:default;overflow:hidden} .layui-layer-tab .layui-layer-title span.layui-layer-tabnow{height:43px;border-left:1px solid #ccc;border-right:1px solid #ccc;background-color:#fff;z-index:10} .layui-layer-tab .layui-layer-title span:first-child{border-left:none} .layui-layer-tabmain{line-height:24px;clear:both} .layui-layer-tabmain .layui-layer-tabli{display:none} .layui-layer-tabmain .layui-layer-tabli.xubox_tab_layer{display:block} .xubox_tabclose{position:absolute;right:10px;top:5px;cursor:pointer} .layui-layer-photos{-webkit-animation-duration:1s;animation-duration:1s;background:url(default/xubox_loading1.gif) center center no-repeat #000} .layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center} .layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top} .layui-layer-imgbar,.layui-layer-imguide{display:none} .layui-layer-imgnext,.layui-layer-imgprev{position:absolute;top:50%;width:27px;_width:44px;height:44px;margin-top:-22px;outline:0;blr:expression(this.onFocus=this.blur())} .layui-layer-imgprev{left:10px;background-position:-5px -5px;_background-position:-70px -5px} .layui-layer-imgprev:hover{background-position:-33px -5px;_background-position:-120px -5px} .layui-layer-imgnext{right:10px;_right:8px;background-position:-5px -50px;_background-position:-70px -50px} .layui-layer-imgnext:hover{background-position:-33px -50px;_background-position:-120px -50px} .layui-layer-imgbar{position:absolute;left:0;bottom:0;width:100%;height:32px;line-height:32px;background-color:rgba(0,0,0,.8);background-color:#000\9;filter:Alpha(opacity=80);color:#fff;overflow:hidden;font-size:0} .layui-layer-imgtit *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:12px} .layui-layer-imgtit a{max-width:65%;overflow:hidden;color:#fff} .layui-layer-imgtit a:hover{color:#fff;text-decoration:underline} .layui-layer-imgtit em{padding-left:10px;font-style:normal} 9 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/layer/skin/moon/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/static/js/plugins/layer/skin/moon/default.png -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/markdown/bootstrap-markdown.zh.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Chinese translation for bootstrap-markdown 3 | * benhaile 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.zh = { 7 | 'Bold': "粗体", 8 | 'Italic': "斜体", 9 | 'Heading': "标题", 10 | 'URL/Link': "链接", 11 | 'Image': "图片", 12 | 'List': "列表", 13 | 'Unordered List': "无序列表", 14 | 'Ordered List': "有序列表", 15 | 'Code': "代码", 16 | 'Quote': "引用", 17 | 'Preview': "预览", 18 | 'strong text': "粗体", 19 | 'emphasized text': "强调", 20 | 'heading text': "标题", 21 | 'enter link description here': "输入链接说明", 22 | 'Insert Hyperlink': "URL地址", 23 | 'enter image description here': "输入图片说明", 24 | 'Insert Image Hyperlink': "图片URL地址", 25 | 'enter image title here': "在这里输入图片标题", 26 | 'list text here': "这里是列表文本", 27 | 'code text here': "这里输入代码", 28 | 'quote here': "这里输入引用文本" 29 | 30 | 31 | }; 32 | }(jQuery)); 33 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/peity/jquery.peity.min.js: -------------------------------------------------------------------------------- 1 | // Peity jQuery plugin version 2.0.3 2 | // (c) 2014 Ben Pickles 3 | // 4 | // http://benpickles.github.io/peity 5 | // 6 | // Released under MIT license. 7 | (function(e,q,h){var o=function(a,b){var c=q.createElementNS("http://www.w3.org/2000/svg",a);e.each(b,function(a,b){c.setAttribute(a,b)});return c},t="createElementNS"in q&&o("svg",{}).createSVGRect,r=1/(window.devicePixelRatio||1),j=e.fn.peity=function(a,b){t&&this.each(function(){var c=e(this),d=c.data("peity");if(d)a&&(d.type=a),e.extend(d.opts,b);else{var f=j.defaults[a],g={};e.each(c.data(),function(a,b){a in f&&(g[a]=b)});var h=e.extend({},f,g,b),d=new s(c,a,h);c.change(function(){d.draw()}).data("peity", 8 | d)}d.draw()});return this},s=function(a,b,c){this.$el=a;this.type=b;this.opts=c},m=s.prototype;m.draw=function(){j.graphers[this.type].call(this,this.opts)};m.fill=function(){var a=this.opts.fill,b=a;e.isFunction(b)||(b=function(b,d){return a[d%a.length]});return b};m.prepare=function(a,b){var c;this.svg?c=e(this.svg).empty():(this.svg=o("svg",{"class":"peity"}),this.$el.hide().after(this.svg),c=e(this.svg).data("peity",this));this.svg.setAttribute("height",b);this.svg.setAttribute("width",a);return c}; 9 | m.values=function(){return e.map(this.$el.text().split(this.opts.delimiter),function(a){return parseFloat(a)})};j.defaults={};j.graphers={};j.register=function(a,b,c){this.defaults[a]=b;this.graphers[a]=c};j.register("pie",{delimiter:null,diameter:16,fill:["#ff9900","#fff4dd","#ffc66e"]},function(a){if(!a.delimiter){var b=this.$el.text().match(/[^0-9\.]/);a.delimiter=b?b[0]:","}b=this.values();if("/"==a.delimiter)var c=b[0],b=[c,h.max(0,b[1]-c)];for(var d=0,c=b.length,f=0;de?1:0,1,q,r,"Z"].join(" ")});i=l}k.setAttribute("fill",j.call(this,n,d,b));this.svg.appendChild(k)}}});j.register("line",{delimiter:",",fill:"#c6d9fd",height:16,max:null, 11 | min:0,stroke:"#4d89f9",strokeWidth:1,width:32},function(a){var b=this.values();1==b.length&&b.push(b[0]);for(var c=h.max.apply(h,b.concat([a.max])),d=h.min.apply(h,b.concat([a.min])),f=this.prepare(a.width,a.height),g=f.width(),f=f.height()-a.strokeWidth,e=g/(b.length-1),c=c-d,j=0==c?f:f/c,m=f+d*j,c=[0,m],i=0;i=d&&0k&&(l+=k,k=-k);n=o("rect",{fill:m.call(this,n,i,b),x:i*g,y:l,width:g-a,height:k});this.svg.appendChild(n)}})})(jQuery,document,Math); 14 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/preetyTextDiff/jquery.pretty-text-diff.min.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.7.1 2 | 3 | /* 4 | @preserve jQuery.PrettyTextDiff 1.0.4 5 | See https://github.com/arnab/jQuery.PrettyTextDiff/ 6 | */ 7 | 8 | (function() { 9 | var $; 10 | 11 | $ = jQuery; 12 | 13 | $.fn.extend({ 14 | prettyTextDiff: function(options) { 15 | var dmp, settings; 16 | settings = { 17 | originalContainer: ".original", 18 | changedContainer: ".changed", 19 | diffContainer: ".diff", 20 | cleanup: true, 21 | debug: false 22 | }; 23 | settings = $.extend(settings, options); 24 | $.fn.prettyTextDiff.debug("Options: ", settings, settings); 25 | dmp = new diff_match_patch(); 26 | return this.each(function() { 27 | var changed, diff_as_html, diffs, original; 28 | if (settings.originalContent && settings.changedContent) { 29 | original = $('
').html(settings.originalContent).text(); 30 | changed = $('
').html(settings.changedContent).text(); 31 | } else { 32 | original = $(settings.originalContainer, this).text(); 33 | changed = $(settings.changedContainer, this).text(); 34 | } 35 | $.fn.prettyTextDiff.debug("Original text found: ", original, settings); 36 | $.fn.prettyTextDiff.debug("Changed text found: ", changed, settings); 37 | diffs = dmp.diff_main(original, changed); 38 | if (settings.cleanup) { 39 | dmp.diff_cleanupSemantic(diffs); 40 | } 41 | $.fn.prettyTextDiff.debug("Diffs: ", diffs, settings); 42 | diff_as_html = $.map(diffs, function(diff) { 43 | return $.fn.prettyTextDiff.createHTML(diff); 44 | }); 45 | $(settings.diffContainer, this).html(diff_as_html.join('')); 46 | return this; 47 | }); 48 | } 49 | }); 50 | 51 | $.fn.prettyTextDiff.debug = function(message, object, settings) { 52 | if (settings.debug) { 53 | return console.log(message, object); 54 | } 55 | }; 56 | 57 | $.fn.prettyTextDiff.createHTML = function(diff) { 58 | var data, html, operation, pattern_amp, pattern_gt, pattern_lt, pattern_para, text; 59 | html = []; 60 | pattern_amp = /&/g; 61 | pattern_lt = //g; 63 | pattern_para = /\n/g; 64 | operation = diff[0], data = diff[1]; 65 | text = data.replace(pattern_amp, '&').replace(pattern_lt, '<').replace(pattern_gt, '>').replace(pattern_para, '
'); 66 | switch (operation) { 67 | case DIFF_INSERT: 68 | return '' + text + ''; 69 | case DIFF_DELETE: 70 | return '' + text + ''; 71 | case DIFF_EQUAL: 72 | return '' + text + ''; 73 | } 74 | }; 75 | 76 | }).call(this); 77 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/prettyfile/bootstrap-prettyfile.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery and Bootsrap3 Plugin prettyFile 3 | * 4 | * version 2.0, Jan 20th, 2014 5 | * by episage, sujin2f 6 | * Git repository : https://github.com/episage/bootstrap-3-pretty-file-upload 7 | */ 8 | ( function( $ ) { 9 | $.fn.extend({ 10 | prettyFile: function( options ) { 11 | var defaults = { 12 | text : "选择文件" 13 | }; 14 | 15 | var options = $.extend(defaults, options); 16 | var plugin = this; 17 | 18 | function make_form( $el, text ) { 19 | $el.wrap('
'); 20 | 21 | $el.hide(); 22 | $el.after( '\ 23 |
\ 24 | \ 25 | \ 26 | \ 27 | \ 28 |
\ 29 | ' ); 30 | 31 | return $el.parent(); 32 | }; 33 | 34 | function bind_change( $wrap, multiple ) { 35 | $wrap.find( 'input[type="file"]' ).change(function () { 36 | // When original file input changes, get its value, show it in the fake input 37 | var files = $( this )[0].files, 38 | info = ''; 39 | 40 | if ( files.length == 0 ) 41 | return false; 42 | 43 | if ( !multiple || files.length == 1 ) { 44 | var path = $( this ).val().split('\\'); 45 | info = path[path.length - 1]; 46 | } else if ( files.length > 1 ) { 47 | // Display number of selected files instead of filenames 48 | info = "已选择了" + files.length + ' 个文件'; 49 | } 50 | 51 | $wrap.find('.input-append input').val( info ); 52 | }); 53 | }; 54 | 55 | function bind_button( $wrap, multiple ) { 56 | $wrap.find( '.input-append' ).click( function( e ) { 57 | e.preventDefault(); 58 | $wrap.find( 'input[type="file"]' ).click(); 59 | }); 60 | }; 61 | 62 | return plugin.each( function() { 63 | $this = $( this ); 64 | 65 | if ( $this ) { 66 | var multiple = $this.attr( 'multiple' ); 67 | 68 | $wrap = make_form( $this, options.text ); 69 | bind_change( $wrap, multiple ); 70 | bind_button( $wrap ); 71 | } 72 | }); 73 | } 74 | }); 75 | }( jQuery )); 76 | 77 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/suggest/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "", 3 | "value": [ 4 | { 5 | "userName": "淳芸", 6 | "shortAccount": "chunyun", 7 | "userId": 20001 8 | }, { 9 | "userName": "orion-01", 10 | "shortAccount": "chunyun", 11 | "userId": 20000 12 | }, { 13 | "userName": "穆晓晨", 14 | "shortAccount": "chunyun", 15 | "userId": 20002 16 | }, { 17 | "userName": "张欢引", 18 | "shortAccount": "chunyun", 19 | "userId": 20003 20 | }, { 21 | "userName": "吴琼", 22 | "shortAccount": "wuqiong", 23 | "userId": 20004 24 | }, { 25 | "userName": "吴东鹏", 26 | "shortAccount": "wudongpeng", 27 | "userId": 20005 28 | }, { 29 | "userName": "黄少铅", 30 | "shortAccount": "huangshaoqian", 31 | "userId": 20006 32 | }, { 33 | "userName": "胡运燕", 34 | "shortAccount": "yunyan", 35 | "userId": 20007 36 | }, { 37 | "userName": "刘幸", 38 | "shortAccount": "liuxing", 39 | "userId": 20008 40 | }, { 41 | "userName": "陈媛媛", 42 | "shortAccount": "chenyuanyuan", 43 | "userId": 20009 44 | }, { 45 | "userName": "旷东林", 46 | "shortAccount": "chunyun", 47 | "userId": 20010 48 | }, { 49 | "userName": "唐宏禹", 50 | "shortAccount": "chunyun", 51 | "userId": 20011 52 | }, { 53 | "userName": "旷东林", 54 | "shortAccount": "kuangdonglin", 55 | "userId": 20010 56 | }, { 57 | "userName": "唐宏禹", 58 | "shortAccount": "tanghongyu", 59 | "userId": 20011 60 | } 61 | ], 62 | "code": 200, 63 | "redirect": "" 64 | } 65 | -------------------------------------------------------------------------------- /manager/src/main/resources/static/js/plugins/validate/messages_zh.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Validation Plugin - v1.13.1 - 10/14/2014 2 | * http://jqueryvalidation.org/ 3 | * Copyright (c) 2014 Jörn Zaefferer; Licensed MIT */ 4 | ! function (a) { 5 | "function" == typeof define && define.amd ? define(["jquery", "jquery.validate.min.js"], a) : a(jQuery) 6 | }(function (a) { 7 | var icon = " "; 8 | a.extend(a.validator.messages, { 9 | required: icon + "必填", 10 | remote: icon + "请修正此栏位", 11 | email: icon + "请输入有效的电子邮件", 12 | url: icon + "请输入有效的网址", 13 | date: icon + "请输入有效的日期", 14 | dateISO: icon + "请输入有效的日期 (YYYY-MM-DD)", 15 | number: icon + "请输入正确的数字", 16 | digits: icon + "只能输入数字", 17 | creditcard: icon + "请输入有效的信用卡号码", 18 | equalTo: icon + "你的输入不相同", 19 | extension: icon + "请输入有效的后缀", 20 | maxlength: a.validator.format(icon + "最多 {0} 个字"), 21 | minlength: a.validator.format(icon + "最少 {0} 个字"), 22 | rangelength: a.validator.format(icon + "请输入长度为 {0} 至 {1} 之间的字串"), 23 | range: a.validator.format(icon + "请输入 {0} 至 {1} 之间的数值"), 24 | max: a.validator.format(icon + "请输入不大于 {0} 的数值"), 25 | min: a.validator.format(icon + "请输入不小于 {0} 的数值") 26 | }) 27 | }); 28 | -------------------------------------------------------------------------------- /manager/src/main/resources/templates/course.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generic - 5 | 6 | 7 | 8 | 9 | 10 |

待开放中...


11 | 参考frp官方文档 12 | 13 | -------------------------------------------------------------------------------- /manager/src/main/resources/templates/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | footer 5 | 6 | 7 | 8 | 9 |
10 |
11 | 12 |
13 |
14 | 15 | -------------------------------------------------------------------------------- /manager/src/main/resources/templates/manager/common.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /manager/src/main/resources/templates/manager/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | - 登录 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 |
21 |
22 |
23 |

FRP

24 |
25 |

欢迎使用 FRP内网穿透

26 |
27 |
28 | 29 |
30 |
31 | 32 |
33 | 34 |

忘记密码了? | 注册一个新账号 35 |

36 |
37 |
38 |
39 | 40 | 41 | 42 | 43 | 51 | 52 | -------------------------------------------------------------------------------- /manager/src/main/resources/templates/manager/register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | - 注册 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 |

FRP

21 |
22 |

欢迎注册 FRP

23 |
24 |
25 | 26 |
27 |
28 | 29 |
30 |
31 | 32 |
33 |
34 |
35 | 37 |
38 |
39 | 40 |

已经有账户了?点此登录 41 |

42 |
43 |
44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 63 | 64 | -------------------------------------------------------------------------------- /manager/src/main/resources/www-kisme-org.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pickear/penetrate/96dcf71976bf8311148cae20d09faa91d8adbc24/manager/src/main/resources/www-kisme-org.jks -------------------------------------------------------------------------------- /manager/src/test/java/com/weasel/penetrate/manager/JasyptTest.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.manager; 2 | 3 | import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; 4 | import org.junit.Test; 5 | 6 | /** 7 | * Created by dell on 2017/3/16. 8 | */ 9 | public class JasyptTest { 10 | 11 | @Test 12 | public void encode(){ 13 | StandardPBEStringEncryptor spe = new StandardPBEStringEncryptor(); 14 | spe.setPassword("666"); 15 | /* spe.setAlgorithm("PBEWithMD5AndDES");*/ 16 | String encrype = spe.encrypt("aaaa"); 17 | System.out.println(encrype); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /monitor/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | penetrate 7 | com.weasel.penetrate 8 | 0.2.0 9 | 10 | 4.0.0 11 | 12 | monitor 13 | 14 | 15 | 16 | net.sourceforge.htmlunit 17 | htmlunit 18 | 19 | 20 | joda-time 21 | joda-time 22 | 23 | 24 | 25 | 26 | 27 | 28 | org.apache.maven.plugins 29 | maven-surefire-plugin 30 | 31 | true 32 | 33 | 34 | 35 | org.apache.maven.plugins 36 | maven-compiler-plugin 37 | 3.1 38 | 39 | 1.8 40 | 1.8 41 | UTF-8 42 | 43 | 44 | 45 | org.apache.maven.plugins 46 | maven-shade-plugin 47 | 2.4.1 48 | 49 | 50 | package 51 | 52 | shade 53 | 54 | 55 | 56 | 58 | com.weasel.penetrate.monitor.FrpMonitor 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | com.github.edwgiz 68 | maven-shade-plugin.log4j2-cachefile-transformer 69 | 2.6.1 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /monitor/src/main/java/com.weasel.penetrate.monitor/DeviceStatus.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.monitor; 2 | 3 | import org.apache.commons.lang3.builder.EqualsBuilder; 4 | import org.apache.commons.lang3.builder.HashCodeBuilder; 5 | import org.joda.time.DateTime; 6 | 7 | import java.util.Date; 8 | 9 | /** 10 | * Created by dell on 2017/3/27. 11 | */ 12 | public class DeviceStatus { 13 | 14 | private String number; 15 | private String status; 16 | private long connects; 17 | private long flowIn; 18 | private long flowOut; 19 | private long totalConnects; 20 | private String time = DateTime.now().toString("yyyy-MM-dd HH:mm:ss"); 21 | 22 | public String getNumber() { 23 | return number; 24 | } 25 | 26 | public void setNumber(String number) { 27 | this.number = number; 28 | } 29 | 30 | public String getStatus() { 31 | return status; 32 | } 33 | 34 | public void setStatus(String status) { 35 | this.status = status; 36 | } 37 | 38 | public long getConnects() { 39 | return connects; 40 | } 41 | 42 | public void setConnects(long connects) { 43 | this.connects = connects; 44 | } 45 | 46 | public long getFlowIn() { 47 | return flowIn; 48 | } 49 | 50 | public void setFlowIn(long flowIn) { 51 | this.flowIn = flowIn; 52 | } 53 | 54 | public long getFlowOut() { 55 | return flowOut; 56 | } 57 | 58 | public void setFlowOut(long flowOut) { 59 | this.flowOut = flowOut; 60 | } 61 | 62 | public long getTotalConnects() { 63 | return totalConnects; 64 | } 65 | 66 | public void setTotalConnects(long totalConnects) { 67 | this.totalConnects = totalConnects; 68 | } 69 | 70 | public String getTime() { 71 | return time; 72 | } 73 | 74 | public void setTime(String time) { 75 | this.time = time; 76 | } 77 | 78 | @Override 79 | public boolean equals(Object o) { 80 | if(null == o){ 81 | return false; 82 | } 83 | if( o == this){ 84 | return true; 85 | } 86 | if(!(o instanceof DeviceStatus)){ 87 | return false; 88 | } 89 | return new EqualsBuilder().append(this.getNumber(),((DeviceStatus)o).getNumber()).isEquals(); 90 | } 91 | 92 | @Override 93 | public int hashCode() { 94 | final int PRIME = 31; 95 | int number = Integer.valueOf(getNumber()); 96 | return new HashCodeBuilder(number%2==0?number+1:number, PRIME).toHashCode(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /monitor/src/main/java/com.weasel.penetrate.monitor/FrpMonitor.java: -------------------------------------------------------------------------------- 1 | package com.weasel.penetrate.monitor; 2 | 3 | import com.gargoylesoftware.htmlunit.BrowserVersion; 4 | import com.gargoylesoftware.htmlunit.WebClient; 5 | import com.gargoylesoftware.htmlunit.html.DomElement; 6 | import com.gargoylesoftware.htmlunit.html.HtmlPage; 7 | import org.apache.commons.lang3.StringUtils; 8 | 9 | import java.io.IOException; 10 | import java.nio.charset.Charset; 11 | import java.util.*; 12 | 13 | /** 14 | * Created by dell on 2017/3/23. 15 | */ 16 | public class FrpMonitor { 17 | 18 | public static void main(String[] args) throws IOException { 19 | 20 | String authorization = Base64.getEncoder().encodeToString("admin:kisme".getBytes(Charset.forName("utf-8"))); 21 | 22 | WebClient webClient = new WebClient(BrowserVersion.CHROME); 23 | webClient.addRequestHeader("Authorization","Basic "+authorization); 24 | HtmlPage htmlPage = webClient.getPage("http://127.0.0.1:7998/frp-status"); 25 | Iterable domElements = htmlPage.getElementById("tab_body").getChildElements(); 26 | Set deviceStatuss = new HashSet<>(); 27 | domElements.forEach(domElement -> { 28 | DeviceStatus deviceStatus = new DeviceStatus(); 29 | Iterable domElementss = domElement.getChildElements(); 30 | int index = 0; 31 | for(Iterator it = domElementss.iterator();it.hasNext();index++){ 32 | DomElement aaa = (DomElement)it.next(); 33 | String content = aaa.getTextContent(); 34 | content = StringUtils.removeAll(content,"\n*\t*"); 35 | switch (index){ 36 | case 0: 37 | deviceStatus.setNumber(content); 38 | break; 39 | case 1: 40 | break; 41 | case 2: 42 | break; 43 | case 3: 44 | deviceStatus.setStatus(content); 45 | break; 46 | case 4: 47 | deviceStatus.setConnects(Long.valueOf(content)); 48 | break; 49 | case 5: 50 | deviceStatus.setFlowOut(Long.valueOf(content)); 51 | break; 52 | case 6: 53 | deviceStatus.setFlowIn(Long.valueOf(content)); 54 | break; 55 | case 7: 56 | deviceStatus.setTotalConnects(Long.valueOf(content)); 57 | break; 58 | default:break; 59 | } 60 | } 61 | deviceStatuss.add(deviceStatus); 62 | }); 63 | webClient.close(); 64 | } 65 | } 66 | --------------------------------------------------------------------------------