diff --git a/plugins/lam/conf/lam.conf b/plugins/lam/conf/lam.conf new file mode 100755 index 000000000..da5c9a3b2 --- /dev/null +++ b/plugins/lam/conf/lam.conf @@ -0,0 +1,38 @@ +server +{ + listen 888; + server_name 127.0.0.1; + index index.html index.htm index.php; + root {$SERVER_PATH}/lam; + + #error_page 404 /404.html; + include {$PHP_CONF_PATH}/enable-php-{$PHP_VER}.conf; + + #AUTH_START + auth_basic "Authorization"; + auth_basic_user_file {$SERVER_PATH}/lam/pma.pass; + #AUTH_END + + location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ + { + expires 30d; + } + + location ~ .*\.(js|css)?$ + { + expires 12h; + } + + location ~ /.*\.(log|pass|json|pl)$ { + deny all; + } + + + location ~ /\. + { + deny all; + } + + access_log {$SERVER_PATH}/lam/access.log; + error_log {$SERVER_PATH}/lam/error.log; +} \ No newline at end of file diff --git a/plugins/lam/ico.png b/plugins/lam/ico.png new file mode 100644 index 000000000..656b43efb Binary files /dev/null and b/plugins/lam/ico.png differ diff --git a/plugins/lam/index.html b/plugins/lam/index.html new file mode 100755 index 000000000..712f00e77 --- /dev/null +++ b/plugins/lam/index.html @@ -0,0 +1,24 @@ +
+
+
+

服务

+

重写模版

+

主页

+

PHP版本

+

安全设置

+

访问日志

+

错误日志

+

配置

+
+
+
+
+
+ +
+ \ No newline at end of file diff --git a/plugins/lam/index.py b/plugins/lam/index.py new file mode 100755 index 000000000..f0cfb11b4 --- /dev/null +++ b/plugins/lam/index.py @@ -0,0 +1,517 @@ +# coding:utf-8 + +import sys +import io +import os +import time +import re +import json + +web_dir = os.getcwd() + "/web" +if os.path.exists(web_dir): + sys.path.append(web_dir) + os.chdir(web_dir) + +import core.mw as mw +import thisdb +from utils.site import sites as MwSites + +app_debug = False +if mw.isAppleSystem(): + app_debug = True + + +def getPluginName(): + return 'lam' + + +def getPluginDir(): + return mw.getPluginDir() + '/' + getPluginName() + + +def getServerDir(): + return mw.getServerDir() + '/' + getPluginName() + + +def getArgs(): + args = sys.argv[2:] + tmp = {} + args_len = len(args) + + if args_len == 1: + t = args[0].strip('{').strip('}') + t = t.split(':') + tmp[t[0]] = t[1] + elif args_len > 1: + for i in range(len(args)): + t = args[i].split(':') + tmp[t[0]] = t[1] + + return tmp + + +def checkArgs(data, ck=[]): + for i in range(len(ck)): + if not ck[i] in data: + return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!')) + return (True, mw.returnJson(True, 'ok')) + + +def getConf(): + return mw.getServerDir() + '/web_conf/nginx/vhost/lam.conf' + + +def getConfInc(): + return getServerDir() + "/" + getCfg()['path'] + '/config/config.php' + + +def getPort(): + file = getConf() + content = mw.readFile(file) + rep = r'listen\s*(.*);' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + +def getHomePage(): + try: + port = getPort() + ip = '127.0.0.1' + if not mw.isAppleSystem(): + ip = mw.getLocalIp() + + cfg = getCfg() + auth = cfg['username']+':'+cfg['password'] + rand_path = cfg['path'] + url = 'http://' + auth + '@' + ip + ':' + port + '/' + rand_path + '/index.php' + return mw.returnJson(True, 'OK', url) + except Exception as e: + return mw.returnJson(False, '插件未启动!') + + +def getPhpVer(expect=74): + php_vers = MwSites.instance().getPhpVersion() + v = php_vers['data'] + is_find = False + for i in range(len(v)): + t = str(v[i]['version']) + if (t == expect): + is_find = True + return str(t) + if not is_find: + if len(v) > 1: + return v[1]['version'] + return v[0]['version'] + return str(expect) + + +def getCachePhpVer(): + cacheFile = getServerDir() + '/php.pl' + v = '' + if os.path.exists(cacheFile): + v = mw.readFile(cacheFile) + else: + v = getPhpVer() + mw.writeFile(cacheFile, v) + return v + + +def contentReplace(content): + service_path = mw.getServerDir() + php_ver = getCachePhpVer() + tmp = mw.execShell('cat /dev/urandom | head -n 32 | md5sum | head -c 16') + blowfish_secret = tmp[0].strip() + # print php_ver + php_conf_dir = mw.getServerDir() + '/web_conf/php/conf' + content = content.replace('{$ROOT_PATH}', mw.getFatherDir()) + content = content.replace('{$SERVER_PATH}', service_path) + content = content.replace('{$PHP_CONF_PATH}', php_conf_dir) + content = content.replace('{$PHP_VER}', php_ver) + content = content.replace('{$BLOWFISH_SECRET}', blowfish_secret) + + cfg = getCfg() + + if cfg['choose'] == "mysql": + content = content.replace('{$CHOOSE_DB}', 'mysql') + content = content.replace('{$CHOOSE_DB_DIR}', 'mysql') + elif cfg['choose'] == "mysql-community": + content = content.replace('{$CHOOSE_DB}', 'mysql-community') + content = content.replace('{$CHOOSE_DB_DIR}', 'mysql-community') + elif cfg['choose'] == "mysql-apt": + content = content.replace('{$CHOOSE_DB}', 'mysql') + content = content.replace('{$CHOOSE_DB_DIR}', 'mysql-apt') + elif cfg['choose'] == "mysql-yum": + content = content.replace('{$CHOOSE_DB}', 'mysql') + content = content.replace('{$CHOOSE_DB_DIR}', 'mysql-yum') + else: + content = content.replace('{$CHOOSE_DB}', 'MariaDB') + content = content.replace('{$CHOOSE_DB_DIR}', 'mariadb') + + content = content.replace('{$PMA_PATH}', cfg['path']) + + port = cfg["port"] + rep = r'listen\s*(.*);' + content = re.sub(rep, "listen " + port + ';', content) + return content + + +def initCfg(): + cfg = getServerDir() + "/cfg.json" + if not os.path.exists(cfg): + data = {} + data['port'] = '989' + data['choose'] = 'mysql' + data['path'] = '' + data['username'] = 'admin' + data['password'] = 'admin' + mw.writeFile(cfg, json.dumps(data)) + + +def setCfg(key, val): + cfg = getServerDir() + "/cfg.json" + data = mw.readFile(cfg) + data = json.loads(data) + data[key] = val + mw.writeFile(cfg, json.dumps(data)) + + +def getCfg(): + cfg = getServerDir() + "/cfg.json" + data = mw.readFile(cfg) + data = json.loads(data) + return data + + +def returnCfg(): + cfg = getServerDir() + "/cfg.json" + data = mw.readFile(cfg) + return data + + +def status(): + conf = getConf() + conf_inc = getServerDir() + "/" + getCfg()["path"] + '/config/config.php' + # 两个文件都在,才算启动成功 + if os.path.exists(conf) and os.path.exists(conf_inc): + return 'start' + return 'stop' + + +def __release_port(port): + from collections import namedtuple + try: + from utils.firewall import Firewall as MwFirewall + MwFirewall.instance().addAcceptPort(port, 'LAM默认端口', 'port') + return port + except Exception as e: + return "Release failed {}".format(e) + + +def __delete_port(port): + from collections import namedtuple + try: + from utils.firewall import Firewall as MwFirewall + MwFirewall.instance().delAcceptPortCmd(port, 'tcp') + return port + except Exception as e: + return "Release failed {}".format(e) + + +def openPort(): + conf = getCfg() + port = conf['port'] + for i in [port]: + __release_port(i) + return True + + +def delPort(): + conf = getCfg() + port = conf['port'] + for i in [port]: + __delete_port(i) + return True + + +def start(): + initCfg() + openPort() + + pma_dir = getServerDir() + "/lam" + if os.path.exists(pma_dir): + rand_str = mw.getRandomString(6) + rand_str = rand_str.lower() + pma_dir_dst = pma_dir + "_" + rand_str + mw.execShell("mv " + pma_dir + " " + pma_dir_dst) + setCfg('path', 'lam_' + rand_str) + + file_tpl = getPluginDir() + '/conf/lam.conf' + file_run = getConf() + if not os.path.exists(file_run): + centent = mw.readFile(file_tpl) + centent = contentReplace(centent) + mw.writeFile(file_run, centent) + + pma_path = getServerDir() + '/pma.pass' + if not os.path.exists(pma_path): + username = mw.getRandomString(8) + password = mw.getRandomString(10) + pass_cmd = username + ':' + mw.hasPwd(password) + setCfg('username', username) + setCfg('password', password) + mw.writeFile(pma_path, pass_cmd) + + tmp = getServerDir() + "/" + getCfg()["path"] + '/tmp' + if not os.path.exists(tmp): + os.mkdir(tmp) + mw.execShell("chown -R www:www " + tmp) + + conf_run = getServerDir() + "/" + getCfg()["path"] + '/config/config.php' + if not os.path.exists(conf_run): + conf_tpl = getPluginDir() + '/conf/config.php' + centent = mw.readFile(conf_tpl) + centent = contentReplace(centent) + mw.writeFile(conf_run, centent) + + log_a = accessLog() + log_e = errorLog() + + for i in [log_a, log_e]: + if os.path.exists(i): + cmd = "echo '' > " + i + mw.execShell(cmd) + + mw.restartWeb() + return 'ok' + + +def stop(): + conf = getConf() + if os.path.exists(conf): + os.remove(conf) + delPort() + mw.restartWeb() + return 'ok' + + +def restart(): + return start() + + +def reload(): + file_tpl = getPluginDir() + '/conf/lam.conf' + file_run = getConf() + if os.path.exists(file_run): + centent = mw.readFile(file_tpl) + centent = contentReplace(centent) + mw.writeFile(file_run, centent) + return start() + + +def setPhpVer(): + args = getArgs() + + if not 'phpver' in args: + return 'phpver missing' + + cacheFile = getServerDir() + '/php.pl' + mw.writeFile(cacheFile, args['phpver']) + + file_tpl = getPluginDir() + '/conf/lam.conf' + file_run = getConf() + + content = mw.readFile(file_tpl) + content = contentReplace(content) + mw.writeFile(file_run, content) + + mw.restartWeb() + return 'ok' + + +def getSetPhpVer(): + cacheFile = getServerDir() + '/php.pl' + if os.path.exists(cacheFile): + return mw.readFile(cacheFile).strip() + return '' + + +def getPmaOption(): + data = getCfg() + return mw.returnJson(True, 'ok', data) + + +def getPmaPort(): + try: + port = getPort() + return mw.returnJson(True, 'OK', port) + except Exception as e: + # print(e) + return mw.returnJson(False, '插件未启动!') + + +def setPmaPort(): + args = getArgs() + data = checkArgs(args, ['port']) + if not data[0]: + return data[1] + + port = args['port'] + if port == '80': + return mw.returnJson(False, '80端不能使用!') + + file = getConf() + if not os.path.exists(file): + return mw.returnJson(False, '插件未启动!') + content = mw.readFile(file) + rep = r'listen\s*(.*);' + content = re.sub(rep, "listen " + port + ';', content) + mw.writeFile(file, content) + + setCfg("port", port) + mw.restartWeb() + return mw.returnJson(True, '修改成功!') + + +def setPmaUsername(): + args = getArgs() + data = checkArgs(args, ['username']) + if not data[0]: + return data[1] + + username = args['username'] + setCfg('username', username) + + cfg = getCfg() + pma_path = getServerDir() + '/pma.pass' + username = mw.getRandomString(10) + pass_cmd = cfg['username'] + ':' + mw.hasPwd(cfg['password']) + mw.writeFile(pma_path, pass_cmd) + + mw.restartWeb() + return mw.returnJson(True, '修改成功!') + + +def setPmaPassword(): + args = getArgs() + data = checkArgs(args, ['password']) + if not data[0]: + return data[1] + + password = args['password'] + setCfg('password', password) + + cfg = getCfg() + pma_path = getServerDir() + '/pma.pass' + username = mw.getRandomString(10) + pass_cmd = cfg['username'] + ':' + mw.hasPwd(cfg['password']) + mw.writeFile(pma_path, pass_cmd) + + mw.restartWeb() + return mw.returnJson(True, '修改成功!') + + +def setPmaPath(): + args = getArgs() + data = checkArgs(args, ['path']) + if not data[0]: + return data[1] + + path = args['path'] + + if len(path) < 5: + return mw.returnJson(False, '不能小于5位!') + + old_path = getServerDir() + "/" + getCfg()['path'] + new_path = getServerDir() + "/" + path + + mw.execShell("mv " + old_path + " " + new_path) + setCfg('path', path) + return mw.returnJson(True, '修改成功!') + + +def accessLog(): + return getServerDir() + '/access.log' + + +def errorLog(): + return getServerDir() + '/error.log' + + +def installVersion(): + return mw.readFile(getServerDir() + '/version.pl') + +def pluginsDbSupport(): + data = {} + + data['installed'] = 'no' + install_path = getServerDir() + if not os.path.exists(install_path): + return mw.returnJson(True, 'ok', data) + + data['installed'] = 'ok' + data['status'] = status() + if (data['status'] == 'stop'): + return mw.returnJson(True, 'ok', data) + + data['cfg'] = getCfg() + port = getPort() + ip = '127.0.0.1' + if not mw.isAppleSystem(): + ip = thisdb.getOption('server_ip') + + cfg = data['cfg'] + auth = cfg['username']+':'+cfg['password'] + rand_path = cfg['path'] + home_page = 'http://' + auth + '@' + ip + ':' + port + '/' + rand_path + '/index.php' + + data['home_page'] = home_page + data['version'] = installVersion().strip() + + return mw.returnJson(True, 'ok', data) + +if __name__ == "__main__": + func = sys.argv[1] + if func == 'status': + print(status()) + elif func == 'start': + print(start()) + elif func == 'stop': + print(stop()) + elif func == 'restart': + print(restart()) + elif func == 'reload': + print(reload()) + elif func == 'conf': + print(getConf()) + elif func == 'version': + print(installVersion()) + elif func == 'get_cfg': + print(returnCfg()) + elif func == 'config_inc': + print(getConfInc()) + elif func == 'get_home_page': + print(getHomePage()) + elif func == 'set_php_ver': + print(setPhpVer()) + elif func == 'get_set_php_ver': + print(getSetPhpVer()) + elif func == 'get_pma_port': + print(getPmaPort()) + elif func == 'set_pma_port': + print(setPmaPort()) + elif func == 'get_pma_option': + print(getPmaOption()) + elif func == 'set_pma_username': + print(setPmaUsername()) + elif func == 'set_pma_password': + print(setPmaPassword()) + elif func == 'set_pma_path': + print(setPmaPath()) + elif func == 'access_log': + print(accessLog()) + elif func == 'error_log': + print(errorLog()) + elif func == 'plugins_db_support': + print(pluginsDbSupport()) + else: + print('error') diff --git a/plugins/lam/info.json b/plugins/lam/info.json new file mode 100755 index 000000000..3ed72e2cf --- /dev/null +++ b/plugins/lam/info.json @@ -0,0 +1,15 @@ +{ + "title":"phpLDAPadmin", + "tip":"soft", + "name":"lam", + "type":"运行环境", + "ps":"LDAP管理工具", + "versions":["9.0"], + "shell":"install.sh", + "checks":"server/lam", + "path": "server/lam", + "author":"gruberroland", + "home":"https://github.com/LDAPAccountManager", + "date":"2025-1-28", + "pid": "2" +} \ No newline at end of file diff --git a/plugins/lam/install.sh b/plugins/lam/install.sh new file mode 100755 index 000000000..30359140e --- /dev/null +++ b/plugins/lam/install.sh @@ -0,0 +1,90 @@ +#!/bin/bash +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin +export PATH + +curPath=`pwd` +rootPath=$(dirname "$curPath") +rootPath=$(dirname "$rootPath") +serverPath=$(dirname "$rootPath") + +# cd /www/server/mdserver-web/plugins/phpldapadmin && bash install.sh install 1.2.6.7 +# cd /www/server/mdserver-web && python3 plugins/phpldapadmin/index.py start + +if [ -f ${rootPath}/bin/activate ];then + source ${rootPath}/bin/activate +fi + +if [ "$sys_os" == "Darwin" ];then + BAK='_bak' +else + BAK='' +fi + +sysName=`uname` +echo "use system: ${sysName}" + +if [ "${sysName}" == "Darwin" ]; then + OSNAME='macos' +elif grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then + OSNAME='centos' +elif grep -Eqi "Fedora" /etc/issue || grep -Eq "Fedora" /etc/*-release; then + OSNAME='fedora' +elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/*-release; then + OSNAME='debian' +elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/*-release; then + OSNAME='ubuntu' +elif grep -Eqi "Raspbian" /etc/issue || grep -Eq "Raspbian" /etc/*-release; then + OSNAME='raspbian' +else + OSNAME='unknow' +fi + +Install_App() +{ + if [ -d $serverPath/lam ];then + exit 0 + fi + + mkdir -p ${serverPath}/lam + mkdir -p ${serverPath}/source/lam + echo "${1}" > ${serverPath}/lam/version.pl + + VER=$1 + + # https://github.com/leenooks/phpLDAPadmin/archive/refs/tags/1.2.6.7.tar.gz + FDIR=phpLDAPadmin-${VER} + FILE=${VER}.tar.gz + DOWNLOAD=https://github.com/leenooks/phpLDAPadmin/archive/refs/tags/${FILE} + + + if [ ! -f $serverPath/source/phpmyadmin/$FILE ];then + wget --no-check-certificate -O $serverPath/source/lam/$FILE $DOWNLOAD + fi + + if [ ! -d $serverPath/source/lam/$FDIR ];then + cd $serverPath/source/lam && tar zxvf $FILE + fi + + cp -r $serverPath/source/lam/$FDIR $serverPath/lam/ + cd $serverPath/lam/ && mv $FDIR lam + # rm -rf $serverPath/source/lam/$FDIR + + cd ${rootPath} && python3 ${rootPath}/plugins/lam/index.py start + echo '安装完成' + +} + +Uninstall_App() +{ + cd ${rootPath} && python3 ${rootPath}/plugins/lam/index.py stop + + rm -rf ${serverPath}/lam + echo '卸载完成' +} + +action=$1 +if [ "${1}" == 'install' ];then + Install_App $2 +else + Uninstall_App $2 +fi diff --git a/plugins/lam/js/lam.js b/plugins/lam/js/lam.js new file mode 100755 index 000000000..030b55243 --- /dev/null +++ b/plugins/lam/js/lam.js @@ -0,0 +1,164 @@ +function str2Obj(str){ + var data = {}; + kv = str.split('&'); + for(i in kv){ + v = kv[i].split('='); + data[v[0]] = v[1]; + } + return data; +} + +function pmaPost(method,args,callback){ + + var _args = null; + if (typeof(args) == 'string'){ + _args = JSON.stringify(str2Obj(args)); + } else { + _args = JSON.stringify(args); + } + + var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); + $.post('/plugins/run', {name:'phpldapadmin', func:method, args:_args}, function(data) { + layer.close(loadT); + if (!data.status){ + layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + if(typeof(callback) == 'function'){ + callback(data); + } + },'json'); +} + + +function pmaAsyncPost(method,args){ + + var _args = null; + if (typeof(args) == 'string'){ + _args = JSON.stringify(str2Obj(args)); + } else { + _args = JSON.stringify(args); + } + return syncPost('/plugins/run', {name:'phpldapadmin', func:method, args:_args}); +} + +function homePage(){ + pmaPost('get_home_page', '', function(data){ + var rdata = $.parseJSON(data.data); + if (!rdata.status){ + layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + var con = ''; + $(".soft-man-con").html(con); + }); +} + +//phpmyadmin切换php版本 +function phpVer(version) { + + var _version = pmaAsyncPost('get_set_php_ver','') + if (_version['data'] != ''){ + version = _version['data']; + } + + $.post('/site/get_php_version', function(data) { + var rdata = data['data']; + // console.log(rdata); + var body = "
PHP版本
'; + $(".soft-man-con").html(body); + },'json'); +} + +function phpVerChange(type, msg) { + var phpver = $("#phpver").val(); + pmaPost('set_php_ver', 'phpver='+phpver, function(data){ + if ( data.data == 'ok' ){ + layer.msg('设置成功!',{icon:1,time:2000,shade: [0.3, '#000']}); + } else { + layer.msg('设置失败!',{icon:2,time:2000,shade: [0.3, '#000']}); + } + }); +} + + +//phpmyadmin安全设置 +function safeConf() { + pmaPost('get_pma_option', {}, function(rdata){ + var rdata = $.parseJSON(rdata.data); + if (!rdata.status){ + layer.msg(rdata.msg,{icon:2,time:2000,shade: [0.3, '#000']}); + return; + } + + var cfg = rdata.data; + var con = '
\ + 访问端口\ + \ + \ +
\ +
\ + 用户名\ + \ + \ +
\ +
\ + 密码\ + \ + \ +
\ +
\ +
\ + 路径名\ + \ + \ +
'; + $(".soft-man-con").html(con); + }); +} + +function setPmaUsername(){ + var username = $("input[name=username]").val(); + pmaPost('set_pma_username',{'username':username}, function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 }); + }); +} + +function setPmaPassword(){ + var password = $("input[name=password]").val(); + pmaPost('set_pma_password',{'password':password}, function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 }); + }); +} + +function setPmaPath(){ + var path = $("input[name=path]").val(); + pmaPost('set_pma_path',{'path':path}, function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 }); + }); +} + +//修改phpmyadmin端口 +function setPamPort() { + var pmport = $("#pmport").val(); + if (pmport < 80 || pmport > 65535) { + layer.msg('端口范围不合法!', { icon: 2 }); + return; + } + var data = 'port=' + pmport; + + pmaPost('set_pma_port',data, function(data){ + var rdata = $.parseJSON(data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 }); + }); +} \ No newline at end of file