mirror of https://github.com/flucont/btcloud.git
				
				
			
				 35 changed files with 2433 additions and 106 deletions
			
			
		- 
					10README.md
 - 
					59app/command/UpdateAll.php
 - 
					4app/common.php
 - 
					32app/controller/Admin.php
 - 
					102app/controller/Api.php
 - 
					89app/lib/Plugins.php
 - 
					8app/view/admin/layout.html
 - 
					214app/view/admin/pluginswin.html
 - 
					84app/view/admin/set.html
 - 
					69app/view/index/download.html
 - 
					1data/config/deployment_list.json
 - 
					1data/win/config/deployment_list.json
 - 
					1data/win/config/plugin_list.json
 - 
					3install.sql
 - 
					BINpublic/install/src/panel6.zip
 - 
					BINpublic/install/update/LinuxPanel-7.9.2.zip
 - 
					182public/static/css/download.css
 - 
					BINpublic/static/file/kaixin.zip
 - 
					BINpublic/static/file/win/__init__.zip
 - 
					BINpublic/static/file/win/kaixin.zip
 - 
					BINpublic/static/images/downico1_01.png
 - 
					BINpublic/static/images/downico2_01.png
 - 
					BINpublic/static/images/prd_1_03.png
 - 
					BINpublic/static/images/prd_2_03.png
 - 
					109public/win/install/panel_update.py
 - 
					BINpublic/win/panel/BtTools20.exe
 - 
					BINpublic/win/panel/BtTools45.exe
 - 
					164public/win/panel/data/api.py
 - 
					1040public/win/panel/data/setup.py
 - 
					BINpublic/win/panel/panel_7.6.0.zip
 - 
					17route/app.php
 - 
					202wiki/files/win/bt.js
 - 
					60wiki/files/win/pluginAuth.py
 - 
					10wiki/update.md
 - 
					78wiki/updatewin.md
 
