├── 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 | 
16 |
17 | 
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 |
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 |
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 |
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 | '' +
45 | $('#nav').html() +
46 | '
' +
47 | '
'
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 |
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 |
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 |
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 |
--------------------------------------------------------------------------------