├── .gitignore ├── LICENSE ├── README.md ├── config.cfg ├── server.py ├── shell.jpg ├── start.sh ├── tests ├── _bootstrap_.py ├── exc_shell.py ├── handshake.py ├── message_lengths.py └── testsuite │ ├── __init__.py │ └── messages.py ├── tool ├── longtime.sh ├── start.sh └── utils │ └── check_process.sh ├── web ├── bootstrap │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── signin.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ ├── check.js │ │ ├── check_add_shell.js │ │ ├── check_change.js │ │ ├── jquery-2.1.4.js │ │ ├── modal.js │ │ ├── npm.js │ │ └── tooltip.js ├── config.json ├── config.php ├── index.php ├── log4php.properties ├── log4php │ ├── Logger.php │ ├── LoggerAppender.php │ ├── LoggerAppenderPool.php │ ├── LoggerAutoloader.php │ ├── LoggerConfigurable.php │ ├── LoggerConfigurator.php │ ├── LoggerException.php │ ├── LoggerFilter.php │ ├── LoggerHierarchy.php │ ├── LoggerLayout.php │ ├── LoggerLevel.php │ ├── LoggerLocationInfo.php │ ├── LoggerLoggingEvent.php │ ├── LoggerMDC.php │ ├── LoggerNDC.php │ ├── LoggerReflectionUtils.php │ ├── LoggerRoot.php │ ├── LoggerThrowableInformation.php │ ├── appenders │ │ ├── LoggerAppenderConsole.php │ │ ├── LoggerAppenderDailyFile.php │ │ ├── LoggerAppenderEcho.php │ │ ├── LoggerAppenderFile.php │ │ ├── LoggerAppenderFirePHP.php │ │ ├── LoggerAppenderMail.php │ │ ├── LoggerAppenderMailEvent.php │ │ ├── LoggerAppenderMongoDB.php │ │ ├── LoggerAppenderNull.php │ │ ├── LoggerAppenderPDO.php │ │ ├── LoggerAppenderPhp.php │ │ ├── LoggerAppenderRollingFile.php │ │ ├── LoggerAppenderSocket.php │ │ └── LoggerAppenderSyslog.php │ ├── configurators │ │ ├── LoggerConfigurationAdapter.php │ │ ├── LoggerConfigurationAdapterINI.php │ │ ├── LoggerConfigurationAdapterPHP.php │ │ ├── LoggerConfigurationAdapterXML.php │ │ └── LoggerConfiguratorDefault.php │ ├── filters │ │ ├── LoggerFilterDenyAll.php │ │ ├── LoggerFilterLevelMatch.php │ │ ├── LoggerFilterLevelRange.php │ │ └── LoggerFilterStringMatch.php │ ├── helpers │ │ ├── LoggerFormattingInfo.php │ │ ├── LoggerOptionConverter.php │ │ ├── LoggerPatternParser.php │ │ └── LoggerUtils.php │ ├── layouts │ │ ├── LoggerLayoutHtml.php │ │ ├── LoggerLayoutPattern.php │ │ ├── LoggerLayoutSerialized.php │ │ ├── LoggerLayoutSimple.php │ │ ├── LoggerLayoutTTCC.php │ │ └── LoggerLayoutXml.php │ ├── pattern │ │ ├── LoggerPatternConverter.php │ │ ├── LoggerPatternConverterClass.php │ │ ├── LoggerPatternConverterCookie.php │ │ ├── LoggerPatternConverterDate.php │ │ ├── LoggerPatternConverterEnvironment.php │ │ ├── LoggerPatternConverterFile.php │ │ ├── LoggerPatternConverterLevel.php │ │ ├── LoggerPatternConverterLine.php │ │ ├── LoggerPatternConverterLiteral.php │ │ ├── LoggerPatternConverterLocation.php │ │ ├── LoggerPatternConverterLogger.php │ │ ├── LoggerPatternConverterMDC.php │ │ ├── LoggerPatternConverterMessage.php │ │ ├── LoggerPatternConverterMethod.php │ │ ├── LoggerPatternConverterNDC.php │ │ ├── LoggerPatternConverterNewLine.php │ │ ├── LoggerPatternConverterProcess.php │ │ ├── LoggerPatternConverterRelative.php │ │ ├── LoggerPatternConverterRequest.php │ │ ├── LoggerPatternConverterServer.php │ │ ├── LoggerPatternConverterSession.php │ │ ├── LoggerPatternConverterSessionID.php │ │ ├── LoggerPatternConverterSuperglobal.php │ │ └── LoggerPatternConverterThrowable.php │ ├── renderers │ │ ├── LoggerRenderer.php │ │ ├── LoggerRendererDefault.php │ │ ├── LoggerRendererException.php │ │ └── LoggerRendererMap.php │ └── xml │ │ └── log4php.dtd ├── login.html ├── login.php ├── shell_manager.php └── webdisk.log └── websocket_server ├── __init__.py └── websocket_server.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 逐浪人 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Websocket Shell 2 | ======================= 3 | web目录可以部署在任意的http服务器上 4 | 5 | web客户端可以通过注册账号和修改密码修改config.json的账号的信息 6 | 7 | 账号权限信息和可执行命令由超级用户在管理界面修改 8 | 9 | python通过配置文件config.cfg配置的url路径读取config.json的内容,主要用于校验 10 | 11 | 在python运行期间如果有新注册账户登录就重新读取url内容 12 | 13 | 这里解释一下用到的两个bison_key 14 | 15 | config.php用到的key主要用来加密密码和配置数据的接口,python获取数据的时候要用到同样的key 16 | 17 | login.php用到的key用来和时间戳生成一个token,JavaScript拿着这个token去和python建立连接,python在校验这个token的合法性时 18 | 需要用到同样的key 19 | 20 | 21 | 因为打开页面的浏览器需要跟server.py运行服务器在一个内网,因为他们需要建立socket链接 22 | 23 | 客户端的JavaScript通过websocket跟服务端的python建立链接,发送命令的id,服务端寻找id对应的命令然后执行 24 | 25 | 执行的结果实时回显在客户端的页面上 26 | 27 | 本项目从下面的项目修改而来 28 | https://github.com/Pithikos/python-websocket-server.git 29 | 30 | 之前一直想让普通用户在未获得linux账号的前提下执行一些linux或mac上的shell 31 | 如服务器更新,app发布,配置数据更新等 32 | 33 | 此前的做法一直是winscp或putty脚本来实现,缺点是不安全也不够灵活,账户和密码都在明文的脚本里边放着 34 | 35 | 本项目解决了这个问题,普通用户通过点击网页就可以完成执行命令的操作了 36 | 跟jenkins(http://jenkins-ci.org/ )的功能可能有重合,有时间了我去试下,不过这个项目更轻便一些 37 | 38 | 39 | 40 | 41 | 用法说明: 42 | 43 | 1. 将python-websocket-shell/web目录设置为网站的根目录 44 | 2. 删掉没必要的账号,注册新的账号,修改账号权限,数值越小权限越大,0是超级用户可以自由执行命令,不过这个“自由”仍然有限制 45 | 3. 超级用户通过管理页面修改脚本对应的权限值 46 | 4. 修改web/config.json的adrress为server.py监听的ip和端口,JavaScript要根据它与python服务器建立websocket连接 47 | 5. ./start.sh 启动websocket的服务端 48 | 6. 修改nginx的配置不允许访问config.json,现在即使允许访问也看不到密码,为防止暴力破解密码还是不允许的好 49 | 50 | 启动服务 ./start.sh 51 | 52 | 停止服务 ./start.sh stop 53 | 54 | web目录为root的nginx配置写法如下,location后面的位置是从web的根目录开始的 55 | 56 | location =/config.json{ 57 | return 404; 58 | } 59 | 60 | apache的配置 61 | 62 | 63 | Options FollowSymLinks Multiviews 64 | MultiviewsMatch Any 65 | AllowOverride None 66 | Require all granted 67 | 68 | Order allow,deny 69 | Deny from all 70 | 71 | 72 | 73 | 74 | 之所以没选择数据库来配置只是为了让网站更容易配置,本项目的初衷就是为了更方便的让普通用户访问脚本 75 | 76 | ![image](https://raw.githubusercontent.com/zhulangen/python-websocket-shell/master/shell.jpg) 77 | 78 | 79 | **Thanks** 80 | 81 | https://github.com/Pithikos/python-websocket-server.git 82 | -------------------------------------------------------------------------------- /config.cfg: -------------------------------------------------------------------------------- 1 | [info] 2 | url=http://192.168.23.131:7070/config.php 3 | -------------------------------------------------------------------------------- /server.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | from websocket_server import WebsocketServer 3 | import subprocess 4 | import os 5 | import time 6 | import sys 7 | import json 8 | import hashlib 9 | import logging 10 | import urllib2 11 | import urllib 12 | import ConfigParser 13 | bison_config_key="2da2d990f2abad8-f0f6d6e46556d7-9ad" 14 | bison_token_key="45a1df1c9e2656e4f4c742cf-4753775d" 15 | 16 | logging.basicConfig(filename='webshell.log',level=logging.DEBUG, format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') 17 | 18 | default_encoding = 'utf-8' 19 | if sys.getdefaultencoding() != default_encoding: 20 | reload(sys) 21 | sys.setdefaultencoding(default_encoding) 22 | 23 | 24 | 25 | 26 | # Called for every client connecting (after handshake) 27 | def new_client(client, server): 28 | address="a new client has joined us ip:%s port:%d\n" % (client['address']) 29 | server.send_message_to_all(address) 30 | 31 | 32 | # Called for every client disconnecting 33 | def client_left(client, server): 34 | print("Client(%d) disconnected" % client['id']) 35 | 36 | 37 | 38 | def reload_config(): 39 | global cmd_dic,account_dic,shell_dic,exclude_cmd 40 | s= get_config_data() 41 | cmd_dic=s['servershell'] 42 | account_dic=s['account'] 43 | shell_dic=s['shell'] 44 | exclude_cmd=s['exclude_cmd'] 45 | logging.debug("重新获取账号配置数据") 46 | return 47 | 48 | 49 | def get_config_data(): 50 | data = {} 51 | data['zhulangren'] = 'zhulangren' 52 | data['time'] = time.time() 53 | tokenstr="%s%s%s" % (bison_config_key,data['time'],data['zhulangren']) 54 | m=hashlib.md5() 55 | m.update(tokenstr) 56 | data['token']=m.hexdigest() 57 | post_data = urllib.urlencode(data) 58 | req = urllib2.urlopen(config_url, post_data) 59 | content = req.read() 60 | s = json.loads(content) 61 | if(s['flag']==-1): 62 | logging.debug("配置数据时间戳超时") 63 | elif(s['flag']==-2): 64 | logging.debug("配置数据密码错误") 65 | else: 66 | s=s['data'] 67 | return s 68 | 69 | 70 | #检查超级用户有没有执行非法指令 71 | def check_exclude_cmd(client, cmd): 72 | for ex in exclude_cmd: 73 | if(cmd.count(ex) >0): 74 | logging.debug("非法命令:%s" % ex) 75 | return True 76 | return False 77 | 78 | #根据账号的id返回账号对应的权限值 79 | def get_index_power(index): 80 | for k in shell_dic.keys(): 81 | if shell_dic[k]['index'] ==index: 82 | return shell_dic[k]['power'] 83 | return 0 84 | 85 | def message_dispatch(client,message,issingle): 86 | try: 87 | pids="" 88 | if(issingle==True): 89 | pids= os.popen("ps -ef | grep %s |grep -v grep | awk '{print $2}'" % (message)) 90 | pids=pids.read() 91 | if(pids=="" or issingle==False): 92 | logstr="account:%s ip:%s cmd:%s" %(client['account'],client['address'],message) 93 | logging.debug(logstr) 94 | server.send_message(client,"%s\n" % (logstr)) 95 | subp=subprocess.Popen(message,shell=True,stdout=subprocess.PIPE) 96 | while subp.poll()==None: 97 | for line in iter(subp.stdout.readline,''): 98 | server.send_message(client,line) 99 | 100 | 101 | else: 102 | server.send_message(client,"进程已经在运行了,请等待执行完成 %s!!!\n" % message) 103 | except Exception as e: 104 | print("ERROR: message_dispatch: "+str(e)) 105 | # Called when a client sends a message 106 | def message_received(client, server, message): 107 | if len(message) > 200: 108 | message = message[:200]+'..' 109 | if(message.startswith('account')): 110 | tokenstr=message.split('|') 111 | if(len(tokenstr)<4): 112 | logging.debug("Error format") 113 | return; 114 | 115 | token=tokenstr[3] 116 | ptime=int(tokenstr[2]) 117 | if(abs( ptime-time.time()) > 300): 118 | logging.debug("timeout time1:%d,time2:%d" % (ptime,time.time()) ) 119 | return; 120 | 121 | account=tokenstr[1] 122 | tokenstr="%s%s%s" % (bison_token_key,tokenstr[1],tokenstr[2]) 123 | m=hashlib.md5() 124 | m.update(tokenstr) 125 | ptoken=m.hexdigest() 126 | #logging.debug("token:%s,ptoken:%s,time:%d,str:%s\n" % (token,ptoken,time.time(), tokenstr)) 127 | global account_dic 128 | if(ptoken==token): 129 | if(account_dic.has_key(account)==False): 130 | reload_config() 131 | if(account_dic.has_key(account)==False): 132 | logging.debug("账号不存在") 133 | return 134 | 135 | client['account']=account 136 | client['power']=int(account_dic[account]['power']); 137 | client['islogin']=True 138 | return 139 | if(client['islogin']==False): 140 | logging.debug("you must login!!!!") 141 | return 142 | #logging.debug(p2:%d \n" %(get_index_power(int(message)),client['power'])) 143 | #检测账号是否有权限执行这个命令 144 | bison_str=message.split('@:') 145 | if(len(bison_str)<2): 146 | logging.debug(" Error format %s" % message) 147 | return; 148 | 149 | bison_id=bison_str[0] 150 | bison_cmd=bison_str[1] 151 | issingle=False 152 | if bison_id=='shell': 153 | issingle=True 154 | shell_power=get_index_power(int(bison_cmd)) 155 | if cmd_dic.has_key(bison_cmd): 156 | bison_cmd=cmd_dic[bison_cmd] 157 | else: 158 | logging.debug("don't have the shell %s!!!!" % (bison_str[1])) 159 | return 160 | 161 | if shell_power < client['power'] and client['power'] !=0: 162 | #重新加载一遍数据如果权限还是不对就退出 163 | reload_config() 164 | client['power']=int(account_dic[client['account']]['power']) 165 | if shell_power < client['power'] and client['power'] !=0: 166 | logging.debug("don't have the power!!!! %s " % client['power']) 167 | return 168 | elif bison_id=='cmd': 169 | if client['power']!=0: 170 | logging.debug("don't have the power %s %d!!!!" % (client['account'],client['power'])) 171 | return 172 | 173 | 174 | if (check_exclude_cmd(client, bison_cmd)==False): 175 | message_dispatch(client,bison_cmd,issingle) 176 | else: 177 | logging.debug("命令包含非法字符") 178 | return 179 | 180 | config=ConfigParser.ConfigParser(); 181 | config.read('config.cfg') 182 | config_url=config.get("info","url") 183 | s= get_config_data() 184 | cmd_dic=s['servershell'] 185 | account_dic=s['account'] 186 | shell_dic=s['shell'] 187 | exclude_cmd=s['exclude_cmd'] 188 | 189 | 190 | 191 | PORT=8009 192 | server = WebsocketServer(PORT) 193 | server.set_fn_new_client(new_client) 194 | server.set_fn_client_left(client_left) 195 | server.set_fn_message_received(message_received) 196 | server.run_forever() 197 | 198 | -------------------------------------------------------------------------------- /shell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhulangren/python-websocket-shell/6491514ad82e26cb8e4ce380266c1faa862fadad/shell.jpg -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #WORKDIR=$(dirname `readlink -f $0`) 3 | WORKDIR=$(cd "$(dirname "$0")"; pwd) 4 | cd $WORKDIR 5 | 6 | 7 | appname="server"; 8 | function stop() 9 | { 10 | pid=$(ps aux | grep $WORKDIR | grep $appname | grep -v grep | awk '{print $2}') 11 | if [ -n "$pid" ] ; then 12 | kill -9 $pid 13 | echo "kill server $pid" 14 | fi 15 | pid=$(ps aux | grep $WORKDIR | grep $appname | grep -v grep | awk '{print $2}') 16 | while [ -n "$pid" ] 17 | do 18 | sleep 1 19 | pid=$(ps aux | grep $WORKDIR | grep $appname | grep -v grep | awk '{print $2}') 20 | echo "$WORKDIR/$appname.py still alive " 21 | done 22 | echo "$WORKDIR/$appname.py had been killed" 23 | } 24 | 25 | function start() 26 | { 27 | #首先看下进程是否存在,如果存在不再次启动而是提示先关闭 28 | pid=$(ps aux | grep $WORKDIR | grep $appname | grep -v grep | awk '{print $2}') 29 | if [ -n "$pid" ] ; then 30 | echo "$WORKDIR/$appname.py still alive please kill it first!!!" 31 | return 1; 32 | fi 33 | #切换到脚本所在目录 34 | cd $WORKDIR 35 | rm debug.log 36 | nohup python -u $WORKDIR/$appname.py > ./debug.log 2>&1 & 37 | echo "server is start" 38 | } 39 | chmod 777 web/config.json 40 | chmod 777 web/webdisk.log 41 | 42 | case "$1" in 43 | start) 44 | 45 | start;; 46 | 47 | restart) 48 | stop; 49 | start;; 50 | 51 | stop) 52 | stop ;; 53 | 54 | help) 55 | echo "start|restart|stop";; 56 | *) 57 | stop; 58 | start ;; 59 | 60 | esac 61 | 62 | -------------------------------------------------------------------------------- /tests/_bootstrap_.py: -------------------------------------------------------------------------------- 1 | #Bootstrap 2 | import sys, os 3 | if 'python-websockets-server' in os.getcwd(): 4 | sys.path.insert(0, '..') 5 | -------------------------------------------------------------------------------- /tests/exc_shell.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | subp=subprocess.Popen('./test.sh',shell=True,stdout=subprocess.PIPE) 3 | while subp.poll()==None: 4 | print subp.stdout.readline() 5 | print subp.returncode 6 | 7 | -------------------------------------------------------------------------------- /tests/handshake.py: -------------------------------------------------------------------------------- 1 | import _bootstrap_ 2 | from websocket import * 3 | 4 | 5 | handler = DummyWebsocketHandler() 6 | 7 | 8 | 9 | 10 | pairs = [ 11 | # Key # Response 12 | ('zyjFH2rQwrTtNFk5lwEMQg==', '2hnZADGmT/V1/w1GJYBtttUKASY='), 13 | ('XJuxlsdq0QrVyKwA/D9D5A==', 'tZ5RV3pw7nP9cF+HDvTd89WJKj8=') 14 | ] 15 | 16 | 17 | # Test hash calculations for response 18 | key = 'zyjFH2rQwrTtNFk5lwEMQg==' 19 | resp = handler.calculate_response_key(key) 20 | assert resp == '2hnZADGmT/V1/w1GJYBtttUKASY=' 21 | 22 | 23 | # Test response messages 24 | key = 'zyjFH2rQwrTtNFk5lwEMQg==' 25 | expect = \ 26 | 'HTTP/1.1 101 Switching Protocols\r\n'\ 27 | 'Upgrade: websocket\r\n' \ 28 | 'Connection: Upgrade\r\n' \ 29 | 'Sec-WebSocket-Accept: 2hnZADGmT/V1/w1GJYBtttUKASY=\r\n'\ 30 | '\r\n' 31 | resp = handler.make_handshake_response(key) 32 | assert resp == expect 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | print("No errors") 41 | -------------------------------------------------------------------------------- /tests/message_lengths.py: -------------------------------------------------------------------------------- 1 | import _bootstrap_ 2 | from websocket import WebSocketsServer 3 | from time import sleep 4 | from testsuite.messages import * 5 | 6 | ''' 7 | This creates just a server that will send a different message to every new connection: 8 | 9 | 1. A message of length less than 126 10 | 2. A message of length 126 11 | 3. A message of length 127 12 | 4. A message of length bigger than 127 13 | 5. A message above 1024 14 | 6. A message above 65K 15 | 7. An enormous message (well beyond 65K) 16 | 17 | 18 | Reconnect to get the next message 19 | ''' 20 | 21 | 22 | counter = 0 23 | 24 | # Called for every client connecting (after handshake) 25 | def new_client(client, server): 26 | print("New client connected and was given id %d" % client['id']) 27 | global counter 28 | if counter == 0: 29 | print("Sending message 1 of length %d" % len(msg_125B)) 30 | server.send_message(client, msg_125B) 31 | elif counter == 1: 32 | print("Sending message 2 of length %d" % len(msg_126B)) 33 | server.send_message(client, msg_126B) 34 | elif counter == 2: 35 | print("Sending message 3 of length %d" % len(msg_127B)) 36 | server.send_message(client, msg_127B) 37 | elif counter == 3: 38 | print("Sending message 4 of length %d" % len(msg_208B)) 39 | server.send_message(client, msg_208B) 40 | elif counter == 4: 41 | print("Sending message 5 of length %d" % len(msg_1251B)) 42 | server.send_message(client, msg_1251B) 43 | elif counter == 5: 44 | print("Sending message 6 of length %d" % len(msg_68KB)) 45 | server.send_message(client, msg_68KB) 46 | elif counter == 6: 47 | print("Sending message 7 of length %d" % len(msg_1500KB)) 48 | server.send_message(client, msg_1500KB) 49 | else: 50 | print("No errors") 51 | counter += 1 52 | 53 | 54 | PORT=9001 55 | server = WebSocketsServer(PORT) 56 | server.set_fn_new_client(new_client) 57 | server.run_forever() 58 | -------------------------------------------------------------------------------- /tests/testsuite/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhulangren/python-websocket-shell/6491514ad82e26cb8e4ce380266c1faa862fadad/tests/testsuite/__init__.py -------------------------------------------------------------------------------- /tests/testsuite/messages.py: -------------------------------------------------------------------------------- 1 | # 2 | # Fixed messages by length 3 | # Every message ends with its length.. 4 | # 5 | 6 | msg_125B = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'\ 7 | 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'\ 8 | 'abcdefghijklmnopqr125' 9 | msg_126B = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'\ 10 | 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'\ 11 | 'abcdefghijklmnopqrs126' 12 | msg_127B = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'\ 13 | 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'\ 14 | 'abcdefghijklmnopqrst127' 15 | msg_208B = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'\ 16 | 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'\ 17 | 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'\ 18 | 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvw208' 19 | msg_1251B = (msg_125B*10)+'1' # 1251 20 | msg_68KB = ('a'*67995)+'68000' # 68000 21 | msg_1500KB = ('a'*1500000)+'1500000' # 1.5Mb 22 | -------------------------------------------------------------------------------- /tool/longtime.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | min=1 4 | max=5 5 | while [ $min -le $max ] 6 | do 7 | echo "$min" 8 | sleep 2 9 | min=`expr $min + 1` 10 | done 11 | 12 | -------------------------------------------------------------------------------- /tool/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | function check_process 3 | { 4 | PIDS=`ps -ef |grep -v $$ |grep $1 |grep -v grep | wc -l` 5 | echo $PIDS 6 | 7 | if [ "$PIDS" = "1" ]; then 8 | return 0; 9 | fi 10 | return 1; 11 | } 12 | check_process "$1" 13 | if [ "$?" = "1" ]; then 14 | echo '已经在执行了,请等待执行完毕' 15 | exit 0 16 | fi 17 | 18 | sh $1 19 | -------------------------------------------------------------------------------- /tool/utils/check_process.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | function check_process() 3 | { 4 | PIDS=`ps -ef |grep $1 |grep -v grep | awk '{print $2}'` 5 | if [ "$PIDS" != "" ]; then 6 | echo 1111111111111111 7 | return 1; 8 | fi 9 | echo 2222222222222222 10 | return 0; 11 | } 12 | 13 | 14 | #check_process test 15 | #if [ "$?" = "1" ]; then 16 | # echo 'dddddddddddddddddddddddddddddd\n' 17 | # 18 | #fi 19 | -------------------------------------------------------------------------------- /web/bootstrap/css/signin.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 40px; 3 | padding-bottom: 40px; 4 | background-color: #eee; 5 | } 6 | 7 | .form-signin { 8 | max-width: 330px; 9 | padding: 15px; 10 | margin: 0 auto; 11 | } 12 | .form-signin .form-signin-heading, 13 | .form-signin .checkbox { 14 | margin-bottom: 10px; 15 | } 16 | .form-signin .checkbox { 17 | font-weight: normal; 18 | } 19 | .form-signin .form-control { 20 | position: relative; 21 | height: auto; 22 | -webkit-box-sizing: border-box; 23 | -moz-box-sizing: border-box; 24 | box-sizing: border-box; 25 | padding: 10px; 26 | font-size: 16px; 27 | } 28 | .form-signin .form-control:focus { 29 | z-index: 2; 30 | } 31 | .form-signin input[type="email"] { 32 | margin-bottom: -1px; 33 | border-bottom-right-radius: 0; 34 | border-bottom-left-radius: 0; 35 | } 36 | .form-signin input[type="password"] { 37 | margin-bottom: 10px; 38 | border-top-left-radius: 0; 39 | border-top-right-radius: 0; 40 | } 41 | -------------------------------------------------------------------------------- /web/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhulangren/python-websocket-shell/6491514ad82e26cb8e4ce380266c1faa862fadad/web/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /web/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhulangren/python-websocket-shell/6491514ad82e26cb8e4ce380266c1faa862fadad/web/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /web/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhulangren/python-websocket-shell/6491514ad82e26cb8e4ce380266c1faa862fadad/web/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /web/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhulangren/python-websocket-shell/6491514ad82e26cb8e4ce380266c1faa862fadad/web/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /web/bootstrap/js/check.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by longzhubaby on 2014/10/23. 3 | */ 4 | $(document).ready(function(){ 5 | $(function(){ 6 | $("#email").focus(function(){ 7 | $("#emailTips").text(""); 8 | }); 9 | $("#email").blur(function(){ 10 | checkEmail(); 11 | }); 12 | $("#pass1").focus(function(){ 13 | $("#pass1Tips").text(""); 14 | }); 15 | $("#pass1").blur(function(){ 16 | checkPass1(); 17 | }); 18 | $("#pass2").focus(function(){ 19 | $("#pass2Tips").text(""); 20 | }); 21 | $("#pass2").blur(function(){ 22 | checkPass2(); 23 | }); 24 | $("#seePass1").click(function() 25 | { 26 | if($(this).attr("class")=="glyphicon glyphicon-eye-close") 27 | { 28 | $(this).attr("class","glyphicon glyphicon-eye-open"); 29 | $("#pass1-1").val($("#pass1").val()); 30 | $("#pass1").hide(); 31 | $("#pass1-1").show(); 32 | } 33 | else{ 34 | $(this).attr("class","glyphicon glyphicon-eye-close"); 35 | $("#pass1").val($("#pass1-1").val()); 36 | $("#pass1").show(); 37 | $("#pass1-1").hide(); 38 | } 39 | }); 40 | $("#seePass2").click(function(){ 41 | if($(this).attr("class")=="glyphicon glyphicon-eye-close") 42 | { 43 | $(this).attr("class","glyphicon glyphicon-eye-open"); 44 | $("#pass2-1").val($("#pass2").val()); 45 | $("#pass2").hide(); 46 | $("#pass2-1").show(); 47 | } 48 | else{ 49 | $(this).attr("class","glyphicon glyphicon-eye-close"); 50 | $("#pass2").val($("#pass2-1").val()); 51 | $("#pass2").show(); 52 | $("#pass2-1").hide(); 53 | } 54 | }); 55 | $("#reg").on("click",function(){ 56 | if(checkEmail()&&checkPass1()&&checkPass2()) 57 | { 58 | email=$("#email").val(); 59 | password=$("#pass1").val(); 60 | $.post("login.php",{emailp:email,passwordp:password},function(data,status){ 61 | if(data=="0") 62 | { 63 | alert("账号已存在"); 64 | }else 65 | { 66 | window.location.reload(); 67 | location.href="login.html"; 68 | } 69 | 70 | }); 71 | }else{ 72 | alert("请完善信息"); 73 | } 74 | }); 75 | }); 76 | }); 77 | 78 | function checkEmail() 79 | { 80 | var email=$("#email").val(); 81 | var regex= /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; 82 | if(email.length==0) 83 | { 84 | $("#emailTips").text("*请输入邮箱账号"); 85 | } 86 | else if(!regex.test(email)) 87 | { 88 | $("#emailTips").text("*邮箱格式不符合要求"); 89 | return false; 90 | }else{ 91 | return true; 92 | } 93 | } 94 | function checkPass1() 95 | { 96 | if($("#pass1").attr("hidden")=="hidden") 97 | { 98 | $("#pass1").val($("#pass1-1").val()); 99 | } 100 | var pass1=$("#pass1").val(); 101 | if(pass1.length<6||pass1.length>20) 102 | { 103 | $("#pass1Tips").text("*密码长度为"+pass1.length+",不符合要求"); 104 | return false; 105 | }else{ 106 | return true; 107 | } 108 | } 109 | function checkPass2() 110 | { 111 | if($("#pass1").attr("hidden")=="hidden") 112 | { 113 | $("#pass1").val($("#pass1-1").val()); 114 | } 115 | if($("#pass2").attr("hidden")=="hidden") 116 | { 117 | $("#pass2").val($("#pass2-1").val()); 118 | } 119 | var pass1=$("#pass1").val(); 120 | var pass2=$("#pass2").val(); 121 | if(pass1!=pass2) 122 | { 123 | $("#pass2Tips").text("*两次输入的密码不相同"); 124 | return false; 125 | }else{ 126 | return true; 127 | } 128 | } -------------------------------------------------------------------------------- /web/bootstrap/js/check_add_shell.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by longzhubaby on 2014/10/23. 3 | */ 4 | $(document).ready(function(){ 5 | $(function(){ 6 | $("#email").focus(function(){ 7 | $("#emailTips").text(""); 8 | }); 9 | $("#email").blur(function(){ 10 | checkEmail(); 11 | }); 12 | 13 | $("#Shell").focus(function(){ 14 | $("#shellTips").text(""); 15 | }); 16 | $("#Shell").blur(function(){ 17 | checkShell(); 18 | }); 19 | 20 | $("#addshell").on("click",function(){ 21 | if(checkEmail()&&checkShell()) 22 | { 23 | bname=$("#email").val(); 24 | bname= encodeURI(bname,"UTF-8"); 25 | bpower=$("#power").val(); 26 | bindex=$("#index").val(); 27 | bshell=$("#Shell").val(); 28 | //alert("数值显示:"+bname+bpower+bindex+bshell); 29 | $.post("config.php",{addshell:"addshell", namep:bname,powerp:bpower,pindex:bindex,pshell:bshell},function(data,status){ 30 | if(data=="-1") 31 | { 32 | alert("与已知脚本索引重复"); 33 | return false; 34 | }else if(data=="-2") 35 | { 36 | alert("与已知脚本名称重复"); 37 | return false; 38 | } 39 | window.location.reload(); 40 | }); 41 | }else{ 42 | alert("请完善信息"); 43 | } 44 | }); 45 | }); 46 | }); 47 | 48 | function checkEmail() 49 | { 50 | var email=$("#email").val(); 51 | if(email.length==0) 52 | { 53 | $("#emailTips").text("请输入Shell显示名称"); 54 | } 55 | else{ 56 | return true; 57 | } 58 | } 59 | function checkShell() 60 | { 61 | var email=$("#Shell").val(); 62 | if(email.length==0) 63 | { 64 | $("#shellTips").text("请输入Shell路径"); 65 | } 66 | else{ 67 | return true; 68 | } 69 | } 70 | 71 | function onAccSubmit(id) { 72 | var j=id.substring(2); 73 | var btn=id.substring(0,2); 74 | var account= document.getElementById("ac"+j).innerHTML; 75 | var power= document.getElementById("ap"+j).value; 76 | $.post("config.php",{editaccount:"editaccount",accountp:account,powerp:power,btnp:btn},function(data,status){ 77 | window.location.reload(); 78 | }); 79 | } 80 | function onShellSubmit(id) { 81 | var j=id.substring(2); 82 | var btn=id.substring(0,2); 83 | 84 | var bname= document.getElementById("bn"+j).value; 85 | bname= encodeURI(bname,"UTF-8"); 86 | var bpower= document.getElementById("bp"+j).value; 87 | var bindex= document.getElementById("bi"+j).value; 88 | var bshell= document.getElementById("bs"+j).value; 89 | $.post("config.php",{editshell:"editshell",namep:bname,powerp:bpower,indexp:bindex,shellp:bshell,btnp:btn},function(data,status){ 90 | window.location.reload(); 91 | }); 92 | 93 | } 94 | -------------------------------------------------------------------------------- /web/bootstrap/js/check_change.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by longzhubaby on 2014/10/23. 3 | */ 4 | $(document).ready(function(){ 5 | $(function(){ 6 | $("#ch_email").focus(function(){ 7 | $("#ch_emailTips").text(""); 8 | }); 9 | $("#ch_email").blur(function(){ 10 | ch_checkEmail(); 11 | }); 12 | 13 | $("#ch_oldpass").focus(function(){ 14 | $("#ch_oldpassTips").text(""); 15 | }); 16 | $("#ch_oldpass").blur(function(){ 17 | ch_checkOldPass(); 18 | }); 19 | 20 | 21 | $("#ch_pass1").focus(function(){ 22 | $("#ch_pass1Tips").text(""); 23 | }); 24 | $("#ch_pass1").blur(function(){ 25 | ch_checkPass1(); 26 | }); 27 | $("#ch_pass2").focus(function(){ 28 | $("#ch_pass2Tips").text(""); 29 | }); 30 | $("#ch_pass2").blur(function(){ 31 | ch_checkPass2(); 32 | }); 33 | 34 | $("#ch_oldseePass1").click(function() 35 | { 36 | if($(this).attr("class")=="glyphicon glyphicon-eye-close") 37 | { 38 | $(this).attr("class","glyphicon glyphicon-eye-open"); 39 | $("#ch_oldpass1-1").val($("#ch_oldpass").val()); 40 | $("#ch_oldpass").hide(); 41 | $("#ch_oldpass1-1").show(); 42 | } 43 | else{ 44 | $(this).attr("class","glyphicon glyphicon-eye-close"); 45 | $("#ch_oldpass").val($("#ch_oldpass1-1").val()); 46 | $("#ch_oldpass").show(); 47 | $("#ch_oldpass1-1").hide(); 48 | } 49 | }); 50 | 51 | 52 | $("#ch_seePass1").click(function() 53 | { 54 | if($(this).attr("class")=="glyphicon glyphicon-eye-close") 55 | { 56 | $(this).attr("class","glyphicon glyphicon-eye-open"); 57 | $("#ch_pass1-1").val($("#ch_pass1").val()); 58 | $("#ch_pass1").hide(); 59 | $("#ch_pass1-1").show(); 60 | } 61 | else{ 62 | $(this).attr("class","glyphicon glyphicon-eye-close"); 63 | $("#ch_pass1").val($("#ch_pass1-1").val()); 64 | $("#ch_pass1").show(); 65 | $("#ch_pass1-1").hide(); 66 | } 67 | }); 68 | $("#ch_seePass2").click(function(){ 69 | if($(this).attr("class")=="glyphicon glyphicon-eye-close") 70 | { 71 | $(this).attr("class","glyphicon glyphicon-eye-open"); 72 | $("#ch_pass2-1").val($("#ch_pass2").val()); 73 | $("#ch_pass2").hide(); 74 | $("#ch_pass2-1").show(); 75 | } 76 | else{ 77 | $(this).attr("class","glyphicon glyphicon-eye-close"); 78 | $("#ch_pass2").val($("#ch_pass2-1").val()); 79 | $("#ch_pass2").show(); 80 | $("#ch_pass2-1").hide(); 81 | } 82 | }); 83 | 84 | 85 | 86 | $("#ch_changepwdbtn").on("click",function(){ 87 | if(ch_checkOldPass()&&ch_checkEmail()&&ch_checkPass1()&&ch_checkPass2()) 88 | { 89 | email=$("#ch_email").val(); 90 | ch_olpass=$("#ch_oldpass").val(); 91 | ch_pass1=$("#ch_pass1").val(); 92 | $.post("login.php", 93 | {emailp:email,passwordold:ch_olpass,passwordnew:ch_pass1}, 94 | function(data,status) 95 | { 96 | if(data=="0") 97 | { 98 | alert("账号不存在"); 99 | }else if (data=="1") { 100 | alert("旧密码错误"); 101 | }else 102 | { 103 | window.location.reload(); 104 | location.href="login.html"; 105 | } 106 | 107 | }); 108 | 109 | 110 | }else 111 | { 112 | alert("请完善信息"); 113 | } 114 | }); 115 | }); 116 | }); 117 | 118 | function ch_checkOldPass() 119 | { 120 | if($("#ch_oldpass").attr("hidden")=="hidden") 121 | { 122 | $("#ch_oldpass").val($("#ch_oldpass1-1").val()); 123 | } 124 | var pass1=$("#ch_oldpass").val(); 125 | if(pass1.length<6||pass1.length>20) 126 | { 127 | $("#ch_oldpassTips").text("*密码长度为"+pass1.length+",不符合要求"); 128 | return false; 129 | }else{ 130 | return true; 131 | } 132 | } 133 | 134 | function ch_checkEmail() 135 | { 136 | var email=$("#ch_email").val(); 137 | var regex= /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; 138 | if(email.length==0) 139 | { 140 | $("#ch_emailTips").text("*请输入邮箱账号"); 141 | } 142 | else if(!regex.test(email)) 143 | { 144 | $("#ch_emailTips").text("*邮箱格式不符合要求"); 145 | return false; 146 | }else{ 147 | return true; 148 | } 149 | } 150 | function ch_checkPass1() 151 | { 152 | if($("#ch_pass1").attr("hidden")=="hidden") 153 | { 154 | $("#ch_pass1").val($("#ch_pass1-1").val()); 155 | } 156 | var pass1=$("#ch_pass1").val(); 157 | if(pass1.length<6||pass1.length>20) 158 | { 159 | $("#ch_pass1Tips").text("*密码长度为"+pass1.length+",不符合要求"); 160 | return false; 161 | }else{ 162 | return true; 163 | } 164 | } 165 | function ch_checkPass2() 166 | { 167 | if($("#ch_pass1").attr("hidden")=="hidden") 168 | { 169 | $("#ch_pass1").val($("#ch_pass1-1").val()); 170 | } 171 | if($("#ch_pass2").attr("hidden")=="hidden") 172 | { 173 | $("#ch_pass2").val($("#ch_pass2-1").val()); 174 | } 175 | var pass1=$("#ch_pass1").val(); 176 | var pass2=$("#ch_pass2").val(); 177 | if(pass1!=pass2) 178 | { 179 | $("#ch_pass2Tips").text("*两次输入的密码不相同"); 180 | return false; 181 | }else{ 182 | return true; 183 | } 184 | } -------------------------------------------------------------------------------- /web/bootstrap/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /web/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "address":"192.168.23.131:8009", 3 | "account":{ 4 | "zhulangren@gmail.com":{ 5 | "power":0, 6 | "passwd":"664933f1166d868ba2a3e941936563c7" 7 | }, 8 | "zhulangren1@gmail.com":{ 9 | "power":1, 10 | "passwd":"18ebf8e5e18d79893c4fc42babbbe071" 11 | }, 12 | "afd@dsf.com":{ 13 | "power":2, 14 | "passwd":"c00b83af74649fb6847089f85d4031b4" 15 | }, 16 | "fdsfdfdfadsf@dff.com":{ 17 | "power":2, 18 | "passwd":"3b1e0dacace138afe2a2c9d395d1e6d1" 19 | } 20 | }, 21 | "shell":{ 22 | "Android":{ 23 | "power":1, 24 | "index":1, 25 | "shell":".\/tool\/longtime.sh" 26 | }, 27 | "外网数据":{ 28 | "power":1, 29 | "index":6, 30 | "shell":".\/tool\/longtime.sh" 31 | }, 32 | "本地Server更新1":{ 33 | "power":2, 34 | "index":5, 35 | "shell":".\/tool\/longtime.sh" 36 | }, 37 | "hhj":{ 38 | "power":6, 39 | "index":7, 40 | "shell":"ls" 41 | }, 42 | "本地数据1":{ 43 | "power":1, 44 | "index":2, 45 | "shell":".\/tool\/longtime.sh" 46 | } 47 | }, 48 | "exclude_cmd":[ 49 | "scp", 50 | "ssh", 51 | "rm", 52 | "delete", 53 | "drop", 54 | "empty", 55 | "mv", 56 | "remove", 57 | "userdel", 58 | "useradd", 59 | "groupadd", 60 | "passwd", 61 | "sudo", 62 | "cp", 63 | "php", 64 | "nginx", 65 | "apache", 66 | "kill", 67 | "reboot", 68 | "halt", 69 | "poweroff", 70 | "config.json", 71 | "vim", 72 | "vi" 73 | ] 74 | } -------------------------------------------------------------------------------- /web/index.php: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Shell 25 | 26 | 27 | 28 | 29 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 |

远程脚本

120 | 121 |
122 |
123 | 132 | 133 | 134 | 135 | 136 | 137 |
138 |
139 | 140 | 141 |
142 | 143 | 144 |
145 | 146 | 149 |
150 | 151 | 152 | 153 |
154 |
155 | # 156 | 157 | 158 | 159 | 160 | 161 | 162 |
163 |
164 | EOF; 165 | 166 | if($power==0) 167 | { 168 | echo $super_form; 169 | } 170 | 171 | ?> 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /web/log4php.properties: -------------------------------------------------------------------------------- 1 | log4php.rootLogger=DEBUG, A1 2 | log4php.appender.A1=LoggerAppenderRollingFile 3 | log4php.appender.A1.file=webdisk.log 4 | log4php.appender.A1.layout=LoggerLayoutTTCC 5 | log4php.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%t] %C{1}:%M %p %m%n 6 | log4php.appender.A1.MaxFileSize=1024 7 | log4php.appender.A1.MaxBackupIndex=3 8 | 9 | -------------------------------------------------------------------------------- /web/log4php/LoggerAppenderPool.php: -------------------------------------------------------------------------------- 1 | getName(); 44 | 45 | if(empty($name)) { 46 | trigger_error('log4php: Cannot add unnamed appender to pool.', E_USER_WARNING); 47 | return; 48 | } 49 | 50 | if (isset(self::$appenders[$name])) { 51 | trigger_error("log4php: Appender [$name] already exists in pool. Overwriting existing appender.", E_USER_WARNING); 52 | } 53 | 54 | self::$appenders[$name] = $appender; 55 | } 56 | 57 | /** 58 | * Retrieves an appender from the pool by name. 59 | * @param string $name Name of the appender to retrieve. 60 | * @return LoggerAppender The named appender or NULL if no such appender 61 | * exists in the pool. 62 | */ 63 | public static function get($name) { 64 | return isset(self::$appenders[$name]) ? self::$appenders[$name] : null; 65 | } 66 | 67 | /** 68 | * Removes an appender from the pool by name. 69 | * @param string $name Name of the appender to remove. 70 | */ 71 | public static function delete($name) { 72 | unset(self::$appenders[$name]); 73 | } 74 | 75 | /** 76 | * Returns all appenders from the pool. 77 | * @return array Array of LoggerAppender objects. 78 | */ 79 | public static function getAppenders() { 80 | return self::$appenders; 81 | } 82 | 83 | /** 84 | * Checks whether an appender exists in the pool. 85 | * @param string $name Name of the appender to look for. 86 | * @return boolean TRUE if the appender with the given name exists. 87 | */ 88 | public static function exists($name) { 89 | return isset(self::$appenders[$name]); 90 | } 91 | 92 | /** 93 | * Clears all appenders from the pool. 94 | */ 95 | public static function clear() { 96 | self::$appenders = array(); 97 | } 98 | } -------------------------------------------------------------------------------- /web/log4php/LoggerConfigurable.php: -------------------------------------------------------------------------------- 1 | $property = LoggerOptionConverter::toBooleanEx($value); 36 | } catch (Exception $ex) { 37 | $value = var_export($value, true); 38 | $this->warn("Invalid value given for '$property' property: [$value]. Expected a boolean value. Property not changed."); 39 | } 40 | } 41 | 42 | /** Setter function for integer type. */ 43 | protected function setInteger($property, $value) { 44 | try { 45 | $this->$property = LoggerOptionConverter::toIntegerEx($value); 46 | } catch (Exception $ex) { 47 | $value = var_export($value, true); 48 | $this->warn("Invalid value given for '$property' property: [$value]. Expected an integer. Property not changed."); 49 | } 50 | } 51 | 52 | /** Setter function for LoggerLevel values. */ 53 | protected function setLevel($property, $value) { 54 | try { 55 | $this->$property = LoggerOptionConverter::toLevelEx($value); 56 | } catch (Exception $ex) { 57 | $value = var_export($value, true); 58 | $this->warn("Invalid value given for '$property' property: [$value]. Expected a level value. Property not changed."); 59 | } 60 | } 61 | 62 | /** Setter function for integer type. */ 63 | protected function setPositiveInteger($property, $value) { 64 | try { 65 | $this->$property = LoggerOptionConverter::toPositiveIntegerEx($value); 66 | } catch (Exception $ex) { 67 | $value = var_export($value, true); 68 | $this->warn("Invalid value given for '$property' property: [$value]. Expected a positive integer. Property not changed."); 69 | } 70 | } 71 | 72 | /** Setter for file size. */ 73 | protected function setFileSize($property, $value) { 74 | try { 75 | $this->$property = LoggerOptionConverter::toFileSizeEx($value); 76 | } catch (Exception $ex) { 77 | $value = var_export($value, true); 78 | $this->warn("Invalid value given for '$property' property: [$value]. Expected a file size value. Property not changed."); 79 | } 80 | } 81 | 82 | /** Setter function for numeric type. */ 83 | protected function setNumeric($property, $value) { 84 | try { 85 | $this->$property = LoggerOptionConverter::toNumericEx($value); 86 | } catch (Exception $ex) { 87 | $value = var_export($value, true); 88 | $this->warn("Invalid value given for '$property' property: [$value]. Expected a number. Property not changed."); 89 | } 90 | } 91 | 92 | /** Setter function for string type. */ 93 | protected function setString($property, $value, $nullable = false) { 94 | if ($value === null) { 95 | if($nullable) { 96 | $this->$property= null; 97 | } else { 98 | $this->warn("Null value given for '$property' property. Expected a string. Property not changed."); 99 | } 100 | } else { 101 | try { 102 | $value = LoggerOptionConverter::toStringEx($value); 103 | $this->$property = LoggerOptionConverter::substConstants($value); 104 | } catch (Exception $ex) { 105 | $value = var_export($value, true); 106 | $this->warn("Invalid value given for '$property' property: [$value]. Expected a string. Property not changed."); 107 | } 108 | } 109 | } 110 | 111 | /** Triggers a warning. */ 112 | protected function warn($message) { 113 | $class = get_class($this); 114 | trigger_error("log4php: $class: $message", E_USER_WARNING); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /web/log4php/LoggerConfigurator.php: -------------------------------------------------------------------------------- 1 | This abstract class assumes and also imposes that filters be 30 | * organized in a linear chain. The {@link #decide 31 | * decide(LoggerLoggingEvent)} method of each filter is called sequentially, 32 | * in the order of their addition to the chain. 33 | * 34 | *

The {@link decide()} method must return one 35 | * of the integer constants {@link LoggerFilter::DENY}, 36 | * {@link LoggerFilter::NEUTRAL} or {@link LoggerFilter::ACCEPT}. 37 | * 38 | *

If the value {@link LoggerFilter::DENY} is returned, then the log event is 39 | * dropped immediately without consulting with the remaining 40 | * filters. 41 | * 42 | *

If the value {@link LoggerFilter::NEUTRAL} is returned, then the next filter 43 | * in the chain is consulted. If there are no more filters in the 44 | * chain, then the log event is logged. Thus, in the presence of no 45 | * filters, the default behaviour is to log all logging events. 46 | * 47 | *

If the value {@link LoggerFilter::ACCEPT} is returned, then the log 48 | * event is logged without consulting the remaining filters. 49 | * 50 | *

The philosophy of log4php filters is largely inspired from the 51 | * Linux ipchains. 52 | * 53 | * @version $Revision: 1213283 $ 54 | * @package log4php 55 | */ 56 | abstract class LoggerFilter extends LoggerConfigurable { 57 | 58 | /** 59 | * The log event must be logged immediately without consulting with 60 | * the remaining filters, if any, in the chain. 61 | */ 62 | const ACCEPT = 1; 63 | 64 | /** 65 | * This filter is neutral with respect to the log event. The 66 | * remaining filters, if any, should be consulted for a final decision. 67 | */ 68 | const NEUTRAL = 0; 69 | 70 | /** 71 | * The log event must be dropped immediately without consulting 72 | * with the remaining filters, if any, in the chain. 73 | */ 74 | const DENY = -1; 75 | 76 | /** 77 | * @var LoggerFilter Points to the next {@link LoggerFilter} in the filter chain. 78 | */ 79 | protected $next; 80 | 81 | /** 82 | * Usually filters options become active when set. We provide a 83 | * default do-nothing implementation for convenience. 84 | */ 85 | public function activateOptions() { 86 | } 87 | 88 | /** 89 | * Decide what to do. 90 | *

If the decision is {@link LoggerFilter::DENY}, then the event will be 91 | * dropped. If the decision is {@link LoggerFilter::NEUTRAL}, then the next 92 | * filter, if any, will be invoked. If the decision is {@link LoggerFilter::ACCEPT} then 93 | * the event will be logged without consulting with other filters in 94 | * the chain. 95 | * 96 | * @param LoggerLoggingEvent $event The {@link LoggerLoggingEvent} to decide upon. 97 | * @return integer {@link LoggerFilter::NEUTRAL} or {@link LoggerFilter::DENY}|{@link LoggerFilter::ACCEPT} 98 | */ 99 | public function decide(LoggerLoggingEvent $event) { 100 | return self::NEUTRAL; 101 | } 102 | 103 | /** 104 | * Adds a new filter to the filter chain this filter is a part of. 105 | * If this filter has already and follow up filter, the param filter 106 | * is passed on until it is the last filter in chain. 107 | * 108 | * @param $filter - the filter to add to this chain 109 | */ 110 | public function addNext($filter) { 111 | if($this->next !== null) { 112 | $this->next->addNext($filter); 113 | } else { 114 | $this->next = $filter; 115 | } 116 | } 117 | 118 | /** 119 | * Returns the next filter in this chain 120 | * @return the next filter 121 | */ 122 | public function getNext() { 123 | return $this->next; 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /web/log4php/LoggerLayout.php: -------------------------------------------------------------------------------- 1 | getRenderedMessage(); 44 | } 45 | 46 | /** 47 | * Returns the content type output by this layout. 48 | * @return string 49 | */ 50 | public function getContentType() { 51 | return "text/plain"; 52 | } 53 | 54 | /** 55 | * Returns the footer for the layout format. 56 | * @return string 57 | */ 58 | public function getFooter() { 59 | return null; 60 | } 61 | 62 | /** 63 | * Returns the header for the layout format. 64 | * @return string 65 | */ 66 | public function getHeader() { 67 | return null; 68 | } 69 | 70 | /** Triggers a warning for this layout with the given message. */ 71 | protected function warn($message) { 72 | trigger_error("log4php: [" . get_class($this) . "]: $message", E_USER_WARNING); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /web/log4php/LoggerLocationInfo.php: -------------------------------------------------------------------------------- 1 | lineNumber = isset($trace['line']) ? $trace['line'] : null; 71 | $this->fileName = isset($trace['file']) ? $trace['file'] : null; 72 | $this->className = isset($trace['class']) ? $trace['class'] : null; 73 | $this->methodName = isset($trace['function']) ? $trace['function'] : null; 74 | $this->fullInfo = $this->getClassName() . '.' . $this->getMethodName() . 75 | '(' . $this->getFileName() . ':' . $this->getLineNumber() . ')'; 76 | } 77 | 78 | /** Returns the caller class name. */ 79 | public function getClassName() { 80 | return ($this->className === null) ? self::LOCATION_INFO_NA : $this->className; 81 | } 82 | 83 | /** Returns the caller file name. */ 84 | public function getFileName() { 85 | return ($this->fileName === null) ? self::LOCATION_INFO_NA : $this->fileName; 86 | } 87 | 88 | /** Returns the caller line number. */ 89 | public function getLineNumber() { 90 | return ($this->lineNumber === null) ? self::LOCATION_INFO_NA : $this->lineNumber; 91 | } 92 | 93 | /** Returns the caller method name. */ 94 | public function getMethodName() { 95 | return ($this->methodName === null) ? self::LOCATION_INFO_NA : $this->methodName; 96 | } 97 | 98 | /** Returns the full information of the caller. */ 99 | public function getFullInfo() { 100 | return ($this->fullInfo === null) ? self::LOCATION_INFO_NA : $this->fullInfo; 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /web/log4php/LoggerMDC.php: -------------------------------------------------------------------------------- 1 | obj = $obj; 37 | } 38 | 39 | /** 40 | * Set the properties of an object passed as a parameter in one 41 | * go. The properties are parsed relative to a 42 | * prefix. 43 | * 44 | * @param object $obj The object to configure. 45 | * @param array $properties An array containing keys and values. 46 | * @param string $prefix Only keys having the specified prefix will be set. 47 | */ 48 | // TODO: check, if this is really useful 49 | public static function setPropertiesByObject($obj, $properties, $prefix) { 50 | $pSetter = new LoggerReflectionUtils($obj); 51 | return $pSetter->setProperties($properties, $prefix); 52 | } 53 | 54 | 55 | /** 56 | * Set the properites for the object that match the 57 | * prefix passed as parameter. 58 | * 59 | * Example: 60 | * 61 | * $arr['xxxname'] = 'Joe'; 62 | * $arr['xxxmale'] = true; 63 | * and prefix xxx causes setName and setMale. 64 | * 65 | * @param array $properties An array containing keys and values. 66 | * @param string $prefix Only keys having the specified prefix will be set. 67 | */ 68 | public function setProperties($properties, $prefix) { 69 | $len = strlen($prefix); 70 | reset($properties); 71 | while(list($key,) = each($properties)) { 72 | if(strpos($key, $prefix) === 0) { 73 | if(strpos($key, '.', ($len + 1)) > 0) { 74 | continue; 75 | } 76 | $value = $properties[$key]; 77 | $key = substr($key, $len); 78 | if($key == 'layout' and ($this->obj instanceof LoggerAppender)) { 79 | continue; 80 | } 81 | $this->setProperty($key, $value); 82 | } 83 | } 84 | $this->activate(); 85 | } 86 | 87 | /** 88 | * Set a property on this PropertySetter's Object. If successful, this 89 | * method will invoke a setter method on the underlying Object. The 90 | * setter is the one for the specified property name and the value is 91 | * determined partly from the setter argument type and partly from the 92 | * value specified in the call to this method. 93 | * 94 | *

If the setter expects a String no conversion is necessary. 95 | * If it expects an int, then an attempt is made to convert 'value' 96 | * to an int using new Integer(value). If the setter expects a boolean, 97 | * the conversion is by new Boolean(value). 98 | * 99 | * @param string $name name of the property 100 | * @param string $value String value of the property 101 | */ 102 | public function setProperty($name, $value) { 103 | if($value === null) { 104 | return; 105 | } 106 | 107 | $method = "set" . ucfirst($name); 108 | 109 | if(!method_exists($this->obj, $method)) { 110 | throw new Exception("Error setting log4php property $name to $value: no method $method in class ".get_class($this->obj)."!"); 111 | } else { 112 | return call_user_func(array($this->obj, $method), $value); 113 | } 114 | } 115 | 116 | public function activate() { 117 | if(method_exists($this->obj, 'activateoptions')) { 118 | return call_user_func(array($this->obj, 'activateoptions')); 119 | } 120 | } 121 | 122 | /** 123 | * Creates an instances from the given class name. 124 | * 125 | * @param string $classname 126 | * @return an object from the class with the given classname 127 | */ 128 | public static function createObject($class) { 129 | if(!empty($class)) { 130 | return new $class(); 131 | } 132 | return null; 133 | } 134 | 135 | /** 136 | * @param object $object 137 | * @param string $name 138 | * @param mixed $value 139 | */ 140 | public static function setter($object, $name, $value) { 141 | if (empty($name)) { 142 | return false; 143 | } 144 | $methodName = 'set'.ucfirst($name); 145 | if (method_exists($object, $methodName)) { 146 | return call_user_func(array($object, $methodName), $value); 147 | } else { 148 | return false; 149 | } 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /web/log4php/LoggerRoot.php: -------------------------------------------------------------------------------- 1 | setLevel($level); 41 | } 42 | 43 | /** 44 | * @return LoggerLevel the level 45 | */ 46 | public function getEffectiveLevel() { 47 | return $this->getLevel(); 48 | } 49 | 50 | /** 51 | * Override level setter to prevent setting the root logger's level to 52 | * null. Root logger must always have a level. 53 | * 54 | * @param LoggerLevel $level 55 | */ 56 | public function setLevel(LoggerLevel $level = null) { 57 | if (isset($level)) { 58 | parent::setLevel($level); 59 | } else { 60 | trigger_error("log4php: Cannot set LoggerRoot level to null.", E_USER_WARNING); 61 | } 62 | } 63 | 64 | /** 65 | * Override parent setter. Root logger cannot have a parent. 66 | * @param Logger $parent 67 | */ 68 | public function setParent(Logger $parent) { 69 | trigger_error("log4php: LoggerRoot cannot have a parent.", E_USER_WARNING); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /web/log4php/LoggerThrowableInformation.php: -------------------------------------------------------------------------------- 1 | throwable = $throwable; 43 | } 44 | 45 | /** 46 | * Return source exception 47 | * 48 | * @return Exception 49 | */ 50 | public function getThrowable() { 51 | return $this->throwable; 52 | } 53 | 54 | /** 55 | * @desc Returns string representation of throwable 56 | * 57 | * @return array 58 | */ 59 | public function getStringRepresentation() { 60 | if (!is_array($this->throwableArray)) { 61 | $renderer = new LoggerRendererException(); 62 | 63 | $this->throwableArray = explode("\n", $renderer->render($this->throwable)); 64 | } 65 | 66 | return $this->throwableArray; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /web/log4php/appenders/LoggerAppenderConsole.php: -------------------------------------------------------------------------------- 1 | fp = fopen($this->target, 'w'); 57 | if(is_resource($this->fp) && $this->layout !== null) { 58 | fwrite($this->fp, $this->layout->getHeader()); 59 | } 60 | $this->closed = (bool)is_resource($this->fp) === false; 61 | } 62 | 63 | 64 | public function close() { 65 | if($this->closed != true) { 66 | if (is_resource($this->fp) && $this->layout !== null) { 67 | fwrite($this->fp, $this->layout->getFooter()); 68 | fclose($this->fp); 69 | } 70 | $this->closed = true; 71 | } 72 | } 73 | 74 | public function append(LoggerLoggingEvent $event) { 75 | if (is_resource($this->fp) && $this->layout !== null) { 76 | fwrite($this->fp, $this->layout->format($event)); 77 | } 78 | } 79 | 80 | /** 81 | * Sets the 'target' parameter. 82 | * @param string $target 83 | */ 84 | public function setTarget($target) { 85 | $value = trim($target); 86 | if ($value == self::STDOUT || strtoupper($value) == 'STDOUT') { 87 | $this->target = self::STDOUT; 88 | } elseif ($value == self::STDERR || strtoupper($value) == 'STDERR') { 89 | $this->target = self::STDERR; 90 | } else { 91 | $target = var_export($target); 92 | $this->warn("Invalid value given for 'target' property: [$target]. Property not set."); 93 | } 94 | } 95 | 96 | /** 97 | * Returns the value of the 'target' parameter. 98 | * @return string 99 | */ 100 | public function getTarget() { 101 | return $this->target; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /web/log4php/appenders/LoggerAppenderDailyFile.php: -------------------------------------------------------------------------------- 1 | datePattern)) { 64 | $this->warn("Required parameter 'datePattern' not set. Closing appender."); 65 | $this->closed = true; 66 | return; 67 | } 68 | } 69 | 70 | /** 71 | * Appends a logging event. 72 | * 73 | * If the target file changes because of passage of time (e.g. at midnight) 74 | * the current file is closed. A new file, with the new date, will be 75 | * opened by the write() method. 76 | */ 77 | public function append(LoggerLoggingEvent $event) { 78 | $eventDate = $this->getDate($event->getTimestamp()); 79 | 80 | // Initial setting of current date 81 | if (!isset($this->currentDate)) { 82 | $this->currentDate = $eventDate; 83 | } 84 | 85 | // Check if rollover is needed 86 | else if ($this->currentDate !== $eventDate) { 87 | $this->currentDate = $eventDate; 88 | 89 | // Close the file if it's open. 90 | // Note: $this->close() is not called here because it would set 91 | // $this->closed to true and the appender would not recieve 92 | // any more logging requests 93 | if (is_resource($this->fp)) { 94 | $this->write($this->layout->getFooter()); 95 | fclose($this->fp); 96 | } 97 | $this->fp = null; 98 | } 99 | 100 | parent::append($event); 101 | } 102 | 103 | /** Renders the date using the configured datePattern. */ 104 | protected function getDate($timestamp = null) { 105 | return date($this->datePattern, $timestamp); 106 | } 107 | 108 | /** 109 | * Determines target file. Replaces %s in file path with a date. 110 | */ 111 | protected function getTargetFile() { 112 | return str_replace('%s', $this->currentDate, $this->file); 113 | } 114 | 115 | /** 116 | * Sets the 'datePattern' parameter. 117 | * @param string $datePattern 118 | */ 119 | public function setDatePattern($datePattern) { 120 | $this->setString('datePattern', $datePattern); 121 | } 122 | 123 | /** 124 | * Returns the 'datePattern' parameter. 125 | * @return string 126 | */ 127 | public function getDatePattern() { 128 | return $this->datePattern; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /web/log4php/appenders/LoggerAppenderEcho.php: -------------------------------------------------------------------------------- 1 | element will be inserted 27 | * before each line break in the logged message. Default is false. 28 | * 29 | * @version $Revision: 1337820 $ 30 | * @package log4php 31 | * @subpackage appenders 32 | * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 33 | * @link http://logging.apache.org/log4php/docs/appenders/echo.html Appender documentation 34 | */ 35 | class LoggerAppenderEcho extends LoggerAppender { 36 | /** 37 | * Used to mark first append. Set to false after first append. 38 | * @var boolean 39 | */ 40 | protected $firstAppend = true; 41 | 42 | /** 43 | * If set to true, a
element will be inserted before each line 44 | * break in the logged message. Default value is false. @var boolean 45 | */ 46 | protected $htmlLineBreaks = false; 47 | 48 | public function close() { 49 | if($this->closed != true) { 50 | if(!$this->firstAppend) { 51 | echo $this->layout->getFooter(); 52 | } 53 | } 54 | $this->closed = true; 55 | } 56 | 57 | public function append(LoggerLoggingEvent $event) { 58 | if($this->layout !== null) { 59 | if($this->firstAppend) { 60 | echo $this->layout->getHeader(); 61 | $this->firstAppend = false; 62 | } 63 | $text = $this->layout->format($event); 64 | 65 | if ($this->htmlLineBreaks) { 66 | $text = nl2br($text); 67 | } 68 | echo $text; 69 | } 70 | } 71 | 72 | /** 73 | * Sets the 'htmlLineBreaks' parameter. 74 | * @param boolean $value 75 | */ 76 | public function setHtmlLineBreaks($value) { 77 | $this->setBoolean('htmlLineBreaks', $value); 78 | } 79 | 80 | /** 81 | * Returns the 'htmlLineBreaks' parameter. 82 | * @returns boolean 83 | */ 84 | public function getHtmlLineBreaks() { 85 | return $this->htmlLineBreaks; 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /web/log4php/appenders/LoggerAppenderFile.php: -------------------------------------------------------------------------------- 1 | file; 73 | } 74 | 75 | /** 76 | * Acquires the target file resource, creates the destination folder if 77 | * necessary. Writes layout header to file. 78 | * 79 | * @return boolean FALSE if opening failed 80 | */ 81 | protected function openFile() { 82 | $file = $this->getTargetFile(); 83 | 84 | // Create the target folder if needed 85 | if(!is_file($file)) { 86 | $dir = dirname($file); 87 | 88 | if(!is_dir($dir)) { 89 | $success = mkdir($dir, 0777, true); 90 | if ($success === false) { 91 | $this->warn("Failed creating target directory [$dir]. Closing appender."); 92 | $this->closed = true; 93 | return false; 94 | } 95 | } 96 | } 97 | 98 | $mode = $this->append ? 'a' : 'w'; 99 | $this->fp = fopen($file, $mode); 100 | if ($this->fp === false) { 101 | $this->warn("Failed opening target file. Closing appender."); 102 | $this->fp = null; 103 | $this->closed = true; 104 | return false; 105 | } 106 | 107 | // Required when appending with concurrent access 108 | if($this->append) { 109 | fseek($this->fp, 0, SEEK_END); 110 | } 111 | 112 | // Write the header 113 | $this->write($this->layout->getHeader()); 114 | } 115 | 116 | /** 117 | * Writes a string to the target file. Opens file if not already open. 118 | * @param string $string Data to write. 119 | */ 120 | protected function write($string) { 121 | // Lazy file open 122 | if(!isset($this->fp)) { 123 | if ($this->openFile() === false) { 124 | return; // Do not write if file open failed. 125 | } 126 | } 127 | 128 | if ($this->locking) { 129 | $this->writeWithLocking($string); 130 | } else { 131 | $this->writeWithoutLocking($string); 132 | } 133 | } 134 | 135 | protected function writeWithLocking($string) { 136 | if(flock($this->fp, LOCK_EX)) { 137 | if(fwrite($this->fp, $string) === false) { 138 | $this->warn("Failed writing to file. Closing appender."); 139 | $this->closed = true; 140 | } 141 | flock($this->fp, LOCK_UN); 142 | } else { 143 | $this->warn("Failed locking file for writing. Closing appender."); 144 | $this->closed = true; 145 | } 146 | } 147 | 148 | protected function writeWithoutLocking($string) { 149 | if(fwrite($this->fp, $string) === false) { 150 | $this->warn("Failed writing to file. Closing appender."); 151 | $this->closed = true; 152 | } 153 | } 154 | 155 | public function activateOptions() { 156 | if (empty($this->file)) { 157 | $this->warn("Required parameter 'file' not set. Closing appender."); 158 | $this->closed = true; 159 | return; 160 | } 161 | } 162 | 163 | public function close() { 164 | if (is_resource($this->fp)) { 165 | $this->write($this->layout->getFooter()); 166 | fclose($this->fp); 167 | } 168 | $this->fp = null; 169 | $this->closed = true; 170 | } 171 | 172 | public function append(LoggerLoggingEvent $event) { 173 | $this->write($this->layout->format($event)); 174 | } 175 | 176 | /** 177 | * Sets the 'file' parameter. 178 | * @param string $file 179 | */ 180 | public function setFile($file) { 181 | $this->setString('file', $file); 182 | } 183 | 184 | /** 185 | * Returns the 'file' parameter. 186 | * @return string 187 | */ 188 | public function getFile() { 189 | return $this->file; 190 | } 191 | 192 | /** 193 | * Returns the 'append' parameter. 194 | * @return boolean 195 | */ 196 | public function getAppend() { 197 | return $this->append; 198 | } 199 | 200 | /** 201 | * Sets the 'append' parameter. 202 | * @param boolean $append 203 | */ 204 | public function setAppend($append) { 205 | $this->setBoolean('append', $append); 206 | } 207 | 208 | /** 209 | * Sets the 'file' parmeter. Left for legacy reasons. 210 | * @param string $fileName 211 | * @deprecated Use setFile() instead. 212 | */ 213 | public function setFileName($fileName) { 214 | $this->setFile($fileName); 215 | } 216 | 217 | /** 218 | * Returns the 'file' parmeter. Left for legacy reasons. 219 | * @return string 220 | * @deprecated Use getFile() instead. 221 | */ 222 | public function getFileName() { 223 | return $this->getFile(); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /web/log4php/appenders/LoggerAppenderFirePHP.php: -------------------------------------------------------------------------------- 1 | console = FirePHP::to($this->target)->console(); 59 | $this->closed = false; 60 | } else { 61 | $this->warn('FirePHP is not installed correctly. Closing appender.'); 62 | } 63 | } 64 | 65 | public function append(LoggerLoggingEvent $event) { 66 | $msg = $event->getMessage(); 67 | 68 | // Skip formatting for objects and arrays which are handled by FirePHP. 69 | if (!is_array($msg) && !is_object($msg)) { 70 | $msg = $this->getLayout()->format($event); 71 | } 72 | 73 | switch ($event->getLevel()->toInt()) { 74 | case LoggerLevel::TRACE: 75 | case LoggerLevel::DEBUG: 76 | $this->console->log($msg); 77 | break; 78 | case LoggerLevel::INFO: 79 | $this->console->info($msg); 80 | break; 81 | case LoggerLevel::WARN: 82 | $this->console->warn($msg); 83 | break; 84 | case LoggerLevel::ERROR: 85 | case LoggerLevel::FATAL: 86 | $this->console->error($msg); 87 | break; 88 | } 89 | } 90 | 91 | /** Returns the target. */ 92 | public function getTarget() { 93 | return $this->target; 94 | } 95 | 96 | /** Sets the target. */ 97 | public function setTarget($target) { 98 | $this->setString('target', $target); 99 | } 100 | } -------------------------------------------------------------------------------- /web/log4php/appenders/LoggerAppenderMail.php: -------------------------------------------------------------------------------- 1 | layout !== null) { 78 | $this->body .= $this->layout->format($event); 79 | } 80 | } 81 | 82 | public function close() { 83 | if($this->closed != true) { 84 | $from = $this->from; 85 | $to = $this->to; 86 | 87 | if(!empty($this->body) and $from !== null and $to !== null and $this->layout !== null) { 88 | $subject = $this->subject; 89 | if(!$this->dry) { 90 | mail( 91 | $to, $subject, 92 | $this->layout->getHeader() . $this->body . $this->layout->getFooter(), 93 | "From: {$from}\r\n"); 94 | } else { 95 | echo "DRY MODE OF MAIL APP.: Send mail to: ".$to." with content: ".$this->body; 96 | } 97 | } 98 | $this->closed = true; 99 | } 100 | } 101 | 102 | /** Sets the 'subject' parameter. */ 103 | public function setSubject($subject) { 104 | $this->setString('subject', $subject); 105 | } 106 | 107 | /** Returns the 'subject' parameter. */ 108 | public function getSubject() { 109 | return $this->subject; 110 | } 111 | 112 | /** Sets the 'to' parameter. */ 113 | public function setTo($to) { 114 | $this->setString('to', $to); 115 | } 116 | 117 | /** Returns the 'to' parameter. */ 118 | public function getTo() { 119 | return $this->to; 120 | } 121 | 122 | /** Sets the 'from' parameter. */ 123 | public function setFrom($from) { 124 | $this->setString('from', $from); 125 | } 126 | 127 | /** Returns the 'from' parameter. */ 128 | public function getFrom() { 129 | return $this->from; 130 | } 131 | 132 | /** Enables or disables dry mode. */ 133 | public function setDry($dry) { 134 | $this->setBoolean('dry', $dry); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /web/log4php/appenders/LoggerAppenderMailEvent.php: -------------------------------------------------------------------------------- 1 | to)) { 84 | $this->warn("Required parameter 'to' not set. Closing appender."); 85 | $this->close = true; 86 | return; 87 | } 88 | 89 | $sendmail_from = ini_get('sendmail_from'); 90 | if (empty($this->from) and empty($sendmail_from)) { 91 | $this->warn("Required parameter 'from' not set. Closing appender."); 92 | $this->close = true; 93 | return; 94 | } 95 | 96 | $this->closed = false; 97 | } 98 | 99 | public function append(LoggerLoggingEvent $event) { 100 | $smtpHost = $this->smtpHost; 101 | $prevSmtpHost = ini_get('SMTP'); 102 | if(!empty($smtpHost)) { 103 | ini_set('SMTP', $smtpHost); 104 | } 105 | 106 | $smtpPort = $this->port; 107 | $prevSmtpPort= ini_get('smtp_port'); 108 | if($smtpPort > 0 and $smtpPort < 65535) { 109 | ini_set('smtp_port', $smtpPort); 110 | } 111 | 112 | // On unix only sendmail_path, which is PHP_INI_SYSTEM i.e. not changeable here, is used. 113 | 114 | $addHeader = empty($this->from) ? '' : "From: {$this->from}\r\n"; 115 | 116 | if(!$this->dry) { 117 | $result = mail($this->to, $this->subject, $this->layout->getHeader() . $this->layout->format($event) . $this->layout->getFooter($event), $addHeader); 118 | } else { 119 | echo "DRY MODE OF MAIL APP.: Send mail to: ".$this->to." with additional headers '".trim($addHeader)."' and content: ".$this->layout->format($event); 120 | } 121 | 122 | ini_set('SMTP', $prevSmtpHost); 123 | ini_set('smtp_port', $prevSmtpPort); 124 | } 125 | 126 | /** Sets the 'from' parameter. */ 127 | public function setFrom($from) { 128 | $this->setString('from', $from); 129 | } 130 | 131 | /** Returns the 'from' parameter. */ 132 | public function getFrom() { 133 | return $this->from; 134 | } 135 | 136 | /** Sets the 'port' parameter. */ 137 | public function setPort($port) { 138 | $this->setPositiveInteger('port', $port); 139 | } 140 | 141 | /** Returns the 'port' parameter. */ 142 | public function getPort() { 143 | return $this->port; 144 | } 145 | 146 | /** Sets the 'smtpHost' parameter. */ 147 | public function setSmtpHost($smtpHost) { 148 | $this->setString('smtpHost', $smtpHost); 149 | } 150 | 151 | /** Returns the 'smtpHost' parameter. */ 152 | public function getSmtpHost() { 153 | return $this->smtpHost; 154 | } 155 | 156 | /** Sets the 'subject' parameter. */ 157 | public function setSubject($subject) { 158 | $this->setString('subject', $subject); 159 | } 160 | 161 | /** Returns the 'subject' parameter. */ 162 | public function getSubject() { 163 | return $this->subject; 164 | } 165 | 166 | /** Sets the 'to' parameter. */ 167 | public function setTo($to) { 168 | $this->setString('to', $to); 169 | } 170 | 171 | /** Returns the 'to' parameter. */ 172 | public function getTo() { 173 | return $this->to; 174 | } 175 | 176 | /** Enables or disables dry mode. */ 177 | public function setDry($dry) { 178 | $this->setBoolean('dry', $dry); 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /web/log4php/appenders/LoggerAppenderNull.php: -------------------------------------------------------------------------------- 1 | level < WARN mapped to E_USER_NOTICE 28 | * - WARN <= level < ERROR mapped to E_USER_WARNING 29 | * - level >= ERROR mapped to E_USER_ERROR 30 | * 31 | * @version $Revision: 1337820 $ 32 | * @package log4php 33 | * @subpackage appenders 34 | * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 35 | * @link http://logging.apache.org/log4php/docs/appenders/php.html Appender documentation 36 | */ 37 | class LoggerAppenderPhp extends LoggerAppender { 38 | 39 | public function append(LoggerLoggingEvent $event) { 40 | $level = $event->getLevel(); 41 | if($level->isGreaterOrEqual(LoggerLevel::getLevelError())) { 42 | trigger_error($this->layout->format($event), E_USER_ERROR); 43 | } else if ($level->isGreaterOrEqual(LoggerLevel::getLevelWarn())) { 44 | trigger_error($this->layout->format($event), E_USER_WARNING); 45 | } else { 46 | trigger_error($this->layout->format($event), E_USER_NOTICE); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /web/log4php/appenders/LoggerAppenderSocket.php: -------------------------------------------------------------------------------- 1 | remoteHost)) { 62 | $this->warn("Required parameter [remoteHost] not set. Closing appender."); 63 | $this->closed = true; 64 | return; 65 | } 66 | 67 | if (empty($this->timeout)) { 68 | $this->timeout = ini_get("default_socket_timeout"); 69 | } 70 | 71 | $this->closed = false; 72 | } 73 | 74 | public function append(LoggerLoggingEvent $event) { 75 | $socket = fsockopen($this->remoteHost, $this->port, $errno, $errstr, $this->timeout); 76 | if ($socket === false) { 77 | $this->warn("Could not open socket to {$this->remoteHost}:{$this->port}. Closing appender."); 78 | $this->closed = true; 79 | return; 80 | } 81 | 82 | if (false === fwrite($socket, $this->layout->format($event))) { 83 | $this->warn("Error writing to socket. Closing appender."); 84 | $this->closed = true; 85 | } 86 | fclose($socket); 87 | } 88 | 89 | // ****************************************** 90 | // *** Accessor methods *** 91 | // ****************************************** 92 | 93 | /** Sets the target host. */ 94 | public function setRemoteHost($hostname) { 95 | $this->setString('remoteHost', $hostname); 96 | } 97 | 98 | /** Sets the target port */ 99 | public function setPort($port) { 100 | $this->setPositiveInteger('port', $port); 101 | } 102 | 103 | /** Sets the timeout. */ 104 | public function setTimeout($timeout) { 105 | $this->setPositiveInteger('timeout', $timeout); 106 | } 107 | 108 | /** Returns the target host. */ 109 | public function getRemoteHost() { 110 | return $this->getRemoteHost(); 111 | } 112 | 113 | /** Returns the target port. */ 114 | public function getPort() { 115 | return $this->port; 116 | } 117 | 118 | /** Returns the timeout */ 119 | public function getTimeout() { 120 | return $this->timeout; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /web/log4php/configurators/LoggerConfigurationAdapter.php: -------------------------------------------------------------------------------- 1 | 28 | * array( 31 | * 'level' => 'info', 32 | * 'appenders' => array('default') 33 | * ), 34 | * 'appenders' => array( 35 | * 'default' => array( 36 | * 'class' => 'LoggerAppenderEcho', 37 | * 'layout' => array( 38 | * 'class' => 'LoggerLayoutSimple' 39 | * ) 40 | * ) 41 | * ) 42 | * ) 43 | * ?> 44 | * 45 | * 46 | * @package log4php 47 | * @subpackage configurators 48 | * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 49 | * @version $Revision: 1343601 $ 50 | * @since 2.2 51 | */ 52 | class LoggerConfigurationAdapterPHP implements LoggerConfigurationAdapter 53 | { 54 | public function convert($url) { 55 | if (!file_exists($url)) { 56 | throw new LoggerException("File [$url] does not exist."); 57 | } 58 | 59 | // Load the config file 60 | $data = @file_get_contents($url); 61 | if ($data === false) { 62 | $error = error_get_last(); 63 | throw new LoggerException("Error loading config file: {$error['message']}"); 64 | } 65 | 66 | $config = @eval('?>' . $data); 67 | 68 | if ($config === false) { 69 | $error = error_get_last(); 70 | throw new LoggerException("Error parsing configuration: " . $error['message']); 71 | } 72 | 73 | if (empty($config)) { 74 | throw new LoggerException("Invalid configuration: empty configuration array."); 75 | } 76 | 77 | if (!is_array($config)) { 78 | throw new LoggerException("Invalid configuration: not an array."); 79 | } 80 | 81 | return $config; 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /web/log4php/filters/LoggerFilterDenyAll.php: -------------------------------------------------------------------------------- 1 | 30 | * An example for this filter: 31 | * 32 | * {@example ../../examples/php/filter_denyall.php 19} 33 | * 34 | *

35 | * The corresponding XML file: 36 | * 37 | * {@example ../../examples/resources/filter_denyall.xml 18} 38 | * 39 | * @version $Revision: 883108 $ 40 | * @package log4php 41 | * @subpackage filters 42 | * @since 0.3 43 | */ 44 | class LoggerFilterDenyAll extends LoggerFilter { 45 | 46 | /** 47 | * Always returns the integer constant {@link LoggerFilter::DENY} 48 | * regardless of the {@link LoggerLoggingEvent} parameter. 49 | * 50 | * @param LoggerLoggingEvent $event The {@link LoggerLoggingEvent} to filter. 51 | * @return LoggerFilter::DENY Always returns {@link LoggerFilter::DENY} 52 | */ 53 | public function decide(LoggerLoggingEvent $event) { 54 | return LoggerFilter::DENY; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /web/log4php/filters/LoggerFilterLevelMatch.php: -------------------------------------------------------------------------------- 1 | The filter admits two options LevelToMatch and 25 | * AcceptOnMatch. If there is an exact match between the value 26 | * of the LevelToMatch option and the level of the 27 | * {@link LoggerLoggingEvent}, then the {@link decide()} method returns 28 | * {@link LoggerFilter::ACCEPT} in case the AcceptOnMatch 29 | * option value is set to true, if it is false then 30 | * {@link LoggerFilter::DENY} is returned. If there is no match, 31 | * {@link LoggerFilter::NEUTRAL} is returned.

32 | * 33 | *

34 | * An example for this filter: 35 | * 36 | * {@example ../../examples/php/filter_levelmatch.php 19} 37 | * 38 | *

39 | * The corresponding XML file: 40 | * 41 | * {@example ../../examples/resources/filter_levelmatch.xml 18} 42 | * 43 | * @version $Revision: 1213283 $ 44 | * @package log4php 45 | * @subpackage filters 46 | * @since 0.6 47 | */ 48 | class LoggerFilterLevelMatch extends LoggerFilter { 49 | 50 | /** 51 | * Indicates if this event should be accepted or denied on match 52 | * @var boolean 53 | */ 54 | protected $acceptOnMatch = true; 55 | 56 | /** 57 | * The level, when to match 58 | * @var LoggerLevel 59 | */ 60 | protected $levelToMatch; 61 | 62 | /** 63 | * @param boolean $acceptOnMatch 64 | */ 65 | public function setAcceptOnMatch($acceptOnMatch) { 66 | $this->setBoolean('acceptOnMatch', $acceptOnMatch); 67 | } 68 | 69 | /** 70 | * @param string $l the level to match 71 | */ 72 | public function setLevelToMatch($level) { 73 | $this->setLevel('levelToMatch', $level); 74 | } 75 | 76 | /** 77 | * Return the decision of this filter. 78 | * 79 | * Returns {@link LoggerFilter::NEUTRAL} if the LevelToMatch 80 | * option is not set or if there is not match. Otherwise, if there is a 81 | * match, then the returned decision is {@link LoggerFilter::ACCEPT} if the 82 | * AcceptOnMatch property is set to true. The 83 | * returned decision is {@link LoggerFilter::DENY} if the 84 | * AcceptOnMatch property is set to false. 85 | * 86 | * @param LoggerLoggingEvent $event 87 | * @return integer 88 | */ 89 | public function decide(LoggerLoggingEvent $event) { 90 | if($this->levelToMatch === null) { 91 | return LoggerFilter::NEUTRAL; 92 | } 93 | 94 | if($this->levelToMatch->equals($event->getLevel())) { 95 | return $this->acceptOnMatch ? LoggerFilter::ACCEPT : LoggerFilter::DENY; 96 | } else { 97 | return LoggerFilter::NEUTRAL; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /web/log4php/filters/LoggerFilterLevelRange.php: -------------------------------------------------------------------------------- 1 | The filter admits three options LevelMin, LevelMax 26 | * and AcceptOnMatch.

27 | * 28 | *

If the level of the {@link LoggerLoggingEvent} is not between Min and Max 29 | * (inclusive), then {@link LoggerFilter::DENY} is returned.

30 | * 31 | *

If the Logging event level is within the specified range, then if 32 | * AcceptOnMatch is true, 33 | * {@link LoggerFilter::ACCEPT} is returned, and if 34 | * AcceptOnMatch is false, 35 | * {@link LoggerFilter::NEUTRAL} is returned.

36 | * 37 | *

If LevelMin is not defined, then there is no 38 | * minimum acceptable level (i.e. a level is never rejected for 39 | * being too "low"/unimportant). If LevelMax is not 40 | * defined, then there is no maximum acceptable level (ie a 41 | * level is never rejected for being too "high"/important).

42 | * 43 | *

Refer to the {@link LoggerAppender::setThreshold()} method 44 | * available to all appenders extending {@link LoggerAppender} 45 | * for a more convenient way to filter out events by level.

46 | * 47 | *

48 | * An example for this filter: 49 | * 50 | * {@example ../../examples/php/filter_levelrange.php 19} 51 | * 52 | *

53 | * The corresponding XML file: 54 | * 55 | * {@example ../../examples/resources/filter_levelrange.xml 18} 56 | * 57 | * @author Simon Kitching 58 | * @author based on the org.apache.log4j.varia.LevelRangeFilte Java code by Ceki Gülcü 59 | * 60 | * @version $Revision: 1213283 $ 61 | * @package log4php 62 | * @subpackage filters 63 | * @since 0.6 64 | */ 65 | class LoggerFilterLevelRange extends LoggerFilter { 66 | 67 | /** 68 | * @var boolean 69 | */ 70 | protected $acceptOnMatch = true; 71 | 72 | /** 73 | * @var LoggerLevel 74 | */ 75 | protected $levelMin; 76 | 77 | /** 78 | * @var LoggerLevel 79 | */ 80 | protected $levelMax; 81 | 82 | /** 83 | * @param boolean $acceptOnMatch 84 | */ 85 | public function setAcceptOnMatch($acceptOnMatch) { 86 | $this->setBoolean('acceptOnMatch', $acceptOnMatch); 87 | } 88 | 89 | /** 90 | * @param string $l the level min to match 91 | */ 92 | public function setLevelMin($level) { 93 | $this->setLevel('levelMin', $level); 94 | } 95 | 96 | /** 97 | * @param string $l the level max to match 98 | */ 99 | public function setLevelMax($level) { 100 | $this->setLevel('levelMax', $level); 101 | } 102 | 103 | /** 104 | * Return the decision of this filter. 105 | * 106 | * @param LoggerLoggingEvent $event 107 | * @return integer 108 | */ 109 | public function decide(LoggerLoggingEvent $event) { 110 | $level = $event->getLevel(); 111 | 112 | if($this->levelMin !== null) { 113 | if($level->isGreaterOrEqual($this->levelMin) == false) { 114 | // level of event is less than minimum 115 | return LoggerFilter::DENY; 116 | } 117 | } 118 | 119 | if($this->levelMax !== null) { 120 | if($level->toInt() > $this->levelMax->toInt()) { 121 | // level of event is greater than maximum 122 | // Alas, there is no Level.isGreater method. and using 123 | // a combo of isGreaterOrEqual && !Equal seems worse than 124 | // checking the int values of the level objects.. 125 | return LoggerFilter::DENY; 126 | } 127 | } 128 | 129 | if($this->acceptOnMatch) { 130 | // this filter set up to bypass later filters and always return 131 | // accept if level in range 132 | return LoggerFilter::ACCEPT; 133 | } else { 134 | // event is ok for this filter; allow later filters to have a look.. 135 | return LoggerFilter::NEUTRAL; 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /web/log4php/filters/LoggerFilterStringMatch.php: -------------------------------------------------------------------------------- 1 | The filter admits two options {@link $stringToMatch} and 25 | * {@link $acceptOnMatch}. If there is a match (using {@link PHP_MANUAL#strpos} 26 | * between the value of the {@link $stringToMatch} option and the message 27 | * of the {@link LoggerLoggingEvent}, 28 | * then the {@link decide()} method returns {@link LoggerFilter::ACCEPT} if 29 | * the AcceptOnMatch option value is true, if it is false then 30 | * {@link LoggerFilter::DENY} is returned. If there is no match, {@link LoggerFilter::NEUTRAL} 31 | * is returned.

32 | * 33 | *

34 | * An example for this filter: 35 | * 36 | * {@example ../../examples/php/filter_stringmatch.php 19} 37 | * 38 | *

39 | * The corresponding XML file: 40 | * 41 | * {@example ../../examples/resources/filter_stringmatch.xml 18} 42 | * 43 | * @version $Revision: 1213283 $ 44 | * @package log4php 45 | * @subpackage filters 46 | * @since 0.3 47 | */ 48 | class LoggerFilterStringMatch extends LoggerFilter { 49 | 50 | /** 51 | * @var boolean 52 | */ 53 | protected $acceptOnMatch = true; 54 | 55 | /** 56 | * @var string 57 | */ 58 | protected $stringToMatch; 59 | 60 | /** 61 | * @param mixed $acceptOnMatch a boolean or a string ('true' or 'false') 62 | */ 63 | public function setAcceptOnMatch($acceptOnMatch) { 64 | $this->setBoolean('acceptOnMatch', $acceptOnMatch); 65 | } 66 | 67 | /** 68 | * @param string $s the string to match 69 | */ 70 | public function setStringToMatch($string) { 71 | $this->setString('stringToMatch', $string); 72 | } 73 | 74 | /** 75 | * @return integer a {@link LOGGER_FILTER_NEUTRAL} is there is no string match. 76 | */ 77 | public function decide(LoggerLoggingEvent $event) { 78 | $msg = $event->getRenderedMessage(); 79 | 80 | if($msg === null or $this->stringToMatch === null) { 81 | return LoggerFilter::NEUTRAL; 82 | } 83 | 84 | if(strpos($msg, $this->stringToMatch) !== false ) { 85 | return ($this->acceptOnMatch) ? LoggerFilter::ACCEPT : LoggerFilter::DENY; 86 | } 87 | return LoggerFilter::NEUTRAL; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /web/log4php/helpers/LoggerFormattingInfo.php: -------------------------------------------------------------------------------- 1 | $fragment) { 47 | if (trim($fragment) === '') { 48 | unset($fragments[$key]); 49 | } 50 | } 51 | 52 | return $fragments; 53 | } 54 | 55 | /** 56 | * Attempts to shorten the given class name to the desired length. 57 | * 58 | * This is done by separating the class name into fragments (delimited 59 | * by \ or .) and trimming individual fragments, starting with the left, 60 | * until desired length has been reached. 61 | * 62 | * The final fragment (i.e. class name) will never be shortened so the 63 | * result may still be longer than given length. 64 | * 65 | * @param string $name The (qualified) class name. 66 | * @param integer $length The length to shorten to. If null or 0 is given, 67 | * the name will be returned without shortening. 68 | */ 69 | public static function shortenClassName($name, $length) { 70 | if ($length === null || $length < 0) { 71 | return $name; 72 | } 73 | 74 | $name = str_replace('.', '\\', $name); 75 | $name = trim($name, ' \\'); 76 | 77 | // Check if any shortening is required 78 | $currentLength = strlen($name); 79 | if ($currentLength <= $length) { 80 | return $name; 81 | } 82 | 83 | // Split name into fragments 84 | $fragments = explode('\\', $name); 85 | 86 | // If zero length is specified, return only last fragment 87 | if ($length == 0) { 88 | return array_pop($fragments); 89 | } 90 | 91 | // If the name splits to only one fragment, then it cannot be shortened 92 | $count = count($fragments); 93 | if ($count == 1) { 94 | return $name; 95 | } 96 | 97 | foreach($fragments as $key => &$fragment) { 98 | 99 | // Never shorten last fragment 100 | if ($key == $count - 1) { 101 | break; 102 | } 103 | 104 | // Check for empty fragments (shouldn't happen but it's possible) 105 | $fragLen = strlen($fragment); 106 | if ($fragLen <= 1) { 107 | continue; 108 | } 109 | 110 | // Shorten fragment to one character and check if total length satisfactory 111 | $fragment = substr($fragment, 0, 1); 112 | $currentLength = $currentLength - $fragLen + 1; 113 | 114 | if ($currentLength <= $length) { 115 | break; 116 | } 117 | } 118 | unset($fragment); 119 | 120 | return implode('\\', $fragments); 121 | } 122 | } 123 | 124 | -------------------------------------------------------------------------------- /web/log4php/layouts/LoggerLayoutPattern.php: -------------------------------------------------------------------------------- 1 | 'LoggerPatternConverterLogger', 47 | 'lo' => 'LoggerPatternConverterLogger', 48 | 'logger' => 'LoggerPatternConverterLogger', 49 | 50 | 'C' => 'LoggerPatternConverterClass', 51 | 'class' => 'LoggerPatternConverterClass', 52 | 53 | 'cookie' => 'LoggerPatternConverterCookie', 54 | 55 | 'd' => 'LoggerPatternConverterDate', 56 | 'date' => 'LoggerPatternConverterDate', 57 | 58 | 'e' => 'LoggerPatternConverterEnvironment', 59 | 'env' => 'LoggerPatternConverterEnvironment', 60 | 61 | 'ex' => 'LoggerPatternConverterThrowable', 62 | 'exception' => 'LoggerPatternConverterThrowable', 63 | 'throwable' => 'LoggerPatternConverterThrowable', 64 | 65 | 'F' => 'LoggerPatternConverterFile', 66 | 'file' => 'LoggerPatternConverterFile', 67 | 68 | 'l' => 'LoggerPatternConverterLocation', 69 | 'location' => 'LoggerPatternConverterLocation', 70 | 71 | 'L' => 'LoggerPatternConverterLine', 72 | 'line' => 'LoggerPatternConverterLine', 73 | 74 | 'm' => 'LoggerPatternConverterMessage', 75 | 'msg' => 'LoggerPatternConverterMessage', 76 | 'message' => 'LoggerPatternConverterMessage', 77 | 78 | 'M' => 'LoggerPatternConverterMethod', 79 | 'method' => 'LoggerPatternConverterMethod', 80 | 81 | 'n' => 'LoggerPatternConverterNewLine', 82 | 'newline' => 'LoggerPatternConverterNewLine', 83 | 84 | 'p' => 'LoggerPatternConverterLevel', 85 | 'le' => 'LoggerPatternConverterLevel', 86 | 'level' => 'LoggerPatternConverterLevel', 87 | 88 | 'r' => 'LoggerPatternConverterRelative', 89 | 'relative' => 'LoggerPatternConverterRelative', 90 | 91 | 'req' => 'LoggerPatternConverterRequest', 92 | 'request' => 'LoggerPatternConverterRequest', 93 | 94 | 's' => 'LoggerPatternConverterServer', 95 | 'server' => 'LoggerPatternConverterServer', 96 | 97 | 'ses' => 'LoggerPatternConverterSession', 98 | 'session' => 'LoggerPatternConverterSession', 99 | 100 | 'sid' => 'LoggerPatternConverterSessionID', 101 | 'sessionid' => 'LoggerPatternConverterSessionID', 102 | 103 | 't' => 'LoggerPatternConverterProcess', 104 | 'pid' => 'LoggerPatternConverterProcess', 105 | 'process' => 'LoggerPatternConverterProcess', 106 | 107 | 'x' => 'LoggerPatternConverterNDC', 108 | 'ndc' => 'LoggerPatternConverterNDC', 109 | 110 | 'X' => 'LoggerPatternConverterMDC', 111 | 'mdc' => 'LoggerPatternConverterMDC', 112 | ); 113 | 114 | /** Maps conversion keywords to the relevant converter. */ 115 | protected $converterMap = array(); 116 | 117 | /** 118 | * Head of a chain of Converters. 119 | * @var LoggerPatternConverter 120 | */ 121 | private $head; 122 | 123 | /** Returns the default converter map. */ 124 | public static function getDefaultConverterMap() { 125 | return self::$defaultConverterMap; 126 | } 127 | 128 | /** Constructor. Initializes the converter map. */ 129 | public function __construct() { 130 | $this->converterMap = self::$defaultConverterMap; 131 | } 132 | 133 | /** 134 | * Sets the conversionPattern option. This is the string which 135 | * controls formatting and consists of a mix of literal content and 136 | * conversion specifiers. 137 | * @param array $conversionPattern 138 | */ 139 | public function setConversionPattern($conversionPattern) { 140 | $this->pattern = $conversionPattern; 141 | } 142 | 143 | /** 144 | * Processes the conversion pattern and creates a corresponding chain of 145 | * pattern converters which will be used to format logging events. 146 | */ 147 | public function activateOptions() { 148 | if (!isset($this->pattern)) { 149 | throw new LoggerException("Mandatory parameter 'conversionPattern' is not set."); 150 | } 151 | 152 | $parser = new LoggerPatternParser($this->pattern, $this->converterMap); 153 | $this->head = $parser->parse(); 154 | } 155 | 156 | /** 157 | * Produces a formatted string as specified by the conversion pattern. 158 | * 159 | * @param LoggerLoggingEvent $event 160 | * @return string 161 | */ 162 | public function format(LoggerLoggingEvent $event) { 163 | $sbuf = ''; 164 | $converter = $this->head; 165 | while ($converter !== null) { 166 | $converter->format($sbuf, $event); 167 | $converter = $converter->next; 168 | } 169 | return $sbuf; 170 | } 171 | } -------------------------------------------------------------------------------- /web/log4php/layouts/LoggerLayoutSerialized.php: -------------------------------------------------------------------------------- 1 | setBoolean('locationInfo', $value); 41 | } 42 | 43 | /** Returns the location information flag. */ 44 | public function getLocationInfo() { 45 | return $this->locationInfo; 46 | } 47 | 48 | public function format(LoggerLoggingEvent $event) { 49 | // If required, initialize the location data 50 | if($this->locationInfo) { 51 | $event->getLocationInformation(); 52 | } 53 | return serialize($event) . PHP_EOL; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /web/log4php/layouts/LoggerLayoutSimple.php: -------------------------------------------------------------------------------- 1 | level, followed by " - " and then the message. 26 | * 27 | * For example the following php and properties files 28 | * 29 | * {@example ../../examples/php/layout_simple.php 19}
30 | * 31 | * {@example ../../examples/resources/layout_simple.properties 18}
32 | * 33 | * would result in: 34 | * 35 | * INFO - Hello World! 36 | * 37 | * @version $Revision: 1213283 $ 38 | * @package log4php 39 | * @subpackage layouts 40 | */ 41 | class LoggerLayoutSimple extends LoggerLayout { 42 | /** 43 | * Returns the log statement in a format consisting of the 44 | * level, followed by " - " and then the 45 | * message. For example, 46 | * INFO - "A message" 47 | * 48 | * @param LoggerLoggingEvent $event 49 | * @return string 50 | */ 51 | public function format(LoggerLoggingEvent $event) { 52 | $level = $event->getLevel(); 53 | $message = $event->getRenderedMessage(); 54 | return "$level - $message" . PHP_EOL; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /web/log4php/layouts/LoggerLayoutTTCC.php: -------------------------------------------------------------------------------- 1 | time, thread, category and nested 23 | * diagnostic context information, hence the name. 24 | * 25 | *

Each of the four fields can be individually enabled or 26 | * disabled. The time format depends on the DateFormat used.

27 | * 28 | *

If no dateFormat is specified it defaults to '%c'. 29 | * See php {@link PHP_MANUAL#date} function for details.

30 | * 31 | * Configurable parameters for this layout are: 32 | * - {@link $threadPrinting} (true|false) enable/disable pid reporting. 33 | * - {@link $categoryPrefixing} (true|false) enable/disable logger category reporting. 34 | * - {@link $contextPrinting} (true|false) enable/disable NDC reporting. 35 | * - {@link $microSecondsPrinting} (true|false) enable/disable micro seconds reporting in timestamp. 36 | * - {@link $dateFormat} (string) set date format. See php {@link PHP_MANUAL#date} function for details. 37 | * 38 | * An example how to use this layout: 39 | * 40 | * {@example ../../examples/php/layout_ttcc.php 19}
41 | * 42 | * {@example ../../examples/resources/layout_ttcc.properties 18}
43 | * 44 | * The above would print:
45 | * 02:28 [13714] INFO root - Hello World! 46 | * 47 | * @version $Revision: 1302503 $ 48 | * @package log4php 49 | * @subpackage layouts 50 | * 51 | * @deprecated LoggerLayout TTCC is deprecated and will be removed in a future release. Please use 52 | * LoggerLayoutPattern instead. 53 | */ 54 | class LoggerLayoutTTCC extends LoggerLayout { 55 | 56 | // Internal representation of options 57 | protected $threadPrinting = true; 58 | protected $categoryPrefixing = true; 59 | protected $contextPrinting = true; 60 | protected $microSecondsPrinting = true; 61 | 62 | /** 63 | * @var string date format. See {@link PHP_MANUAL#strftime} for details 64 | */ 65 | protected $dateFormat = '%c'; 66 | 67 | /** 68 | * Constructor 69 | * 70 | * @param string date format 71 | * @see dateFormat 72 | */ 73 | public function __construct($dateFormat = '') { 74 | $this->warn("LoggerLayout TTCC is deprecated and will be removed in a future release. Please use LoggerLayoutPattern instead."); 75 | if (!empty($dateFormat)) { 76 | $this->dateFormat = $dateFormat; 77 | } 78 | return; 79 | } 80 | 81 | /** 82 | * The ThreadPrinting option specifies whether the name of the 83 | * current thread is part of log output or not. This is true by default. 84 | */ 85 | public function setThreadPrinting($threadPrinting) { 86 | $this->setBoolean('threadPrinting', $threadPrinting); 87 | } 88 | 89 | /** 90 | * @return boolean Returns value of the ThreadPrinting option. 91 | */ 92 | public function getThreadPrinting() { 93 | return $this->threadPrinting; 94 | } 95 | 96 | /** 97 | * The CategoryPrefixing option specifies whether {@link Category} 98 | * name is part of log output or not. This is true by default. 99 | */ 100 | public function setCategoryPrefixing($categoryPrefixing) { 101 | $this->setBoolean('categoryPrefixing', $categoryPrefixing); 102 | } 103 | 104 | /** 105 | * @return boolean Returns value of the CategoryPrefixing option. 106 | */ 107 | public function getCategoryPrefixing() { 108 | return $this->categoryPrefixing; 109 | } 110 | 111 | /** 112 | * The ContextPrinting option specifies log output will include 113 | * the nested context information belonging to the current thread. 114 | * This is true by default. 115 | */ 116 | public function setContextPrinting($contextPrinting) { 117 | $this->setBoolean('contextPrinting', $contextPrinting); 118 | } 119 | 120 | /** 121 | * @return boolean Returns value of the ContextPrinting option. 122 | */ 123 | public function getContextPrinting() { 124 | return $this->contextPrinting; 125 | } 126 | 127 | /** 128 | * The MicroSecondsPrinting option specifies if microseconds infos 129 | * should be printed at the end of timestamp. 130 | * This is true by default. 131 | */ 132 | public function setMicroSecondsPrinting($microSecondsPrinting) { 133 | $this->setBoolean('microSecondsPrinting', $microSecondsPrinting); 134 | } 135 | 136 | /** 137 | * @return boolean Returns value of the MicroSecondsPrinting option. 138 | */ 139 | public function getMicroSecondsPrinting() { 140 | return $this->microSecondsPrinting; 141 | } 142 | 143 | 144 | public function setDateFormat($dateFormat) { 145 | $this->setString('dateFormat', $dateFormat); 146 | } 147 | 148 | /** 149 | * @return string 150 | */ 151 | public function getDateFormat() { 152 | return $this->dateFormat; 153 | } 154 | 155 | /** 156 | * In addition to the level of the statement and message, the 157 | * returned string includes time, thread, category. 158 | *

Time, thread, category are printed depending on options. 159 | * 160 | * @param LoggerLoggingEvent $event 161 | * @return string 162 | */ 163 | public function format(LoggerLoggingEvent $event) { 164 | $timeStamp = (float)$event->getTimeStamp(); 165 | $format = strftime($this->dateFormat, (int)$timeStamp); 166 | 167 | if ($this->microSecondsPrinting) { 168 | $usecs = floor(($timeStamp - (int)$timeStamp) * 1000); 169 | $format .= sprintf(',%03d', $usecs); 170 | } 171 | 172 | $format .= ' '; 173 | 174 | if ($this->threadPrinting) { 175 | $format .= '['.getmypid().'] '; 176 | } 177 | 178 | $level = $event->getLevel(); 179 | $format .= $level.' '; 180 | 181 | if($this->categoryPrefixing) { 182 | $format .= $event->getLoggerName().' '; 183 | } 184 | 185 | if($this->contextPrinting) { 186 | $ndc = $event->getNDC(); 187 | if($ndc != null) { 188 | $format .= $ndc.' '; 189 | } 190 | } 191 | 192 | $format .= '- '.$event->getRenderedMessage(); 193 | $format .= PHP_EOL; 194 | 195 | return $format; 196 | } 197 | 198 | public function ignoresThrowable() { 199 | return true; 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /web/log4php/layouts/LoggerLayoutXml.php: -------------------------------------------------------------------------------- 1 | It does not output a complete well-formed XML file. 32 | * The output is designed to be included as an external entity in a separate file to form 33 | * a correct XML file.

34 | * 35 | * Example: 36 | * 37 | * {@example ../../examples/php/layout_xml.php 19}
38 | * 39 | * {@example ../../examples/resources/layout_xml.properties 18}
40 | * 41 | * The above would print: 42 | * 43 | *
 44 |  * 
 45 |  * 	
 46 |  * 		
 47 |  * 		
 48 |  * 	
 49 |  * 
 50 |  * 
51 | * 52 | * @version $Revision: 1213283 $ 53 | * @package log4php 54 | * @subpackage layouts 55 | */ 56 | class LoggerLayoutXml extends LoggerLayout { 57 | const LOG4J_NS_PREFIX ='log4j'; 58 | const LOG4J_NS = 'http://jakarta.apache.org/log4j/'; 59 | 60 | const LOG4PHP_NS_PREFIX = 'log4php'; 61 | const LOG4PHP_NS = 'http://logging.apache.org/log4php/'; 62 | 63 | const CDATA_START = ''; 65 | const CDATA_PSEUDO_END = ']]>'; 66 | const CDATA_EMBEDDED_END = ']]>]]>getLog4jNamespace()) { 90 | $this->namespace = self::LOG4J_NS; 91 | $this->namespacePrefix = self::LOG4J_NS_PREFIX; 92 | } else { 93 | $this->namespace = self::LOG4PHP_NS; 94 | $this->namespacePrefix = self::LOG4PHP_NS_PREFIX; 95 | } 96 | } 97 | 98 | /** 99 | * @return string 100 | */ 101 | public function getHeader() { 102 | return "<{$this->namespacePrefix}:eventSet ". 103 | "xmlns:{$this->namespacePrefix}=\"{$this->namespace}\" ". 104 | "version=\"0.3\" ". 105 | "includesLocationInfo=\"".($this->getLocationInfo() ? "true" : "false")."\"". 106 | ">" . PHP_EOL; 107 | } 108 | 109 | /** 110 | * Formats a {@link LoggerLoggingEvent} in conformance with the log4php.dtd. 111 | * 112 | * @param LoggerLoggingEvent $event 113 | * @return string 114 | */ 115 | public function format(LoggerLoggingEvent $event) { 116 | $ns = $this->namespacePrefix; 117 | 118 | $loggerName = $event->getLoggerName(); 119 | $timeStamp = number_format((float)($event->getTimeStamp() * 1000), 0, '', ''); 120 | $thread = $event->getThreadName(); 121 | $level = $event->getLevel()->toString(); 122 | 123 | $buf = "<$ns:event logger=\"{$loggerName}\" level=\"{$level}\" thread=\"{$thread}\" timestamp=\"{$timeStamp}\">".PHP_EOL; 124 | $buf .= "<$ns:message>"; 125 | $buf .= $this->encodeCDATA($event->getRenderedMessage()); 126 | $buf .= "".PHP_EOL; 127 | 128 | $ndc = $event->getNDC(); 129 | if(!empty($ndc)) { 130 | $buf .= "<$ns:NDC>encodeCDATA($ndc); 132 | $buf .= "]]>".PHP_EOL; 133 | } 134 | 135 | $mdcMap = $event->getMDCMap(); 136 | if (!empty($mdcMap)) { 137 | $buf .= "<$ns:properties>".PHP_EOL; 138 | foreach ($mdcMap as $name=>$value) { 139 | $buf .= "<$ns:data name=\"$name\" value=\"$value\" />".PHP_EOL; 140 | } 141 | $buf .= "".PHP_EOL; 142 | } 143 | 144 | if ($this->getLocationInfo()) { 145 | $locationInfo = $event->getLocationInformation(); 146 | $buf .= "<$ns:locationInfo ". 147 | "class=\"" . $locationInfo->getClassName() . "\" ". 148 | "file=\"" . htmlentities($locationInfo->getFileName(), ENT_QUOTES) . "\" ". 149 | "line=\"" . $locationInfo->getLineNumber() . "\" ". 150 | "method=\"" . $locationInfo->getMethodName() . "\" "; 151 | $buf .= "/>".PHP_EOL; 152 | } 153 | 154 | $buf .= "".PHP_EOL; 155 | 156 | return $buf; 157 | } 158 | 159 | /** 160 | * @return string 161 | */ 162 | public function getFooter() { 163 | return "namespacePrefix}:eventSet>" . PHP_EOL; 164 | } 165 | 166 | 167 | /** 168 | * Whether or not file name and line number will be included in the output. 169 | * @return boolean 170 | */ 171 | public function getLocationInfo() { 172 | return $this->locationInfo; 173 | } 174 | 175 | /** 176 | * The {@link $locationInfo} option takes a boolean value. By default, 177 | * it is set to false which means there will be no location 178 | * information output by this layout. If the the option is set to 179 | * true, then the file name and line number of the statement at the 180 | * origin of the log statement will be output. 181 | */ 182 | public function setLocationInfo($flag) { 183 | $this->setBoolean('locationInfo', $flag); 184 | } 185 | 186 | /** 187 | * @return boolean 188 | */ 189 | public function getLog4jNamespace() { 190 | return $this->log4jNamespace; 191 | } 192 | 193 | /** 194 | * @param boolean 195 | */ 196 | public function setLog4jNamespace($flag) { 197 | $this->setBoolean('log4jNamespace', $flag); 198 | } 199 | 200 | /** 201 | * Encases a string in CDATA tags, and escapes any existing CDATA end 202 | * tags already present in the string. 203 | * @param string $string 204 | */ 205 | private function encodeCDATA($string) { 206 | $string = str_replace(self::CDATA_END, self::CDATA_EMBEDDED_END, $string); 207 | return self::CDATA_START . $string . self::CDATA_END; 208 | } 209 | } 210 | 211 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverter.php: -------------------------------------------------------------------------------- 1 | Conversion specifiers in a conversion patterns are parsed to 26 | * individual PatternConverters. Each of which is responsible for 27 | * converting a logging event in a converter specific manner.

28 | * 29 | * @version $Revision: 1326626 $ 30 | * @package log4php 31 | * @subpackage helpers 32 | * @since 0.3 33 | */ 34 | abstract class LoggerPatternConverter { 35 | 36 | /** 37 | * Next converter in the converter chain. 38 | * @var LoggerPatternConverter 39 | */ 40 | public $next = null; 41 | 42 | /** 43 | * Formatting information, parsed from pattern modifiers. 44 | * @var LoggerFormattingInfo 45 | */ 46 | protected $formattingInfo; 47 | 48 | /** 49 | * Converter-specific formatting options. 50 | * @var array 51 | */ 52 | protected $option; 53 | 54 | /** 55 | * Constructor 56 | * @param LoggerFormattingInfo $formattingInfo 57 | * @param array $option 58 | */ 59 | public function __construct(LoggerFormattingInfo $formattingInfo = null, $option = null) { 60 | $this->formattingInfo = $formattingInfo; 61 | $this->option = $option; 62 | $this->activateOptions(); 63 | } 64 | 65 | /** 66 | * Called in constructor. Converters which need to process the options 67 | * can override this method. 68 | */ 69 | public function activateOptions() { } 70 | 71 | /** 72 | * Converts the logging event to the desired format. Derived pattern 73 | * converters must implement this method. 74 | * 75 | * @param LoggerLoggingEvent $event 76 | */ 77 | abstract public function convert(LoggerLoggingEvent $event); 78 | 79 | /** 80 | * Converts the event and formats it according to setting in the 81 | * Formatting information object. 82 | * 83 | * @param string &$sbuf string buffer to write to 84 | * @param LoggerLoggingEvent $event Event to be formatted. 85 | */ 86 | public function format(&$sbuf, $event) { 87 | $string = $this->convert($event); 88 | 89 | if (!isset($this->formattingInfo)) { 90 | $sbuf .= $string; 91 | return; 92 | } 93 | 94 | $fi = $this->formattingInfo; 95 | 96 | // Empty string 97 | if($string === '' || is_null($string)) { 98 | if($fi->min > 0) { 99 | $sbuf .= str_repeat(' ', $fi->min); 100 | } 101 | return; 102 | } 103 | 104 | $len = strlen($string); 105 | 106 | // Trim the string if needed 107 | if($len > $fi->max) { 108 | if ($fi->trimLeft) { 109 | $sbuf .= substr($string, $len - $fi->max, $fi->max); 110 | } else { 111 | $sbuf .= substr($string , 0, $fi->max); 112 | } 113 | } 114 | 115 | // Add padding if needed 116 | else if($len < $fi->min) { 117 | if($fi->padLeft) { 118 | $sbuf .= str_repeat(' ', $fi->min - $len); 119 | $sbuf .= $string; 120 | } else { 121 | $sbuf .= $string; 122 | $sbuf .= str_repeat(' ', $fi->min - $len); 123 | } 124 | } 125 | 126 | // No action needed 127 | else { 128 | $sbuf .= $string; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterClass.php: -------------------------------------------------------------------------------- 1 | option) && is_numeric($this->option) && $this->option >= 0) { 41 | $this->length = (integer) $this->option; 42 | } 43 | } 44 | 45 | public function convert(LoggerLoggingEvent $event) { 46 | $name = $event->getLocationInformation()->getClassName(); 47 | 48 | if (!isset($this->cache[$name])) { 49 | 50 | // If length is set return shortened class name 51 | if (isset($this->length)) { 52 | $this->cache[$name] = LoggerUtils::shortenClassName($name, $this->length); 53 | } 54 | 55 | // If no length is specified return the full class name 56 | else { 57 | $this->cache[$name] = $name; 58 | } 59 | } 60 | 61 | return $this->cache[$name]; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterCookie.php: -------------------------------------------------------------------------------- 1 | self::DATE_FORMAT_ISO8601, 47 | 'ABSOLUTE' => self::DATE_FORMAT_ABSOLUTE, 48 | 'DATE' => self::DATE_FORMAT_DATE, 49 | ); 50 | 51 | private $useLocalDate = false; 52 | 53 | public function activateOptions() { 54 | 55 | // Parse the option (date format) 56 | if (!empty($this->option)) { 57 | if(isset($this->specials[$this->option])) { 58 | $this->format = $this->specials[$this->option]; 59 | } else { 60 | $this->format = $this->option; 61 | } 62 | } 63 | 64 | // Check whether the pattern contains milliseconds (u) 65 | if (preg_match('/(?format)) { 66 | $this->useLocalDate = true; 67 | } 68 | } 69 | 70 | public function convert(LoggerLoggingEvent $event) { 71 | if ($this->useLocalDate) { 72 | return $this->date($this->format, $event->getTimeStamp()); 73 | } 74 | return date($this->format, $event->getTimeStamp()); 75 | } 76 | 77 | /** 78 | * Currently, PHP date() function always returns zeros for milliseconds (u) 79 | * on Windows. This is a replacement function for date() which correctly 80 | * displays milliseconds on all platforms. 81 | * 82 | * It is slower than PHP date() so it should only be used if necessary. 83 | */ 84 | private function date($format, $utimestamp) { 85 | $timestamp = floor($utimestamp); 86 | $ms = floor(($utimestamp - $timestamp) * 1000); 87 | $ms = str_pad($ms, 3, '0', STR_PAD_LEFT); 88 | 89 | return date(preg_replace('`(?getLocationInformation()->getFileName(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterLevel.php: -------------------------------------------------------------------------------- 1 | getLevel()->toString(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterLine.php: -------------------------------------------------------------------------------- 1 | getLocationInformation()->getLineNumber(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterLiteral.php: -------------------------------------------------------------------------------- 1 | literalValue = $literalValue; 35 | } 36 | 37 | public function convert(LoggerLoggingEvent $event) { 38 | return $this->literalValue; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterLocation.php: -------------------------------------------------------------------------------- 1 | getLocationInformation()->getClassName() . '.' . 35 | $event->getLocationInformation()->getMethodName() . '(' . 36 | $event->getLocationInformation()->getFileName() . ':' . 37 | $event->getLocationInformation()->getLineNumber() . ')'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterLogger.php: -------------------------------------------------------------------------------- 1 | option) && is_numeric($this->option) && $this->option >= 0) { 43 | $this->length = (integer) $this->option; 44 | } 45 | } 46 | 47 | public function convert(LoggerLoggingEvent $event) { 48 | $name = $event->getLoggerName(); 49 | 50 | if (!isset($this->cache[$name])) { 51 | 52 | // If length is set return shortened logger name 53 | if (isset($this->length)) { 54 | $this->cache[$name] = LoggerUtils::shortenClassName($name, $this->length); 55 | } 56 | 57 | // If no length is specified return full logger name 58 | else { 59 | $this->cache[$name] = $name; 60 | } 61 | } 62 | 63 | return $this->cache[$name]; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterMDC.php: -------------------------------------------------------------------------------- 1 | option) && $this->option !== '') { 38 | $this->key = $this->option; 39 | } 40 | } 41 | 42 | public function convert(LoggerLoggingEvent $event) { 43 | if (isset($this->key)) { 44 | return $event->getMDC($this->key); 45 | } else { 46 | $buff = array(); 47 | $map = $event->getMDCMap(); 48 | foreach($map as $key => $value) { 49 | $buff []= "$key=$value"; 50 | } 51 | return implode(', ', $buff); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterMessage.php: -------------------------------------------------------------------------------- 1 | getRenderedMessage(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterMethod.php: -------------------------------------------------------------------------------- 1 | getLocationInformation()->getMethodName(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterNDC.php: -------------------------------------------------------------------------------- 1 | getNDC(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterNewLine.php: -------------------------------------------------------------------------------- 1 | getRelativeTime(); 34 | return number_format($ts, 4); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterRequest.php: -------------------------------------------------------------------------------- 1 | option) && $this->option !== '') { 52 | $key = $this->option; 53 | } 54 | 55 | /* 56 | * There is a bug in PHP which doesn't allow superglobals to be 57 | * accessed when their name is stored in a variable, e.g.: 58 | * 59 | * $name = '_SERVER'; 60 | * $array = $$name; 61 | * 62 | * This code does not work when run from within a method (only when run 63 | * in global scope). But the following code does work: 64 | * 65 | * $name = '_SERVER'; 66 | * global $$name; 67 | * $array = $$name; 68 | * 69 | * That's why global is used here. 70 | */ 71 | global ${$this->name}; 72 | 73 | // Check the given superglobal exists. It is possible that it is not initialized. 74 | if (!isset(${$this->name})) { 75 | $class = get_class($this); 76 | trigger_error("log4php: $class: Cannot find superglobal variable \${$this->name}.", E_USER_WARNING); 77 | return; 78 | } 79 | 80 | $source = ${$this->name}; 81 | 82 | // When the key is set, display the matching value 83 | if (isset($key)) { 84 | if (isset($source[$key])) { 85 | $this->value = $source[$key]; 86 | } 87 | } 88 | 89 | // When the key is not set, display all values 90 | else { 91 | $values = array(); 92 | foreach($source as $key => $value) { 93 | $values[] = "$key=$value"; 94 | } 95 | $this->value = implode(', ', $values); 96 | } 97 | } 98 | 99 | public function convert(LoggerLoggingEvent $event) { 100 | return $this->value; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /web/log4php/pattern/LoggerPatternConverterThrowable.php: -------------------------------------------------------------------------------- 1 | getThrowableInformation(); 33 | if (isset($info)) { 34 | $ex = $info->getThrowable(); 35 | return (string) $ex . PHP_EOL; 36 | } 37 | return ''; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /web/log4php/renderers/LoggerRenderer.php: -------------------------------------------------------------------------------- 1 | input to a string. 32 | * @param mixed $input The entity to render. 33 | * @return string The rendered string. 34 | */ 35 | public function render($input); 36 | } 37 | -------------------------------------------------------------------------------- /web/log4php/renderers/LoggerRendererDefault.php: -------------------------------------------------------------------------------- 1 | print_r. 25 | * 26 | * @package log4php 27 | * @subpackage renderers 28 | * @since 0.3 29 | */ 30 | class LoggerRendererDefault implements LoggerRenderer { 31 | 32 | /** @inheritdoc */ 33 | public function render($input) { 34 | return print_r($input, true); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /web/log4php/renderers/LoggerRendererException.php: -------------------------------------------------------------------------------- 1 | reset(); 48 | } 49 | 50 | /** 51 | * Adds a renderer to the map. 52 | * 53 | * If a renderer already exists for the given $renderedClass it 54 | * will be overwritten without warning. 55 | * 56 | * @param string $renderedClass The name of the class which will be 57 | * rendered by the renderer. 58 | * @param string $renderingClass The name of the class which will 59 | * perform the rendering. 60 | */ 61 | public function addRenderer($renderedClass, $renderingClass) { 62 | // Check the rendering class exists 63 | if (!class_exists($renderingClass)) { 64 | trigger_error("log4php: Failed adding renderer. Rendering class [$renderingClass] not found."); 65 | return; 66 | } 67 | 68 | // Create the instance 69 | $renderer = new $renderingClass(); 70 | 71 | // Check the class implements the right interface 72 | if (!($renderer instanceof LoggerRenderer)) { 73 | trigger_error("log4php: Failed adding renderer. Rendering class [$renderingClass] does not implement the LoggerRenderer interface."); 74 | return; 75 | } 76 | 77 | // Convert to lowercase since class names in PHP are not case sensitive 78 | $renderedClass = strtolower($renderedClass); 79 | 80 | $this->map[$renderedClass] = $renderer; 81 | } 82 | 83 | /** 84 | * Sets a custom default renderer class. 85 | * 86 | * TODO: there's code duplication here. This method is almost identical to 87 | * addRenderer(). However, it has custom error messages so let it sit for 88 | * now. 89 | * 90 | * @param string $renderingClass The name of the class which will 91 | * perform the rendering. 92 | */ 93 | public function setDefaultRenderer($renderingClass) { 94 | // Check the class exists 95 | if (!class_exists($renderingClass)) { 96 | trigger_error("log4php: Failed setting default renderer. Rendering class [$renderingClass] not found."); 97 | return; 98 | } 99 | 100 | // Create the instance 101 | $renderer = new $renderingClass(); 102 | 103 | // Check the class implements the right interface 104 | if (!($renderer instanceof LoggerRenderer)) { 105 | trigger_error("log4php: Failed setting default renderer. Rendering class [$renderingClass] does not implement the LoggerRenderer interface."); 106 | return; 107 | } 108 | 109 | $this->defaultRenderer = $renderer; 110 | } 111 | 112 | /** 113 | * Returns the default renderer. 114 | * @var LoggerRenderer 115 | */ 116 | public function getDefaultRenderer() { 117 | return $this->defaultRenderer; 118 | } 119 | 120 | /** 121 | * Finds the appropriate renderer for the given input, and 122 | * renders it (i.e. converts it to a string). 123 | * 124 | * @param mixed $input Input to render. 125 | * @return string The rendered contents. 126 | */ 127 | public function findAndRender($input) { 128 | if ($input === null) { 129 | return null; 130 | } 131 | 132 | // For objects, try to find a renderer in the map 133 | if(is_object($input)) { 134 | $renderer = $this->getByClassName(get_class($input)); 135 | if (isset($renderer)) { 136 | return $renderer->render($input); 137 | } 138 | } 139 | 140 | // Fall back to the default renderer 141 | return $this->defaultRenderer->render($input); 142 | } 143 | 144 | /** 145 | * Returns the appropriate renderer for a given object. 146 | * 147 | * @param mixed $object 148 | * @return LoggerRenderer Or null if none found. 149 | */ 150 | public function getByObject($object) { 151 | if (!is_object($object)) { 152 | return null; 153 | } 154 | return $this->getByClassName(get_class($object)); 155 | } 156 | 157 | /** 158 | * Returns the appropriate renderer for a given class name. 159 | * 160 | * If no renderer could be found, returns NULL. 161 | * 162 | * @param string $class 163 | * @return LoggerRendererObject Or null if not found. 164 | */ 165 | public function getByClassName($class) { 166 | for(; !empty($class); $class = get_parent_class($class)) { 167 | $class = strtolower($class); 168 | if(isset($this->map[$class])) { 169 | return $this->map[$class]; 170 | } 171 | } 172 | return null; 173 | } 174 | 175 | /** Empties the renderer map. */ 176 | public function clear() { 177 | $this->map = array(); 178 | } 179 | 180 | /** Resets the renderer map to it's default configuration. */ 181 | public function reset() { 182 | $this->defaultRenderer = new LoggerRendererDefault(); 183 | $this->clear(); 184 | $this->addRenderer('Exception', 'LoggerRendererException'); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /web/log4php/xml/log4php.dtd: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 54 | 55 | 56 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 72 | 73 | 74 | 77 | 78 | 79 | 82 | 83 | 84 | 85 | 89 | 90 | 91 | 94 | 95 | 96 | 99 | 100 | 101 | 102 | 103 | 107 | 108 | 109 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 128 | 129 | 130 | 131 | 132 | 138 | 139 | 140 | 141 | 142 | 143 | 149 | -------------------------------------------------------------------------------- /web/login.php: -------------------------------------------------------------------------------- 1 | debug("loginout"); 28 | $_SESSION['islogin']=false; 29 | header("location: login.html"); 30 | }else 31 | { 32 | $logger->debug("login"); 33 | $email = $_POST[ 'email']; 34 | $_SESSION['account']=$email; 35 | 36 | 37 | 38 | if(check_login($email,$_POST[ 'password'])) 39 | { 40 | $_SESSION['islogin']=true; 41 | $_SESSION['time']=time(); 42 | $tokenstr="${bison_token_key}${_SESSION['account']}${_SESSION['time']}"; 43 | $token=md5($tokenstr); 44 | $logger->debug($tokenstr); 45 | $logger->debug($token); 46 | $_SESSION['token']="account|${_SESSION['account']}|${_SESSION['time']}|$token"; 47 | header("location: index.php"); 48 | }else 49 | { 50 | 51 | $_SESSION['islogin']=false; 52 | header("location: login.html"); 53 | } 54 | } 55 | 56 | 57 | 58 | ?> 59 | -------------------------------------------------------------------------------- /web/webdisk.log: -------------------------------------------------------------------------------- 1 | Wed Sep 9 07:57:21 2015,077 [1332] DEBUG root - loginout 2 | Wed Sep 9 07:57:41 2015,422 [1333] DEBUG root - abc:azzzbc@gmail.comddfaaaaaaaa 3 | Wed Sep 9 08:04:06 2015,593 [1319] DEBUG root - abc:zhula1111ngren@gmail.com1111111 4 | Wed Sep 9 08:04:52 2015,273 [1318] DEBUG root - login 5 | Wed Sep 9 08:04:52 2015,274 [1318] DEBUG root - 45a1df1c9e2656e4f4c742cf-4753775dabc@gmail.com1441811092 6 | Wed Sep 9 08:04:52 2015,274 [1318] DEBUG root - 0900b893ae380b714f8b9148c05c082a 7 | -------------------------------------------------------------------------------- /websocket_server/__init__.py: -------------------------------------------------------------------------------- 1 | from .websocket_server import * 2 | --------------------------------------------------------------------------------