@ -0,0 +1,214 @@ | 
			
		|||||
 | 
				{extend name="admin/layout" /} | 
			
		||||
 | 
				{block name="title"}插件列表{/block} | 
			
		||||
 | 
				{block name="main"} | 
			
		||||
 | 
				<style> | 
			
		||||
 | 
				td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:340px;} | 
			
		||||
 | 
				.bt-ico-ask { | 
			
		||||
 | 
				  border: 1px solid #fb7d00; | 
			
		||||
 | 
				  border-radius: 8px; | 
			
		||||
 | 
				  color: #fb7d00; | 
			
		||||
 | 
				  cursor: help; | 
			
		||||
 | 
				  display: inline-block; | 
			
		||||
 | 
				  font-family: arial; | 
			
		||||
 | 
				  font-size: 11px; | 
			
		||||
 | 
				  font-style: normal; | 
			
		||||
 | 
				  height: 16px; | 
			
		||||
 | 
				  line-height: 16px; | 
			
		||||
 | 
				  margin-left: 5px; | 
			
		||||
 | 
				  text-align: center; | 
			
		||||
 | 
				  width: 16px | 
			
		||||
 | 
				} | 
			
		||||
 | 
				.bt-ico-ask:hover { | 
			
		||||
 | 
				  background-color: #fb7d00; | 
			
		||||
 | 
				  color: #fff | 
			
		||||
 | 
				} | 
			
		||||
 | 
				</style> | 
			
		||||
 | 
				<div class="modal fade" id="help" tabindex="-1" role="dialog"> | 
			
		||||
 | 
					<div class="modal-dialog" role="document"> | 
			
		||||
 | 
						<div class="modal-content"> | 
			
		||||
 | 
							<div class="modal-header"> | 
			
		||||
 | 
								<button type="button" class="close" data-dismiss="modal" aria-label="Close"> | 
			
		||||
 | 
									<span aria-hidden="true">×</span> | 
			
		||||
 | 
								</button> | 
			
		||||
 | 
								<h4 class="modal-title">帮助</h4> | 
			
		||||
 | 
							</div> | 
			
		||||
 | 
							<div class="modal-body"> | 
			
		||||
 | 
								<p>“版本与状态”一列中,红色的按钮代表本地不存在该版本插件包,需要点击下载;绿色的按钮代表已存在。</p> | 
			
		||||
 | 
				                <p>官方插件包本地存储路径是/data/win/plugins/package/软件标识-版本号.zip,第三方插件包路径是/data/plugins/other/other/,对于部分包含二次验证的插件可以自行修改。</p> | 
			
		||||
 | 
				                <p>点击【重新获取】按钮会从宝塔官方获取最新插件列表,但是插件包需要手动点击下载。如果需要批量下载插件包,可查看<a href="/admin/set/type/task">定时任务设置</a></p> | 
			
		||||
 | 
							</div> | 
			
		||||
 | 
							<div class="modal-footer"> | 
			
		||||
 | 
								<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button> | 
			
		||||
 | 
							</div> | 
			
		||||
 | 
						</div> | 
			
		||||
 | 
					</div> | 
			
		||||
 | 
				</div> | 
			
		||||
 | 
				<div class="container" style="padding-top:70px;"> | 
			
		||||
 | 
					<div class="col-xs-12 center-block" style="float: none;"> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				<div id="searchToolbar"> | 
			
		||||
 | 
				<form onsubmit="return searchSubmit()" method="GET" class="form-inline"> | 
			
		||||
 | 
				  <div class="form-group"> | 
			
		||||
 | 
				    <label>搜索</label> | 
			
		||||
 | 
					<input type="text" class="form-control" name="keyword" placeholder="应用名称"> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				  <div class="form-group"> | 
			
		||||
 | 
					<select name="type" class="form-control"><option value="0">全部插件</option> | 
			
		||||
 | 
				    {foreach $typelist as $k=>$v}<option value="{$k}">{$v}</option>{/foreach} </select> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				  <div class="form-group"> | 
			
		||||
 | 
					<button class="btn btn-primary" type="submit"><i class="fa fa-search"></i>搜索</button>  | 
			
		||||
 | 
					<a href="javascript:searchClear()" class="btn btn-default"><i class="fa fa-repeat"></i>重置</a>  | 
			
		||||
 | 
				    <a href="javascript:refresh_plugins()" class="btn btn-success"><i class="fa fa-refresh"></i>重新获取</a>  | 
			
		||||
 | 
				    <button type="button" class="btn btn-default" data-toggle="modal" data-target="#help"><i class="fa fa-info-circle"></i>帮助</button> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				</form> | 
			
		||||
 | 
				</div> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      <table id="listTable"> | 
			
		||||
 | 
					  </table> | 
			
		||||
 | 
					</div> | 
			
		||||
 | 
				  </div> | 
			
		||||
 | 
				<script src="//cdn.staticfile.org/layer/3.5.1/layer.js"></script> | 
			
		||||
 | 
				<script src="//cdn.staticfile.org/bootstrap-table/1.20.2/bootstrap-table.min.js"></script> | 
			
		||||
 | 
				<script src="//cdn.staticfile.org/bootstrap-table/1.20.2/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script> | 
			
		||||
 | 
				<script src="/static/js/custom.js"></script> | 
			
		||||
 | 
				<script> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				function download_version(name, version, status){ | 
			
		||||
 | 
				    if(status == true){ | 
			
		||||
 | 
				        var confirm = layer.confirm('是否确定重新下载'+version+'版本插件包?', { | 
			
		||||
 | 
				            btn: ['确定','取消'] | 
			
		||||
 | 
				        }, function(){ | 
			
		||||
 | 
				            download_plugin(name, version) | 
			
		||||
 | 
				        }, function(){ | 
			
		||||
 | 
				            layer.close(confirm) | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				    }else{ | 
			
		||||
 | 
				        download_plugin(name, version) | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				function download_plugin(name, version){ | 
			
		||||
 | 
				    var ii = layer.msg('正在下载,请稍候...', {icon: 16, shade:0.1, time: 0}); | 
			
		||||
 | 
				    $.ajax({ | 
			
		||||
 | 
						type : 'POST', | 
			
		||||
 | 
						url : '/admin/download_plugin', | 
			
		||||
 | 
				        data: { name:name, version:version, os:'Windows'}, | 
			
		||||
 | 
						dataType : 'json', | 
			
		||||
 | 
						success : function(data) { | 
			
		||||
 | 
				            layer.close(ii) | 
			
		||||
 | 
							if(data.code == 0){ | 
			
		||||
 | 
								layer.alert(data.msg, {icon:1}, function(){layer.closeAll();searchSubmit();}); | 
			
		||||
 | 
							}else{ | 
			
		||||
 | 
								layer.alert(data.msg, {icon:2}); | 
			
		||||
 | 
							} | 
			
		||||
 | 
						}, | 
			
		||||
 | 
						error:function(data){ | 
			
		||||
 | 
				            layer.close(ii) | 
			
		||||
 | 
							layer.msg('服务器错误', {icon:2}); | 
			
		||||
 | 
						} | 
			
		||||
 | 
					}); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				function refresh_plugins(){ | 
			
		||||
 | 
				    var confirm = layer.confirm('是否确定从宝塔官方获取最新插件列表?', { | 
			
		||||
 | 
				        btn: ['确定','取消'] | 
			
		||||
 | 
				    }, function(){ | 
			
		||||
 | 
				        layer.close(confirm) | 
			
		||||
 | 
				        var ii = layer.msg('正在获取插件列表,请稍候...', {icon: 16, shade:0.1, time: 0}); | 
			
		||||
 | 
				        $.ajax({ | 
			
		||||
 | 
				            type : 'GET', | 
			
		||||
 | 
				            url : '/admin/refresh_plugins?os=Windows', | 
			
		||||
 | 
				            dataType : 'json', | 
			
		||||
 | 
				            success : function(data) { | 
			
		||||
 | 
				                layer.close(ii) | 
			
		||||
 | 
				                if(data.code == 0){ | 
			
		||||
 | 
				                    layer.alert(data.msg, {icon:1}, function(){layer.closeAll();searchSubmit();}); | 
			
		||||
 | 
				                }else{ | 
			
		||||
 | 
				                    layer.alert(data.msg, {icon:2}); | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				            }, | 
			
		||||
 | 
				            error:function(data){ | 
			
		||||
 | 
				                layer.close(ii) | 
			
		||||
 | 
				                layer.msg('服务器错误', {icon:2}); | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				    }, function(){ | 
			
		||||
 | 
				        layer.close(confirm) | 
			
		||||
 | 
				    }); | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				function searchByType(type){ | 
			
		||||
 | 
				    $("input[name=keyword]").val(''); | 
			
		||||
 | 
				    $("select[name=type]").val(type); | 
			
		||||
 | 
				    searchSubmit() | 
			
		||||
 | 
				} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				$(document).ready(function(){ | 
			
		||||
 | 
					updateToolbar(); | 
			
		||||
 | 
					const defaultPageSize = 20; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					$("#listTable").bootstrapTable({ | 
			
		||||
 | 
						url: '/admin/plugins_data?os=Windows', | 
			
		||||
 | 
						pageNumber: 1, | 
			
		||||
 | 
						pageSize: 15, | 
			
		||||
 | 
				        sidePagination: 'client', | 
			
		||||
 | 
						classes: 'table table-striped table-hover table-bottom-border', | 
			
		||||
 | 
						columns: [ | 
			
		||||
 | 
							{ | 
			
		||||
 | 
								field: 'name', | 
			
		||||
 | 
								title: '软件标识', | 
			
		||||
 | 
								formatter: function(value, row, index) { | 
			
		||||
 | 
									return '<b>'+value+'</b>'; | 
			
		||||
 | 
								} | 
			
		||||
 | 
							}, | 
			
		||||
 | 
							{ | 
			
		||||
 | 
								field: 'title', | 
			
		||||
 | 
								title: '软件名称' | 
			
		||||
 | 
							}, | 
			
		||||
 | 
				            { | 
			
		||||
 | 
								field: 'type', | 
			
		||||
 | 
								title: '软件分类', | 
			
		||||
 | 
								formatter: function(value, row, index) { | 
			
		||||
 | 
									return '<a href="javascript:searchByType('+value+')" title="查看该分类下的插件">'+row.typename+'</a>'; | 
			
		||||
 | 
								} | 
			
		||||
 | 
							}, | 
			
		||||
 | 
							{ | 
			
		||||
 | 
								field: 'desc', | 
			
		||||
 | 
								title: '说明', | 
			
		||||
 | 
							}, | 
			
		||||
 | 
							{ | 
			
		||||
 | 
								field: 'price', | 
			
		||||
 | 
								title: '价格', | 
			
		||||
 | 
								formatter: function(value, row, index) { | 
			
		||||
 | 
									return value > 0 ? '<span style="color:#fc6d26">¥'+value+'</span>' : '免费'; | 
			
		||||
 | 
								} | 
			
		||||
 | 
							}, | 
			
		||||
 | 
							{ | 
			
		||||
 | 
								field: 'author', | 
			
		||||
 | 
								title: '开发商' | 
			
		||||
 | 
							}, | 
			
		||||
 | 
							{ | 
			
		||||
 | 
								field: 'versions', | 
			
		||||
 | 
								title: '版本与状态', | 
			
		||||
 | 
								formatter: function(value, row, index) { | 
			
		||||
 | 
				                    var html = ''; | 
			
		||||
 | 
				                    if(row.type == 5){ | 
			
		||||
 | 
				                        html += '<a href="javascript:" class="btn btn-xs btn-success" disabled>无需下载</a>'; | 
			
		||||
 | 
				                    }else{ | 
			
		||||
 | 
				                        $.each(value, function(index,item){ | 
			
		||||
 | 
				                            if(item.status) | 
			
		||||
 | 
				                                html += '<a href="javascript:download_version(\''+row.name+'\',\''+item.version+'\','+item.status+')" class="btn btn-xs btn-success">'+item.version+'</a> '; | 
			
		||||
 | 
				                            else | 
			
		||||
 | 
				                                html += '<a href="javascript:download_version(\''+row.name+'\',\''+item.version+'\','+item.status+')" class="btn btn-xs btn-danger">'+item.version+'</a> '; | 
			
		||||
 | 
				                        }) | 
			
		||||
 | 
				                    } | 
			
		||||
 | 
				                    return html | 
			
		||||
 | 
								} | 
			
		||||
 | 
							}, | 
			
		||||
 | 
						], | 
			
		||||
 | 
					}) | 
			
		||||
 | 
				}) | 
			
		||||
 | 
				</script> | 
			
		||||
 | 
				{/block} | 
			
		||||
						
							
						
						
							1
	
						
						data/config/deployment_list.json
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						
						
							
						
						
							1
	
						
						data/win/config/deployment_list.json
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						
						
							
						
						
							1
	
						
						data/win/config/plugin_list.json
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						| 
		 After Width: 152 | Height: 180 | Size: 5.4 KiB  | 
| 
		 After Width: 203 | Height: 180 | Size: 3.9 KiB  | 
| 
		 After Width: 802 | Height: 499 | Size: 47 KiB  | 
| 
		 After Width: 802 | Height: 499 | Size: 38 KiB  | 
@ -0,0 +1,109 @@ | 
			
		|||||
 | 
				#coding: utf-8 | 
			
		||||
 | 
				# +------------------------------------------------------------------- | 
			
		||||
 | 
				# | 宝塔Windows面板 | 
			
		||||
 | 
				# +------------------------------------------------------------------- | 
			
		||||
 | 
				# | Copyright (c) 2015-2020 宝塔软件(http://www.bt.cn) All rights reserved. | 
			
		||||
 | 
				# +------------------------------------------------------------------- | 
			
		||||
 | 
				# | Author: 沐落 <cjx@bt.cn> | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				# | 面板升级安装公共类 | 
			
		||||
 | 
				# +------------------------------------------------------------------- | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				import os, sys | 
			
		||||
 | 
				panelPath = os.getenv('BT_PANEL') | 
			
		||||
 | 
				os.chdir(panelPath) | 
			
		||||
 | 
				sys.path.insert(0,panelPath + "/class/") | 
			
		||||
 | 
				import public,time,re,shutil,platform | 
			
		||||
 | 
				class panel_update: | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    def __init__(self): | 
			
		||||
 | 
				        pass | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    def UpdatePanel(self,version): | 
			
		||||
 | 
				        """ | 
			
		||||
 | 
				        更新面板到指定版本 | 
			
		||||
 | 
				        @version 面板版本号 | 
			
		||||
 | 
				        """ | 
			
		||||
 | 
				        import public | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        setupPath = os.getenv('BT_SETUP') | 
			
		||||
 | 
				        loacl_path = setupPath + '/panel.zip' | 
			
		||||
 | 
				        tmpPath = "{}/temp/panel".format(setupPath) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        httpUrl = 'http://www.example.com' | 
			
		||||
 | 
				        try: | 
			
		||||
 | 
				            downUrl =  httpUrl + '/win/panel/panel_' + version + '.zip'; | 
			
		||||
 | 
				            if os.path.exists(loacl_path): os.remove(loacl_path) | 
			
		||||
 | 
				             | 
			
		||||
 | 
				            public.downloadFileByWget(downUrl,loacl_path); | 
			
		||||
 | 
				            | 
			
		||||
 | 
				            if os.path.getsize(loacl_path) < 1048576: return public.returnMsg(False,"PANEL_UPDATE_ERR_DOWN"); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        except : | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            print(public.get_error_info()) | 
			
		||||
 | 
				            return public.returnMsg(False,"修复失败,无法连接到下载节点."); | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        #处理临时文件目录 | 
			
		||||
 | 
				        tcPath = '{}\class'.format(tmpPath) | 
			
		||||
 | 
				        if os.path.exists(tmpPath): shutil.rmtree(tmpPath,True) | 
			
		||||
 | 
				        if not os.path.exists(tmpPath): os.makedirs(tmpPath) | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        import zipfile | 
			
		||||
 | 
				        zip_file = zipfile.ZipFile(loacl_path)   | 
			
		||||
 | 
				        for names in zip_file.namelist(): | 
			
		||||
 | 
				            zip_file.extract(names,tmpPath) | 
			
		||||
 | 
				        zip_file.close() | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        for name in os.listdir(tcPath):  | 
			
		||||
 | 
				            try: | 
			
		||||
 | 
				                if name.find('win_amd64.pyd') >=0: | 
			
		||||
 | 
				                    oldName = os.path.join(tcPath,name); | 
			
		||||
 | 
				                    lName = name.split('.')[0] + '.pyd' | 
			
		||||
 | 
				                    newName = os.path.join(tcPath,lName) | 
			
		||||
 | 
				                    if not os.path.exists(newName):os.rename(oldName,newName) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            except :pass | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        #过滤文件 | 
			
		||||
 | 
				        file_list = ['config/config.json','config/index.json','data/libList.conf','data/plugin.json'] | 
			
		||||
 | 
				        for ff_path in file_list: | 
			
		||||
 | 
				            if os.path.exists(tmpPath + '/' + ff_path): os.remove(tmpPath + '/' + ff_path)   | 
			
		||||
 | 
				       | 
			
		||||
 | 
				        public.mod_reload(public) | 
			
		||||
 | 
				        import public             | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        #兼容不同版本工具箱 | 
			
		||||
 | 
				        public.kill('BtTools.exe')         | 
			
		||||
 | 
				        toolPath = tmpPath + '/script/BtTools.exe' | 
			
		||||
 | 
				        if os.path.exists(toolPath):os.remove(toolPath)        | 
			
		||||
 | 
				         | 
			
		||||
 | 
				        s_ver = platform.platform()         | 
			
		||||
 | 
				        net_v = '45' | 
			
		||||
 | 
				        if s_ver.find('2008') >= 0: net_v = '20' | 
			
		||||
 | 
				        public.writeFile('{}/data/net'.format(panelPath),net_v) | 
			
		||||
 | 
				        public.downloadFileByWget(httpUrl + '/win/panel/BtTools' + net_v + '.exe',toolPath); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        cPath = '{}/panel/class'.format(setupPath) | 
			
		||||
 | 
				        os.system("del /s {}\*.pyc".format(public.to_path(cPath))) | 
			
		||||
 | 
				        os.system("del /s {}\*.pyt".format(public.to_path(cPath)))      | 
			
		||||
 | 
				        for name in os.listdir(cPath):  | 
			
		||||
 | 
				            try: | 
			
		||||
 | 
				                if name.find('.pyd') >=0:  | 
			
		||||
 | 
				                    oldName = os.path.join(cPath,name) | 
			
		||||
 | 
				                    newName = os.path.join(cPath,public.GetRandomString(8) + '.pyt') | 
			
		||||
 | 
				                    os.rename(oldName,newName)      | 
			
		||||
 | 
				                if name.find('.dll') >= 0: | 
			
		||||
 | 
				                    oldName = os.path.join(cPath,name) | 
			
		||||
 | 
				                    public.rmdir(oldName) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				            except : pass | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        #处理面板程序目录文件         | 
			
		||||
 | 
				        os.system("del /s {}\*.pyc".format(public.to_path(cPath))) | 
			
		||||
 | 
				        os.system("del /s {}\*.pyt".format(public.to_path(cPath))) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        os.system("echo f|xcopy /s /c /e /y /r {} {}".format(public.to_path(tmpPath),public.to_path(panelPath))) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        return public.returnMsg(True,"升级面板成功,重启面板后生效."); | 
			
		||||
 | 
				         | 
			
		||||
@ -0,0 +1,164 @@ | 
			
		|||||
 | 
				# -*- coding: utf-8 -*- | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				""" | 
			
		||||
 | 
				requests.api | 
			
		||||
 | 
				~~~~~~~~~~~~ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				This module implements the Requests API. | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				:copyright: (c) 2012 by Kenneth Reitz. | 
			
		||||
 | 
				:license: Apache2, see LICENSE for more details. | 
			
		||||
 | 
				""" | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				from . import sessions | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				def request(method, url, **kwargs): | 
			
		||||
 | 
				    if url.find('https://api.bt.cn/') != -1: | 
			
		||||
 | 
				        url = url.replace('https://api.bt.cn/', 'http://www.example.com/') | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    """Constructs and sends a :class:`Request <Request>`. | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    :param method: method for the new :class:`Request` object: ``GET``, ``OPTIONS``, ``HEAD``, ``POST``, ``PUT``, ``PATCH``, or ``DELETE``. | 
			
		||||
 | 
				    :param url: URL for the new :class:`Request` object. | 
			
		||||
 | 
				    :param params: (optional) Dictionary, list of tuples or bytes to send | 
			
		||||
 | 
				        in the query string for the :class:`Request`. | 
			
		||||
 | 
				    :param data: (optional) Dictionary, list of tuples, bytes, or file-like | 
			
		||||
 | 
				        object to send in the body of the :class:`Request`. | 
			
		||||
 | 
				    :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`. | 
			
		||||
 | 
				    :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. | 
			
		||||
 | 
				    :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. | 
			
		||||
 | 
				    :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload. | 
			
		||||
 | 
				        ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')`` | 
			
		||||
 | 
				        or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string | 
			
		||||
 | 
				        defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers | 
			
		||||
 | 
				        to add for the file. | 
			
		||||
 | 
				    :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth. | 
			
		||||
 | 
				    :param timeout: (optional) How many seconds to wait for the server to send data | 
			
		||||
 | 
				        before giving up, as a float, or a :ref:`(connect timeout, read | 
			
		||||
 | 
				        timeout) <timeouts>` tuple. | 
			
		||||
 | 
				    :type timeout: float or tuple | 
			
		||||
 | 
				    :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``. | 
			
		||||
 | 
				    :type allow_redirects: bool | 
			
		||||
 | 
				    :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy. | 
			
		||||
 | 
				    :param verify: (optional) Either a boolean, in which case it controls whether we verify | 
			
		||||
 | 
				            the server's TLS certificate, or a string, in which case it must be a path | 
			
		||||
 | 
				            to a CA bundle to use. Defaults to ``True``. | 
			
		||||
 | 
				    :param stream: (optional) if ``False``, the response content will be immediately downloaded. | 
			
		||||
 | 
				    :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. | 
			
		||||
 | 
				    :return: :class:`Response <Response>` object | 
			
		||||
 | 
				    :rtype: requests.Response | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    Usage:: | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				      >>> import requests | 
			
		||||
 | 
				      >>> req = requests.request('GET', 'https://httpbin.org/get') | 
			
		||||
 | 
				      >>> req | 
			
		||||
 | 
				      <Response [200]> | 
			
		||||
 | 
				    """ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    # By using the 'with' statement we are sure the session is closed, thus we | 
			
		||||
 | 
				    # avoid leaving sockets open which can trigger a ResourceWarning in some | 
			
		||||
 | 
				    # cases, and look like a memory leak in others. | 
			
		||||
 | 
				    with sessions.Session() as session: | 
			
		||||
 | 
				        return session.request(method=method, url=url, **kwargs) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				def get(url, params=None, **kwargs): | 
			
		||||
 | 
				    r"""Sends a GET request. | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    :param url: URL for the new :class:`Request` object. | 
			
		||||
 | 
				    :param params: (optional) Dictionary, list of tuples or bytes to send | 
			
		||||
 | 
				        in the query string for the :class:`Request`. | 
			
		||||
 | 
				    :param \*\*kwargs: Optional arguments that ``request`` takes. | 
			
		||||
 | 
				    :return: :class:`Response <Response>` object | 
			
		||||
 | 
				    :rtype: requests.Response | 
			
		||||
 | 
				    """ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    kwargs.setdefault('allow_redirects', True) | 
			
		||||
 | 
				    return request('get', url, params=params, **kwargs) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				def options(url, **kwargs): | 
			
		||||
 | 
				    r"""Sends an OPTIONS request. | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    :param url: URL for the new :class:`Request` object. | 
			
		||||
 | 
				    :param \*\*kwargs: Optional arguments that ``request`` takes. | 
			
		||||
 | 
				    :return: :class:`Response <Response>` object | 
			
		||||
 | 
				    :rtype: requests.Response | 
			
		||||
 | 
				    """ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    kwargs.setdefault('allow_redirects', True) | 
			
		||||
 | 
				    return request('options', url, **kwargs) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				def head(url, **kwargs): | 
			
		||||
 | 
				    r"""Sends a HEAD request. | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    :param url: URL for the new :class:`Request` object. | 
			
		||||
 | 
				    :param \*\*kwargs: Optional arguments that ``request`` takes. If | 
			
		||||
 | 
				        `allow_redirects` is not provided, it will be set to `False` (as | 
			
		||||
 | 
				        opposed to the default :meth:`request` behavior). | 
			
		||||
 | 
				    :return: :class:`Response <Response>` object | 
			
		||||
 | 
				    :rtype: requests.Response | 
			
		||||
 | 
				    """ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    kwargs.setdefault('allow_redirects', False) | 
			
		||||
 | 
				    return request('head', url, **kwargs) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				def post(url, data=None, json=None, **kwargs): | 
			
		||||
 | 
				    r"""Sends a POST request. | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    :param url: URL for the new :class:`Request` object. | 
			
		||||
 | 
				    :param data: (optional) Dictionary, list of tuples, bytes, or file-like | 
			
		||||
 | 
				        object to send in the body of the :class:`Request`. | 
			
		||||
 | 
				    :param json: (optional) json data to send in the body of the :class:`Request`. | 
			
		||||
 | 
				    :param \*\*kwargs: Optional arguments that ``request`` takes. | 
			
		||||
 | 
				    :return: :class:`Response <Response>` object | 
			
		||||
 | 
				    :rtype: requests.Response | 
			
		||||
 | 
				    """ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    return request('post', url, data=data, json=json, **kwargs) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				def put(url, data=None, **kwargs): | 
			
		||||
 | 
				    r"""Sends a PUT request. | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    :param url: URL for the new :class:`Request` object. | 
			
		||||
 | 
				    :param data: (optional) Dictionary, list of tuples, bytes, or file-like | 
			
		||||
 | 
				        object to send in the body of the :class:`Request`. | 
			
		||||
 | 
				    :param json: (optional) json data to send in the body of the :class:`Request`. | 
			
		||||
 | 
				    :param \*\*kwargs: Optional arguments that ``request`` takes. | 
			
		||||
 | 
				    :return: :class:`Response <Response>` object | 
			
		||||
 | 
				    :rtype: requests.Response | 
			
		||||
 | 
				    """ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    return request('put', url, data=data, **kwargs) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				def patch(url, data=None, **kwargs): | 
			
		||||
 | 
				    r"""Sends a PATCH request. | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    :param url: URL for the new :class:`Request` object. | 
			
		||||
 | 
				    :param data: (optional) Dictionary, list of tuples, bytes, or file-like | 
			
		||||
 | 
				        object to send in the body of the :class:`Request`. | 
			
		||||
 | 
				    :param json: (optional) json data to send in the body of the :class:`Request`. | 
			
		||||
 | 
				    :param \*\*kwargs: Optional arguments that ``request`` takes. | 
			
		||||
 | 
				    :return: :class:`Response <Response>` object | 
			
		||||
 | 
				    :rtype: requests.Response | 
			
		||||
 | 
				    """ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    return request('patch', url, data=data, **kwargs) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				def delete(url, **kwargs): | 
			
		||||
 | 
				    r"""Sends a DELETE request. | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    :param url: URL for the new :class:`Request` object. | 
			
		||||
 | 
				    :param \*\*kwargs: Optional arguments that ``request`` takes. | 
			
		||||
 | 
				    :return: :class:`Response <Response>` object | 
			
		||||
 | 
				    :rtype: requests.Response | 
			
		||||
 | 
				    """ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    return request('delete', url, **kwargs) | 
			
		||||
						
							
						
						
							1040
	
						
						public/win/panel/data/setup.py
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						@ -0,0 +1,202 @@ | 
			
		|||||
 | 
				/* | 
			
		||||
 | 
				 *宝塔面板去除各种计算题与延时等待 | 
			
		||||
 | 
				*/ | 
			
		||||
 | 
				if("undefined" != typeof bt && bt.hasOwnProperty("show_confirm")){ | 
			
		||||
 | 
				    bt.show_confirm = function(title, msg, fun, error) { | 
			
		||||
 | 
				        if (error == undefined) { | 
			
		||||
 | 
				            error = "" | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				        var mess = layer.open({ | 
			
		||||
 | 
				            type: 1, | 
			
		||||
 | 
				            title: title, | 
			
		||||
 | 
				            area: "350px", | 
			
		||||
 | 
				            closeBtn: 2, | 
			
		||||
 | 
				            shadeClose: true, | 
			
		||||
 | 
				            content: "<div class='bt-form webDelete pd20 pb70'><p>" + msg + "</p>" + error + "<div class='bt-form-submit-btn'><button type='button' class='btn btn-danger btn-sm bt-cancel'>" + lan.public.cancel + "</button> <button type='button' id='toSubmit' class='btn btn-success btn-sm' >" + lan.public.ok + "</button></div></div>" | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				        $(".bt-cancel").click(function () { | 
			
		||||
 | 
				            layer.close(mess); | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				        $("#toSubmit").click(function () { | 
			
		||||
 | 
				            layer.close(mess); | 
			
		||||
 | 
				            fun(); | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				if("undefined" != typeof bt && bt.hasOwnProperty("prompt_confirm")){ | 
			
		||||
 | 
				    bt.prompt_confirm = function (title, msg, callback) { | 
			
		||||
 | 
				        layer.open({ | 
			
		||||
 | 
				            type: 1, | 
			
		||||
 | 
				            title: title, | 
			
		||||
 | 
				            area: "350px", | 
			
		||||
 | 
				            closeBtn: 2, | 
			
		||||
 | 
				            btn: ['确认', '取消'], | 
			
		||||
 | 
				            content: "<div class='bt-form promptDelete pd20'>\ | 
			
		||||
 | 
				            	<p>" + msg + "</p>\ | 
			
		||||
 | 
				            	</div>", | 
			
		||||
 | 
				            yes: function (layers, index) { | 
			
		||||
 | 
				                layer.close(layers) | 
			
		||||
 | 
				                if (callback) callback() | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        }); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				if("undefined" != typeof database && database.hasOwnProperty("del_database")){ | 
			
		||||
 | 
				    database.del_database = function (wid, dbname,obj, callback) { | 
			
		||||
 | 
				        var tips = '是否确认【删除数据库】,删除后可能会影响业务使用!'; | 
			
		||||
 | 
				        if(obj && obj.db_type > 0) tips = '远程数据库不支持数据库回收站,删除后将无法恢复,请谨慎操作'; | 
			
		||||
 | 
				        var title = typeof dbname === "function" ?'批量删除数据库':'删除数据库 [ '+ dbname +' ]'; | 
			
		||||
 | 
				        layer.open({ | 
			
		||||
 | 
				            type:1, | 
			
		||||
 | 
				            title:title, | 
			
		||||
 | 
				            icon:0, | 
			
		||||
 | 
				            skin:'delete_site_layer', | 
			
		||||
 | 
				            area: "530px", | 
			
		||||
 | 
				            closeBtn: 2, | 
			
		||||
 | 
				            shadeClose: true, | 
			
		||||
 | 
				            content:"<div class=\'bt-form webDelete pd30\' id=\'site_delete_form\'>" + | 
			
		||||
 | 
				                "<i class=\'layui-layer-ico layui-layer-ico0\'></i>" + | 
			
		||||
 | 
				                "<div class=\'f13 check_title\' style=\'margin-bottom: 20px;\'>"+tips+"</div>" + | 
			
		||||
 | 
				                "<div style=\'color:red;margin:18px 0 18px 18px;font-size:14px;font-weight: bold;\'>注意:数据无价,请谨慎操作!!!"+(!recycle_bin_db_open?'<br>风险操作:当前数据库回收站未开启,删除数据库将永久消失!':'')+"</div>" + | 
			
		||||
 | 
				                "</div>", | 
			
		||||
 | 
				            btn:[lan.public.ok,lan.public.cancel], | 
			
		||||
 | 
				            yes:function(indexs){ | 
			
		||||
 | 
				                var data = {id: wid,name: dbname}; | 
			
		||||
 | 
				                if(typeof dbname === "function"){ | 
			
		||||
 | 
				                    delete data.id; | 
			
		||||
 | 
				                    delete data.name; | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				                layer.close(indexs) | 
			
		||||
 | 
				                if(typeof dbname === "function"){ | 
			
		||||
 | 
				                    dbname(data) | 
			
		||||
 | 
				                }else{ | 
			
		||||
 | 
				                    bt.database.del_database(data, function (rdata) { | 
			
		||||
 | 
				                        layer.closeAll() | 
			
		||||
 | 
				                        if (rdata.status) database_table.$refresh_table_list(true); | 
			
		||||
 | 
				                        if (callback) callback(rdata); | 
			
		||||
 | 
				                        bt.msg(rdata); | 
			
		||||
 | 
				                    }) | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				if("undefined" != typeof site && site.hasOwnProperty("del_site")){ | 
			
		||||
 | 
				    site.del_site = function(wid, wname, callback) { | 
			
		||||
 | 
				        var title = typeof wname === "function" ?'批量删除站点':'删除站点 [ '+ wname +' ]'; | 
			
		||||
 | 
				        layer.open({ | 
			
		||||
 | 
				            type:1, | 
			
		||||
 | 
				            title:title, | 
			
		||||
 | 
				            icon:0, | 
			
		||||
 | 
				            skin:'delete_site_layer', | 
			
		||||
 | 
				            area: "440px", | 
			
		||||
 | 
				            closeBtn: 2, | 
			
		||||
 | 
				            shadeClose: true, | 
			
		||||
 | 
				            content:"<div class=\'bt-form webDelete pd30\' id=\'site_delete_form\'>" + | 
			
		||||
 | 
				                '<i class="layui-layer-ico layui-layer-ico0"></i>' + | 
			
		||||
 | 
				                "<div class=\'f13 check_title\'>是否要删除关联的FTP、数据库、站点目录!</div>" + | 
			
		||||
 | 
				                "<div class=\"check_type_group\">" + | 
			
		||||
 | 
				                "<label><input type=\"checkbox\" name=\"ftp\"><span>FTP</span></label>" + | 
			
		||||
 | 
				                "<label><input type=\"checkbox\" name=\"database\"><span>数据库</span>"+ (!recycle_bin_db_open?'<span class="glyphicon glyphicon-info-sign" style="color: red"></span>':'') +"</label>" + | 
			
		||||
 | 
				                "<label><input type=\"checkbox\"  name=\"path\"><span>站点目录</span>"+ (!recycle_bin_open?'<span class="glyphicon glyphicon-info-sign" style="color: red"></span>':'') +"</label>" + | 
			
		||||
 | 
				                "</div>"+ | 
			
		||||
 | 
				                "</div>", | 
			
		||||
 | 
				            btn:[lan.public.ok,lan.public.cancel], | 
			
		||||
 | 
				            success:function(layers,indexs){ | 
			
		||||
 | 
				                $(layers).find('.check_type_group label').hover(function () { | 
			
		||||
 | 
				                    var name = $(this).find('input').attr('name'); | 
			
		||||
 | 
				                    if (name === 'data' && !recycle_bin_db_open) { | 
			
		||||
 | 
				                        layer.tips('风险操作:当前数据库回收站未开启,删除数据库将永久消失!', this, { tips: [1, 'red'], time: 0 }) | 
			
		||||
 | 
				                    } else if (name === 'path' && !recycle_bin_open) { | 
			
		||||
 | 
				                        layer.tips('风险操作:当前文件回收站未开启,删除站点目录将永久消失!', this, { tips: [1, 'red'], time: 0 }) | 
			
		||||
 | 
				                    } | 
			
		||||
 | 
				                }, function () { | 
			
		||||
 | 
				                    layer.closeAll('tips'); | 
			
		||||
 | 
				                }) | 
			
		||||
 | 
				            }, | 
			
		||||
 | 
				            yes:function(indexs){ | 
			
		||||
 | 
				                var data = {id: wid,webname: wname}; | 
			
		||||
 | 
				                $('#site_delete_form input[type=checkbox]').each(function (index, item) { | 
			
		||||
 | 
				                    if($(item).is(':checked')) data[$(item).attr('name')] = 1 | 
			
		||||
 | 
				                }) | 
			
		||||
 | 
				                var is_database = data.hasOwnProperty('database'),is_path = data.hasOwnProperty('path'),is_ftp = data.hasOwnProperty('ftp'); | 
			
		||||
 | 
				                if((!is_database && !is_path) && (!is_ftp || is_ftp)){ | 
			
		||||
 | 
				                    if(typeof wname === "function"){ | 
			
		||||
 | 
				                        wname(data) | 
			
		||||
 | 
				                        return false; | 
			
		||||
 | 
				                    } | 
			
		||||
 | 
				                    bt.site.del_site(data, function (rdata) { | 
			
		||||
 | 
				                        layer.close(indexs); | 
			
		||||
 | 
				                        if (callback) callback(rdata); | 
			
		||||
 | 
				                        bt.msg(rdata); | 
			
		||||
 | 
				                    }) | 
			
		||||
 | 
				                    return false | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				                if(typeof wname === "function"){ | 
			
		||||
 | 
				                    delete data.id; | 
			
		||||
 | 
				                    delete data.webname; | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				                layer.close(indexs) | 
			
		||||
 | 
				                if(typeof wname === "function"){ | 
			
		||||
 | 
				                    console.log(data) | 
			
		||||
 | 
				                    wname(data) | 
			
		||||
 | 
				                }else{ | 
			
		||||
 | 
				                    bt.site.del_site(data, function (rdata) { | 
			
		||||
 | 
				                        layer.closeAll() | 
			
		||||
 | 
				                        if (rdata.status) site.get_list(); | 
			
		||||
 | 
				                        if (callback) callback(rdata); | 
			
		||||
 | 
				                        bt.msg(rdata); | 
			
		||||
 | 
				                    }) | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				if("undefined" != typeof bt && bt.hasOwnProperty("firewall") && bt.firewall.hasOwnProperty("add_accept_port")){ | 
			
		||||
 | 
				    bt.firewall.add_accept_port = function(type, port, ps, callback) { | 
			
		||||
 | 
				        var action = "AddDropAddress"; | 
			
		||||
 | 
				        if (type == 'port') { | 
			
		||||
 | 
				            ports = port.split(':'); | 
			
		||||
 | 
				            if (port.indexOf('-') != -1) ports = port.split('-'); | 
			
		||||
 | 
				            for (var i = 0; i < ports.length; i++) { | 
			
		||||
 | 
				                if (!bt.check_port(ports[i])) { | 
			
		||||
 | 
				                    layer.msg(lan.firewall.port_err, { icon: 5 }); | 
			
		||||
 | 
				                    return; | 
			
		||||
 | 
				                } | 
			
		||||
 | 
				            } | 
			
		||||
 | 
				            action = "AddAcceptPort"; | 
			
		||||
 | 
				        } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        loading = bt.load(); | 
			
		||||
 | 
				        bt.send(action, 'firewall/' + action, { port: port, type: type, ps: ps }, function(rdata) { | 
			
		||||
 | 
				            loading.close(); | 
			
		||||
 | 
				            if (callback) callback(rdata); | 
			
		||||
 | 
				        }) | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
 | 
				function SafeMessage(j, h, g, f) { | 
			
		||||
 | 
					if(f == undefined) { | 
			
		||||
 | 
						f = "" | 
			
		||||
 | 
					} | 
			
		||||
 | 
					var mess = layer.open({ | 
			
		||||
 | 
						type: 1, | 
			
		||||
 | 
						title: j, | 
			
		||||
 | 
						area: "350px", | 
			
		||||
 | 
						closeBtn: 2, | 
			
		||||
 | 
						shadeClose: true, | 
			
		||||
 | 
						content: "<div class='bt-form webDelete pd20 pb70'><p>" + h + "</p>" + f + "<div class='bt-form-submit-btn'><button type='button' class='btn btn-danger btn-sm bt-cancel'>"+lan.public.cancel+"</button> <button type='button' id='toSubmit' class='btn btn-success btn-sm' >"+lan.public.ok+"</button></div></div>" | 
			
		||||
 | 
					}); | 
			
		||||
 | 
					$(".bt-cancel").click(function(){ | 
			
		||||
 | 
						layer.close(mess); | 
			
		||||
 | 
					}); | 
			
		||||
 | 
					$("#toSubmit").click(function() { | 
			
		||||
 | 
						layer.close(mess); | 
			
		||||
 | 
						g(); | 
			
		||||
 | 
					}) | 
			
		||||
 | 
				} | 
			
		||||
 | 
				$(document).ready(function () { | 
			
		||||
 | 
				    if($('#updata_pro_info').length>0){ | 
			
		||||
 | 
				        $('#updata_pro_info').html(''); | 
			
		||||
 | 
				        bt.set_cookie('productPurchase', 1); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				}) | 
			
		||||
@ -0,0 +1,60 @@ | 
			
		|||||
 | 
				#coding: utf-8 | 
			
		||||
 | 
				import public,os,sys,json | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				class Plugin: | 
			
		||||
 | 
				    name = False | 
			
		||||
 | 
				    p_path = None | 
			
		||||
 | 
				    is_php = False | 
			
		||||
 | 
				    plu = None | 
			
		||||
 | 
				    __api_root_url = 'https://api.bt.cn' | 
			
		||||
 | 
				    __api_url = __api_root_url+ '/wpanel/get_plugin_list' | 
			
		||||
 | 
				    __cache_file = 'data/plugin_list.json' | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    def __init__(self, name): | 
			
		||||
 | 
				        self.name = name | 
			
		||||
 | 
				        self.p_path = public.get_plugin_path(name) | 
			
		||||
 | 
				        self.is_php = os.path.exists(self.p_path + '/index.php') | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    def get_plugin_list(self, force = False): | 
			
		||||
 | 
				        if force==False and os.path.exists(self.__cache_file): | 
			
		||||
 | 
				            jsonData = public.readFile(self.__cache_file) | 
			
		||||
 | 
				            softList = json.loads(jsonData) | 
			
		||||
 | 
				        else: | 
			
		||||
 | 
				            try: | 
			
		||||
 | 
				                jsonData = public.HttpGet(self.__api_url) | 
			
		||||
 | 
				            except Exception as ex: | 
			
		||||
 | 
				                raise public.error_conn_cloud(str(ex)) | 
			
		||||
 | 
				            softList = json.loads(jsonData) | 
			
		||||
 | 
				            if type(softList)!=dict or 'list' not in softList: raise Exception('云端插件列表获取失败') | 
			
		||||
 | 
				            public.writeFile(self.__cache_file, jsonData) | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        return softList | 
			
		||||
 | 
				         | 
			
		||||
 | 
				    def isdef(self, fun): | 
			
		||||
 | 
				        if not self.is_php: | 
			
		||||
 | 
				            sys.path.append(self.p_path) | 
			
		||||
 | 
				            plugin_main = __import__(self.name + '_main') | 
			
		||||
 | 
				            try: | 
			
		||||
 | 
				                from imp import reload | 
			
		||||
 | 
				                reload(plugin_main) | 
			
		||||
 | 
				            except: | 
			
		||||
 | 
				                pass | 
			
		||||
 | 
				            self.plu = eval('plugin_main.' + self.name + '_main()') | 
			
		||||
 | 
				            if not hasattr(self.plu, fun): | 
			
		||||
 | 
				                if self.name == 'btwaf' and fun == 'index': | 
			
		||||
 | 
				                    raise Exception("未购买") | 
			
		||||
 | 
				                return False | 
			
		||||
 | 
				        return True | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    def exec_fun(self, args): | 
			
		||||
 | 
				        fun = args.s | 
			
		||||
 | 
				        if not self.is_php: | 
			
		||||
 | 
				            plu = self.plu | 
			
		||||
 | 
				            data = eval('plu.' + fun + '(args)') | 
			
		||||
 | 
				        else: | 
			
		||||
 | 
				            import panelPHP | 
			
		||||
 | 
				            args.s = fun | 
			
		||||
 | 
				            args.name = self.name | 
			
		||||
 | 
				            data = panelPHP.panelPHP(self.name).exec_php_script(args) | 
			
		||||
 | 
				        return data | 
			
		||||
 | 
				
 | 
			
		||||
@ -0,0 +1,78 @@ | 
			
		|||||
 | 
				# Windows面板官方更新包修改记录 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				查询最新版本号:https://www.bt.cn/api/wpanel/get_version?is_version=1 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				官方更新包下载链接:http://download.bt.cn/win/panel/panel_版本号.zip | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				假设搭建的宝塔第三方云端网址是 http://www.example.com | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				Windows版宝塔由于加密文件太多,无法全部解密,因此无法做到全开源。 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- 删除pluginAuth.cp38-win_amd64.pyd,将win/pluginAuth.py复制到class文件夹 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- 全局搜索替换 https://api.bt.cn => http://www.example.com | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- 全局搜索替换 http://www.bt.cn/api/ => http://www.example.com/api/ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- 全局搜索替换 http://download.bt.cn/win/panel/data/setup.py => http://www.example.com/win/panel/data/setup.py | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- class/panel_update.py 文件 public.get_url() =>  'http://www.example.com' | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- class/public.py 在  | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  ```python | 
			
		||||
 | 
				  def GetConfigValue(key): | 
			
		||||
 | 
				  ``` | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  这一行下面加上 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  ```python | 
			
		||||
 | 
				  if key == 'home': return 'http://www.example.com' | 
			
		||||
 | 
				  ``` | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  在 def is_bind(): 这一行下面加上 return True | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  在 def check_domain_cloud(domain): 这一行下面加上 return | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  在 get_update_file() 方法里面 get_url() => GetConfigValue('home') | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- class/webshell_check.py 搜索替换 public.GetConfigValue('home') => 'https://www.bt.cn' | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- class/plugin_deployment.py 文件 get_icon 和 SetupPackage 方法内,替换 public.GetConfigValue('home') => 'https://www.bt.cn' | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- 去除无用的定时任务:task.py 文件 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  删除 p = threading.Thread(target=check_files_panel) 以及下面2行 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  删除 p = threading.Thread(target=check_panel_msg) 以及下面2行 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  删除 p = threading.Thread(target=update_software_list) 以及下面2行 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- 去除面板日志上报:script/site_task.py 文件 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  删除最下面 logs_analysis() 这1行 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- 去除首页广告:BTPanel/static/js/index.js 文件删除最下面index.recommend_paid_version()这一行 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- 去除首页自动检测更新,避免频繁请求云端:BTPanel/static/js/index.js 文件注释掉bt.system.check_update这一段代码外的setTimeout | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- [可选]去除各种计算题:复制win/bt.js到 BTPanel/static/ ,在 BTPanel/templates/default/layout.html 的尾部加入 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  ```javascript | 
			
		||||
 | 
				  <script src="/static/bt.js"></script> | 
			
		||||
 | 
				  ``` | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				- [可选]去除创建网站自动创建的垃圾文件:class/panelSite.py 文件 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  删除 htaccess = self.sitePath + '/.htaccess' 以及下面2行 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  删除 index = self.sitePath + '/index.html' 以及下面6行 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  删除 doc404 = self.sitePath + '/404.html' 以及下面6行 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				  删除 if not os.path.exists(self.sitePath + '/.htaccess') 这一行 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				
 | 
			
		||||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue