import console; import inet.ftp; var p = string.split(_CMDLINE," "); if(p[1]!=null and p[2]!=null and p[3]!=null and p[4]!=null and p[5]!=null){ ftp = inet.ftp(p[1],p[2],p[3]); if(!ftp){ console.log("请输入正确的服务器参数"); return; } file = ftp.upload(p[4],p[5],2) ftp.close() }else{ console.log('参数:服务器 用户名 密码 源文件 目标ftp路径\n所有参数不能包含空格'); } console.close();
import console; import mysql.client; //本地数据库 console.log("正在连接本地数据库服务器..."); var localdb,err = mysql.client( server = "localhost"; uid = "root"; pwd = "123456"; ); if(!localdb){ console.log("连接数据库失败",err) return; } localdb.selectDb("blog"); console.log("本地数据库连接成功"); //远端数据库 console.log("正在连接远端数据库服务器..."); var remotedb,err = mysql.client( server = "8.8.8.8"; uid = "xxxxx"; pwd = "xxxxx"; ); if(!remotedb){ console.log("连接数据库失败",err) return; } remotedb.selectDb("blog"); console.log("远端数据库连接成功"); //同步本地日志到远端 console.log("同步本地日志到远端"); //查询最大ID var result = remotedb.query("SELECT max(ID) as MAXID FROM wp_posts"); var remote_post_max_id = result.fetchObject()["MAXID"]; //console.log("远端最大ID:"++remote_post_max_id) result.free(); //查询本地 var result = localdb.query("SELECT ID FROM wp_posts where ID>"++tostring(remote_post_max_id)); var local_post_sync_count = result.numRows(); console.log("需同步"++local_post_sync_count) result.free(); //执行同步 if(local_post_sync_count>0){ //首先替换网址 localdb.exec("update wp_posts set post_content=replace(post_content,'thinkai.net','thinkai.net') where ID>"++tostring(remote_post_max_id)); var result = localdb.query("SELECT * FROM wp_posts where ID>"++tostring(remote_post_max_id)); for(i=1;local_post_sync_count){ var row = result.fetchObject(); console.log(string.concat("同步ID:",row['ID']," 标题:",row['post_title'])); remotedb.exec("insert into wp_posts values (@ID, @post_author, @post_date, @post_date_gmt, @post_content, @post_title, @post_excerpt, @post_status, @comment_status, @ping_status, @post_password, @post_name, @to_ping, @pinged, @post_modified, @post_modified_gmt, @post_content_filtered, @post_parent, @guid, @menu_order, @post_type, @post_mime_type, @comment_count)",row) } } //同步本地日志分类到远端 console.log("同步本地日志分类到远端"); //查询最大ID var result = remotedb.query("SELECT max(object_id) as MAXID FROM wp_term_relationships"); var remote_term_max_id = result.fetchObject()["MAXID"]; result.free(); //查询本地 var result = localdb.query("SELECT object_id FROM wp_term_relationships where object_id>"++tostring(remote_term_max_id)); var local_term_sync_count = result.numRows(); console.log("需同步"++local_term_sync_count) result.free(); //执行同步 if(local_term_sync_count>0){ var result = localdb.query("SELECT * FROM wp_term_relationships where object_id>"++tostring(remote_term_max_id)); for(i=1;local_term_sync_count){ var row = result.fetchObject(); console.log(string.concat("同步ID:",row['object_id'])); remotedb.exec("insert into wp_term_relationships values (@object_id, @term_taxonomy_id, @term_order)",row) } } //同步本地分类项目到远端 console.log("同步本地分类项目到远端"); //查询最大ID var result = remotedb.query("SELECT max(term_taxonomy_id) as MAXID FROM wp_term_taxonomy"); var remote_termt_max_id = result.fetchObject()["MAXID"]; result.free(); //查询本地 var result = localdb.query("SELECT term_taxonomy_id FROM wp_term_taxonomy where term_taxonomy_id>"++tostring(remote_termt_max_id)); var local_termt_sync_count = result.numRows(); console.log("需同步"++local_termt_sync_count) result.free(); //执行同步 if(local_termt_sync_count>0){ var result = localdb.query("SELECT * FROM wp_term_taxonomy where term_taxonomy_id>"++tostring(remote_termt_max_id)); for(i=1;local_termt_sync_count){ var row = result.fetchObject(); console.log(string.concat("同步ID:",row['term_taxonomy_id'])); remotedb.exec("insert into wp_term_taxonomy values (@term_taxonomy_id, @term_id, @taxonomy, @description, @parent, @count)",row) } } //查询最大ID var result = remotedb.query("SELECT max(term_id) as MAXID FROM wp_terms"); var remote_term_max_id = result.fetchObject()["MAXID"]; result.free(); //查询本地 var result = localdb.query("SELECT term_id FROM wp_terms where term_id>"++tostring(remote_term_max_id)); var local_term_sync_count = result.numRows(); console.log("需同步"++local_term_sync_count) result.free(); //执行同步 if(local_term_sync_count>0){ var result = localdb.query("SELECT * FROM wp_terms where term_id>"++tostring(remote_term_max_id)); for(i=1;local_term_sync_count){ var row = result.fetchObject(); console.log(string.concat("同步ID:",row['term_id'])); remotedb.exec("insert into wp_terms values (@term_id, @name, @slug, @term_group)",row) } } localdb.close(); remotedb.close(); console.pause();
首先你得有个获取队列情况的接口。如果使用ami的话太麻烦,接收的数据控制不好断节,所以我用了php+shell的形式获取数据。由于是局域网内使用,所以没加验证,有需求的自己加一下。
vi /var/www/html/cli.php
按i进入插入模式,粘贴上如下代码:
<?php if(isset($_GET["cmd"])){ //先判断是否是预期参数 $fp=popen("asterisk -x \"".$_GET["cmd"]."\"","r"); //asterisk -x单句命令执行 while(!feof($fp)) echo fgets($fp,4096); pclose($fp); } ?>
按Esc输入":wq"保存退出。好了这个接口就可以使用来执行Asterisk CLI命令了。
然后通过你自己的坐席数据库接口,结合ahk写一个客户端。
;数据库配置信息 host = 135.230.71.1 api = http://%host%/sqlapi.php #MaxMem 1024 ;检查连通性 if Not InStr(ping_info := ping(host),"正常") { MsgBox, 4112, 网络错误, % ping_info ExitApp } ;创建GUI gui, add, edit, x0 y0 w800 h400 vshow, gui, show, , 本地呼叫系统坐席队列监控 gui, +AlwaysOnTop +Resize ;循环监控坐席状态 3秒间隔 Loop { out = Queue := QueueStatus() ;获取队列状态数组 tp := get_result_obj("select 队列,业务 from [我是口令呼叫系统数据库].[dbo].[呼叫系统业务分派] where 状态=1 and ((cast(getdate() as time) between 开始时间1 and 结束时间1) or (cast(getdate() as time) between 开始时间2 and 结束时间2));") ;这是一个获取当前正在执行的任务的语句 task := [] for k,v in tp task[v[1]] := v[2] tp := get_result_obj("select 分机,工号,姓名 from [我是口令呼叫系统数据库].[dbo].[呼叫系统分机信息] where [工号] is not null") ;获取已经登记的坐席信息 user := [] for k,v in tp user[v[1]] := {"id":v[2],"name":v[3]} ;格式化输出 for group,gv in Queue { out .= task[group] "(" group ") 策略:" gv["strategy"] " " gv["incall"] "个等待来电 平均摘机时间:" gv["holdtime"] "(秒)平均通话时长:" gv["talktime"] "(秒)`n" for exten,mv in gv["member"] { sp = loop % 20-strlen(user[exten]["name"]) sp .= " " ;很笨的一种汉化替换方法 status := RegExReplace(mv["status"],"In use","通话中") status := RegExReplace(status,"Not in use","空闲") status := RegExReplace(status,"Ringing","振铃") status := RegExReplace(status,"Unavailable","不可用") status := RegExReplace(status,"On hold","保持") out .= " 坐席:" user[exten]["name"] "(" user[exten]["id"] " " exten ")" sp " 类型:" mv["kind"] " 状态:" status " 本次签入后呼叫量:" mv["callcount"] " 最后一次摘机:" mv["lastcalltime"] "秒前`n" } for k,cv in gv["caller"] out .= " 来电:" k "." cv["phone"] " 等待时间:" cv["wait"] "秒`n" out .= "`n" } GuiControl, , show, % out Sleep, 3000 } Return ;界面调整尺寸 GuiSize: GuiControl, move, show, % "w" A_GuiWidth "h" A_GuiHeight Return ;获取状态函数 QueueStatus(){ src := URLDownloadToVar("http://135.230.71.2/cli.php?cmd=queue show") ;你的Asterisk的cli接口 queues := [] Loop, Parse, src, `n, `r { line := A_LoopField if RegExMatch(line,"(\d+) has (\d+) calls \(max unlimited\) in '(\w+)' strategy \((\d+)s holdtime, (\d+)s talktime\), W:\d+, C:\d+, A:\d+, SL:[0-9\.]+% within \d+s",qtm) ;队列标题匹配 { cqueue := qtm1 queues[cqueue] := {"incall":qtm2,"strategy":qtm3,"holdtime":qtm4,"talktime":qtm5,member:{},caller:{}} } else if RegExMatch(line,"\s+sip/(\d+) with penalty 1 \(ringinuse disabled\) \((\w+)\) \((.+)\) has taken (\d+) calls \(last was (\d+) secs ago\)",mcm) ;坐席匹配1 queues[cqueue]["member"][mcm1] := {"kind":mcm2,"status":mcm3,"callcount":mcm4,"lastcalltime":mcm5} else if RegExMatch(line,"\s+sip/(\d+) with penalty 1 \(ringinuse disabled\) \((\w+)\) \((.+)\) has taken no calls yet",mcm) ;坐席匹配2 queues[cqueue]["member"][mcm1] := {"kind":mcm2,"status":mcm3,"callcount":0,"lastcalltime":"NULL"} else if RegExMatch(line,"\s+(\d+). DAHDI/i1/(\d+)-\w+ \(wait: 0:(\d+), prio: 0\)",ccm) ;来电匹配 queues[cqueue]["caller"][ccm1] := {"phone":ccm2,"wait":ccm3} } Return queues } ;返回csv带标题格式查询结果 get_result_with_colname(sql){ global api result := URLDownloadToVar(api "?str=" urlencode(sql "我是口令") "&o=1","UTF-8") return RegExReplace(result,"`n$","") } ;返回csv查询结果 get_result(sql){ global api result := URLDownloadToVar(api "?str=" urlencode(sql "我是口令"),"UTF-8") return RegExReplace(result,"`n$","") } ;返回查询数组 get_result_obj(sql){ global api result := URLDownloadToVar(api "?str=" urlencode(sql "我是口令"),"UTF-8") ;return RegExReplace(result,"`n$","") line := strsplit(result,"`n","`r") for k,v in line { if v line[k] := strsplit(v,",") Else line.remove(k) } return line } ;返回1行数据 get_1_result(sql){ global api result := URLDownloadToVar(api "?str=" urlencode(sql "我是口令"),"UTF-8") return RegExReplace(result,"^([^\n]*)\n.*$","$1") } ;返回执行影响结果 get_rowcount(sql){ global api result := URLDownloadToVar(api "?str=" urlencode(sql "我是口令") "&o=2","UTF-8") return RegExReplace(result,"^([^\n]*)\n.*$","$1") } URLDownloadToVar(url, Encoding = "",Method="GET",postData=""){ ;网址,编码,请求方式,post数据 hObject:=ComObjCreate("WinHttp.WinHttpRequest.5.1") if Method = GET { Try { hObject.Open("GET",url) hObject.Send() } catch e return -1 } else if Method = POST { Try { hObject.Open("POST",url,False) hObject.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") hObject.Send(postData) } catch e return -1 } if (Encoding && hObject.ResponseBody) { oADO := ComObjCreate("adodb.stream") oADO.Type := 1 oADO.Mode := 3 oADO.Open() oADO.Write(hObject.ResponseBody) oADO.Position := 0 oADO.Type := 2 oADO.Charset := Encoding return oADO.ReadText(), oADO.Close() } return hObject.ResponseText } Ansi2UTF8(sString) { Ansi2Unicode(sString, wString, 0) Unicode2Ansi(wString, zString, 65001) Return zString } UTF82Ansi(zString) { Ansi2Unicode(zString, wString, 65001) Unicode2Ansi(wString, sString, 0) Return sString } Ansi2Unicode(ByRef sString, ByRef wString, CP = 0) { nSize := DllCall("MultiByteToWideChar" , "Uint", CP , "Uint", 0 , "Uint", &sString , "int", -1 , "Uint", 0 , "int", 0) VarSetCapacity(wString, nSize * 2) DllCall("MultiByteToWideChar" , "Uint", CP , "Uint", 0 , "Uint", &sString , "int", -1 , "Uint", &wString , "int", nSize) } Unicode2Ansi(ByRef wString, ByRef sString, CP = 0) { nSize := DllCall("WideCharToMultiByte" , "Uint", CP , "Uint", 0 , "Uint", &wString , "int", -1 , "Uint", 0 , "int", 0 , "Uint", 0 , "Uint", 0) VarSetCapacity(sString, nSize) DllCall("WideCharToMultiByte" , "Uint", CP , "Uint", 0 , "Uint", &wString , "int", -1 , "str", sString , "int", nSize , "Uint", 0 , "Uint", 0) } urlencode(string){ string := Ansi2UTF8(string) StringLen, len, string Loop % len { SetFormat, IntegerFast, hex StringMid, out, string, %A_Index%, 1 hex := Asc(out) hex2 := hex StringReplace, hex, hex, 0x, , All SetFormat, IntegerFast, d hex2 := hex2 If (hex2==33 || (hex2>=39 && hex2 <=42) || hex2==45 || hex2 ==46 || (hex2>=48 && hex2<=57) || (hex2>=65 && hex2<=90) || hex2==95 || (hex2>=97 && hex2<=122) || hex2==126) content .= out Else content .= "`%" hex } Return content } ping(ip){ FileEncoding, RunWait, %ComSpec% /c ping -n 1 %ip% >%A_Temp%\ahk_ping.tmp, , Hide FileRead, content, %A_Temp%\ahk_ping.tmp StringReplace, content, content, `r, , All StringSplit, var, content, `n If content Contains 请求超时,Request timed out Return "请求超时" If content Contains 找不到主机,could not find host Return "找不到主机 " If content Contains 无法访问目标主机,Destination host unreachable Return "无法访问目标主机 " Else { time := RegExReplace(var3, "(来自|Reply from) \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}[\s的回复|]*: (字节|bytes)=\d{1,3}\ (时间|time)[=<](\d{1,3})ms TTL=\d{1,3}","$4") Return "正常 time:" time "ms" } FileEncoding, UTF-8 } ;调试用 输出数组 show_obj(obj,menu_name:=""){ static id if menu_name = { main = 1 id++ menu_name := id } Menu, % menu_name, add, Menu, % menu_name, DeleteAll for k,v in obj { if (IsObject(v)) { id++ submenu_name := id Menu, % submenu_name, add, Menu, % submenu_name, DeleteAll Menu, % menu_name, add, % k ? "【" k "】[obj]" : "", :%submenu_name% show_obj(v,submenu_name) } Else { Menu, % menu_name, add, % k ? "【" k "】" v: "", MenuHandler } } if main = 1 menu,% menu_name, show MenuHandler: return } GuiClose: ExitApp
好了,看下效果:
RunAs, Administrator, ;用户名 密码 try Run, %ComSpec% /c, , hide catch error ;错误对象 MsgBox, 4112, % error["Message"], % error["Extra"] RunAs
;加载你的dll 注意像下面这种文件名里面有多个点的写全文件名 hModule := DllCall("LoadLibrary", "Str", "time.cqp.dll", "Ptr") ;无参数类型返回字符串 ;Ptr1 := DllCall("time.cqp.dll\info") ;返回指针 ;带参数类型返回字符串 ;注意一定要用numput,不然指针飞了报0x0000005的错 ;长度自己定好 VarSetCapacity(p1,3),VarSetCapacity(p2,3),VarSetCapacity(p3,3),VarSetCapacity(p4,3) numput(0x313233,p1),numput(0x343536,p2),numput(0x373839,p3),numput(0x404142,p4) ;注意这里指针一定要用&变量的格式传入指针 参数记得写全 不然报错-4 Ptr2 := DllCall("time.cqp.dll\plugmain","Ptr",&p1,"Ptr",&p2,"Ptr",&p3,"Ptr",&p4,"Ptr",&p4) Error := ErrorLevel ;保存错误值 Str = ;初始输出字符串变量 Loop { UChar := NumGet(0+Ptr2,A_index-1,"UChar") if (UChar=0x0) ;以0结束 break Str .= Chr(UChar) } MsgBox % Str "`n" Error
从AHK_L 46+开始增加了StrPut()和StrGet()来读取写入字符串到内存。
hModule := DllCall("LoadLibrary", "Str", "time.cqp.dll", "Ptr") StrPutVar("你",p1),StrPutVar("是",p2),StrPutVar("谁",p3),StrPutVar("啊",p4),StrPutVar("?",p5) Ptr2 := DllCall("time.cqp.dll\plugmain","Ptr",&p1,"Ptr",&p2,"Ptr",&p3,"Ptr",&p4,"Ptr",&p5) Error := ErrorLevel ;保存错误值 MsgBox % StrGet(Ptr2) "`n" Error StrPutVar(string, ByRef var, encoding:="") { ; 确定容量. VarSetCapacity( var, StrPut(string, encoding) ; StrPut 返回字符数, 但 VarSetCapacity 需要字节数. * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) ) ; 复制或转换字符串. return StrPut(string, &var, encoding) }
;Autohotkey+Web Short Message(com.wangtai.smstwoman)短信接口 ;Thinkai@2015-01-05 ;注意每次运行APP的管理网址都不一样 ManageUrl = http://192.168.1.106:1984/8119 ;获取参数 RegExMatch(ManageUrl,"^(http://.*:\d*/)(\d{4})",parameter) global parameter1 global parameter2 ;运用实例 ;发短信 if (SendMsg(10001,7)=1) MsgBox, 64, 提示, 短信发送成功 ;接收回复 NewMessage := GetNewMsg() From := NewMessage[1]["person"] ? NewMessage[1]["person"] "(" NewMessage[1]["address"] ")" : "未知(" NewMessage[1]["address"] ")" MsgBox % "From:" From "`n" NewMessage[1]["body"] ;获取联系人 Contact := GetContacts() for k,v in Contact { MsgBox, 64, 提示, 第一个联系人是%v%`,号码是%k% Return } ;获取新消息函数(调用后收到的) GetNewMsg(){ ;返回数组说明 ;数组[1]: ; _id:消息ID ; address:号码 ; body:短信正文 ; date:收信Uinx时间戳 ; person:联系人 Loop { res := URLDownloadToVar(parameter1 "get_new_msg/" parameter2 "/", "utf-8","POST") ;获取最新短信的JSON数据 if (strlen(res)>2) Return json_toobj(res) Sleep, 100 } } ;获取联系人函数 GetContacts(){ obj := {} ;初始数组 res := URLDownloadToVar(parameter1 "get_contacts/" parameter2 "/", "utf-8","POST") ;获取联系人的JSON数据 ;处理格式问题 StringTrimLeft, res, res, 1 StringTrimRight, res, res, 1 StringSplit, var, res, `, loop % var0 { tmp_var := var%A_index% RegExMatch(tmp_var,"""(.*)"":""(.*)""",m) m1 := RegExReplace(m1,"\s","") m1 := RegExReplace(m1,"\+86","") obj["" m1] := m2 ;注意此处数组key的类型 } Return obj ;返回数组 obj[电话号码] := 联系人姓名 } ;发短信函数 SendMsg(to,msg){ ;号码,消息 msg := urlencode(msg) Return URLDownloadToVar(parameter1 "send/" parameter2 "/" to "/", "utf-8","POST","msg=" msg) } URLDownloadToVar(url, Encoding = "",Method="GET",postData=""){ ;网址,编码,请求方式,post数据 hObject:=ComObjCreate("WinHttp.WinHttpRequest.5.1") if Method = GET { hObject.Open("GET",url) Try hObject.Send() catch e return -1 } else if Method = POST { hObject.Open("POST",url,False) hObject.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") Try hObject.Send(postData) catch e return -1 } if Encoding { oADO := ComObjCreate("adodb.stream") oADO.Type := 1 oADO.Mode := 3 oADO.Open() oADO.Write(hObject.ResponseBody) oADO.Position := 0 oADO.Type := 2 oADO.Charset := Encoding return oADO.ReadText(), oADO.Close() } return hObject.ResponseText } urlencode(string){ string := Ansi2UTF8(string) StringLen, len, string Loop % len { SetFormat, IntegerFast, hex ;运算结果为HEX StringMid, out, string, %A_Index%, 1 hex := Asc(out) ;获取单字节ascii值 hex2 := hex ;另存变量 StringReplace, hex, hex, 0x, , All SetFormat, IntegerFast, d hex2 := hex2 ;十进制化 ;判断是否可见单字节字符 是则直接连接 否则编码 If (hex2==33 || (hex2>=39 && hex2 <=42) || hex2==45 || hex2 ==46 || (hex2>=48 && hex2<=57) || (hex2>=65 && hex2<=90) || hex2==95 || (hex2>=97 && hex2<=122) || hex2==126) content .= out Else content .= "`%" hex } Return content } Ansi2Oem(sString) { Ansi2Unicode(sString, wString, 0) Unicode2Ansi(wString, zString, 1) Return zString } Oem2Ansi(zString) { Ansi2Unicode(zString, wString, 1) Unicode2Ansi(wString, sString, 0) Return sString } Ansi2UTF8(sString) { Ansi2Unicode(sString, wString, 0) Unicode2Ansi(wString, zString, 65001) Return zString } UTF82Ansi(zString) { Ansi2Unicode(zString, wString, 65001) Unicode2Ansi(wString, sString, 0) Return sString } Ansi2Unicode(ByRef sString, ByRef wString, CP = 0) { nSize := DllCall("MultiByteToWideChar" , "Uint", CP , "Uint", 0 , "Uint", &sString , "int", -1 , "Uint", 0 , "int", 0) VarSetCapacity(wString, nSize * 2) DllCall("MultiByteToWideChar" , "Uint", CP , "Uint", 0 , "Uint", &sString , "int", -1 , "Uint", &wString , "int", nSize) } Unicode2Ansi(ByRef wString, ByRef sString, CP = 0) { nSize := DllCall("WideCharToMultiByte" , "Uint", CP , "Uint", 0 , "Uint", &wString , "int", -1 , "Uint", 0 , "int", 0 , "Uint", 0 , "Uint", 0) VarSetCapacity(sString, nSize) DllCall("WideCharToMultiByte" , "Uint", CP , "Uint", 0 , "Uint", &wString , "int", -1 , "str", sString , "int", nSize , "Uint", 0 , "Uint", 0) } json_toobj(str){ quot := """" ; firmcoded specifically for readability. Hardcode for (minor) performance gain ws := "`t`n`r " Chr(160) ; whitespace plus NBSP. This gets trimmed from the markup obj := {} ; dummy object objs := [] ; stack keys := [] ; stack isarrays := [] ; stack literals := [] ; queue y := nest := 0 ; First pass swaps out literal strings so we can parse the markup easily StringGetPos, z, str, %quot% ; initial seek while !ErrorLevel { ; Look for the non-literal quote that ends this string. Encode literal backslashes as '\u005C' because the ; '\u..' entities are decoded last and that prevents literal backslashes from borking normal characters StringGetPos, x, str, %quot%,, % z + 1 while !ErrorLevel { StringMid, key, str, z + 2, x - z - 1 StringReplace, key, key, \\, \u005C, A If SubStr( key, 0 ) != "\" Break StringGetPos, x, str, %quot%,, % x + 1 } ; StringReplace, str, str, %quot%%t%%quot%, %quot% ; this might corrupt the string str := ( z ? SubStr( str, 1, z ) : "" ) quot SubStr( str, x + 2 ) ; this won't ; Decode entities StringReplace, key, key, \%quot%, %quot%, A StringReplace, key, key, \b, % Chr(08), A StringReplace, key, key, \t, % A_Tab, A StringReplace, key, key, \n, `n, A StringReplace, key, key, \f, % Chr(12), A StringReplace, key, key, \r, `r, A StringReplace, key, key, \/, /, A while y := InStr( key, "\u", 0, y + 1 ) if ( A_IsUnicode || Abs( "0x" SubStr( key, y + 2, 4 ) ) < 0x100 ) key := ( y = 1 ? "" : SubStr( key, 1, y - 1 ) ) Chr( "0x" SubStr( key, y + 2, 4 ) ) SubStr( key, y + 6 ) literals.insert(key) StringGetPos, z, str, %quot%,, % z + 1 ; seek } ; Second pass parses the markup and builds the object iteratively, swapping placeholders as they are encountered key := isarray := 1 ; The outer loop splits the blob into paths at markers where nest level decreases Loop Parse, str, % "]}" { StringReplace, str, A_LoopField, [, [], A ; mark any array open-brackets ; This inner loop splits the path into segments at markers that signal nest level increases Loop Parse, str, % "[{" { ; The first segment might contain members that belong to the previous object ; Otherwise, push the previous object and key to their stacks and start a new object if ( A_Index != 1 ) { objs.insert( obj ) isarrays.insert( isarray ) keys.insert( key ) obj := {} isarray := key := Asc( A_LoopField ) = 93 } ; arrrrays are made by pirates and they have index keys if ( isarray ) { Loop Parse, A_LoopField, `,, % ws "]" if ( A_LoopField != "" ) obj[key++] := A_LoopField = quot ? literals.remove(1) : A_LoopField } ; otherwise, parse the segment as key/value pairs else { Loop Parse, A_LoopField, `, Loop Parse, A_LoopField, :, % ws if ( A_Index = 1 ) key := A_LoopField = quot ? literals.remove(1) : A_LoopField else if ( A_Index = 2 && A_LoopField != "" ) obj[key] := A_LoopField = quot ? literals.remove(1) : A_LoopField } nest += A_Index > 1 } ; Loop Parse, str, % "[{" If !--nest Break ; Insert the newly closed object into the one on top of the stack, then pop the stack pbj := obj obj := objs.remove() obj[key := keys.remove()] := pbj If ( isarray := isarrays.remove() ) key++ } ; Loop Parse, str, % "]}" Return obj }
#下载 wget http://fossies.org/unix/privat/DenyHosts-2.6.tar.gz #解压 tar -zxvf DenyHosts-2.6.tar.gz #为了方便改个名 mv DenyHosts-2.6 denyhost #进入目录 cd denyhost #安装python yum install python -y #安装denyhost,脚本 python setup.py install #进入配置目录 cd /usr/share/denyhosts/ #为了方便改变配置文件名称 cp daemon-control-dist daemon-control #修改服务文件名称 cp denyhosts.cfg-dist denyhosts.cfg #提高安全级别,修改权限 chown root daemon-control chmod 700 daemon-control #创建启动服务连接 ln -s /usr/share/denyhosts/daemon-control /etc/init.d/denyhosts #添加启动项 chkconfig --add denyhosts #配置denyhosts.cfg vi denyhosts.cfg
填充以下内容
SECURE_LOG = /var/log/secure #ssh日志文件 HOSTS_DENY = /etc/hosts.deny #将阻止IP写入到hosts.deny PURGE_DENY = 5m #过多久后清除已经禁止的,其中w代表周,d代表天,h代表小时,s代表秒,m代表分钟 BLOCK_SERVICE = sshd #阻止服务名 DENY_THRESHOLD_INVALID = 5 #允许无效用户(在/etc/passwd未列出)登录失败次数,允许无效用户登录失败的次数. DENY_THRESHOLD_VALID = 5 #允许普通用户登录失败的次数 DENY_THRESHOLD_ROOT = 5 #允许root登录失败的次数 DENY_THRESHOLD_RESTRICTED = 1 #设定 deny host 写入到该资料夹 WORK_DIR = /usr/share/denyhosts/data #将deny的host或ip纪录到Work_dir中 SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS = YES HOSTNAME_LOOKUP=YES #是否做域名反解 LOCK_FILE = /var/lock/subsys/denyhosts #将DenyHOts启动的pid纪录到LOCK_FILE中,已确保服务正确启动,防止同时启动多个服务。 ADMIN_EMAIL = denyhosts@163.com #设置管理员邮件地址 SMTP_HOST = localhost SMTP_PORT = 25 SMTP_FROM = DenyHosts SMTP_SUBJECT = DenyHosts Report AGE_RESET_VALID=1d #有效用户登录失败计数归零的时间 AGE_RESET_ROOT=1d #root用户登录失败计数归零的时间 AGE_RESET_RESTRICTED=5d #用户的失败登录计数重置为0的时间(/usr/share/denyhosts/data/restricted-usernames) AGE_RESET_INVALID=10d #无效用户登录失败计数归零的时间 DAEMON_LOG = /var/log/denyhosts #自己的日志文件 DAEMON_SLEEP = 30s DAEMON_PURGE = 5m #该项与PURGE_DENY 设置成一样,也是清除hosts.deniedssh 用户的时间
如果想删除一个已经禁止的主机IP,并加入到允许主机例表,只在 /etc/hosts.deny 删除是没用的。需要进入 /var/lib/denyhosts 目录,进入以下操作:
1、停止DenyHosts服务:
service denyhosts stop
2、在 /etc/hosts.deny 中删除你想取消的主机IP
3、编辑 DenyHosts 工作目录的所有文件,通过
grep 192.168.1.191 /usr/share/denyhosts/data/*
然后一个个删除文件中你想取消的主机IP所在的行:
* /usr/share/denyhosts/data/hosts
* /usr/share/denyhosts/data/hosts-restricted
* /usr/share/denyhosts/data/hosts-root
* /usr/share/denyhosts/data/hosts-valid
* /usr/share/denyhosts/data/users-hosts
4、添加你想允许的主机IP地址到/var/lib/denyhosts/allowed-hosts
vi /usr/share/denyhosts/data/allowed-hostsps
然后逐行输入你的IP
thinkai.net 192.168.1.*
5、启动DenyHosts服务:
service denyhosts start
报错排查
#service denyhost start
starting DenyHosts: /usr/bin/env python /usr/bin/denyhosts.py –daemon
–config=/usr/share/denyhosts/denyhosts.cfg
python: can't open file '/usr/bin/denyhosts.py': [Errno 2] No such file or
directory
cd /usr/share/denyhosts/ vi daemon-control
DENYHOSTS_BIN = "/usr/bin/denyhosts.py"
改为
DENYHOSTS_BIN = "/usr/local/bin/denyhosts.py"
cd /usr/local/lib/python2.7/site-packages/ cp -rp DenyHosts /usr/lib/python2.4/site-packages/ /etc/init.d/denyhosts restart
vi /etc/passwd
按i键进入编辑状态
修改第1行第1个root为新的用户名
按esc键退出编辑状态,并输入:x保存并退出
vi /etc/shadow
修改第1行第1个root为新的用户名
按esc键退出编辑状态,并输入:x!强制保存并退出
补充:为了正常使用sudo,需要修改/etc/sudoers的设置,修改方法如下:
visudo
找到root ALL=(ALL) ALL
在下面添加一行:新用户名 ALL=(ALL) ALL
:x保存退出
虽然免费的stun服务器也能凑合着用,但是也越来越不适用于中国的网络环境,所以你可以到大的IDC去买云主机并购买额外IP来搭建STUN服务器,主流成本100多RMB一个月。
首先你的有两个公网IP的服务器!然后注意把防火墙关掉。
#下载stun
wget http://ncu.dl.sourceforge.net/project/stun/stun/0.97/stund-0.97.tgz
#检查安装编译环境
yum -y install gcc automake autoconf libtool make
#解压
tar -zxvf stund-0.97.tgz
#进入目录
cd stund
#编译
make
#复制服务端
mkdir /root/bin/ cp server /root/bin/stunserver
#创建服务脚本
vi /etc/init.d/stund
#然后填充服务脚本
#!/bin/bash # #chkconfig: 2345 70 30 #description:STUN Server RETVAL=0 start(){ #启动服务的入口函数 echo "STUN Server is started..." /root/bin/stunserver -v -h 8.8.8.8 -a 4.4.4.4 -v #主IP 辅助IP } stop(){ #关闭服务的入口函数 echo "STUN Server is stoped..." } #使用case选择 case $1 in start) start ;; stop) stop ;; *) echo "error choice ! please input start or stop";; esac exit $RETVA
#按【ESC】输入:wq保存退出
#设置权限
chmod +x /etc/init.d/stund
#添加服务
chkconfig --add stund
#设置防火墙
setup
#找到Firewall设置 把Enable去掉,然后Save保存退出
#为了安全 可以修改root用户名和设置denyhosts
#重启后,你就可以下载NatTypeTester测试你的服务器了。
<?php if ($EMAIL_INC) return; $EMAIL_INC= "defined"; define( "SmtpPort",25); class Pop3 { var $subject; // 邮件主题 var $from_email; // 发件人地址 var $from_name; // 发件人姓名 var $to_email; // 收件人地址 var $to_name; // 收件人姓名 var $body; // 邮件内容 var $filename; // 文件名 var $socket; // 当前的 socket var $Line; var $Status; function pop3_open($server, $port) { $this->Socket = fsockopen($server, $port); if ($this->Socket <= 0){ return false; } $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "+") return false; return true; } function pop3_user($user) { if ($this->Socket < 0){ return false; } fputs($this->Socket, "USER $this->user\r\n"); $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "+") return false; return true; } function pop3_pass( $pass) { fputs($this->Socket, "PASS $pass\r\n"); $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "+") return 0; return 1; } function pop3_stat() { fputs($this->Socket, "STAT\r\n"); $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "+") return 0; if (!eregi( "+OK (.*) (.*)", $this->Line, $regs)) return 0; return $regs[1]; } function pop3_list() { fputs($this->Socket, "LIST\r\n"); $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "+") return 0; $i = 0; while (substr($this->Line = fgets($this->Socket, 1024), 0, 1) <> ".") { $articles[$i] = $this->Line; $i++; } $articles[ "count"] = $i; return $articles; } function pop3_retr($nr) { fputs($this->Socket, "RETR $nr\r\n"); $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "+") return 0; while (substr($this->Line = fgets($this->Socket, 1024), 0, 1) <> ".") { $data[$i] = $this->Line; $i++; } $data[ "count"] = $i; return $data; } function pop3_dele( $nr) { fputs($this->Socket, "DELE $nr\r\n"); $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "+") return 0; return 1; } function pop3_quit() { fputs($this->Socket, "QUIT\r\n"); $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "+") return 0; return 1; } } class Smtp { var $Subject; // string the email's subject var $FromName; // string sender's name (opt) var $ToName; // string recipient's name (opt) var $Body; // string body copy var $Attachment; // attachment (optional) var $AttachmentType; var $Socket; var $Line; var $Status; function Smtp($Server = "localhost",$Port = SmtpPort) { return $this->Open($Server, $Port); } function SmtpMail($FromEmail, $FromName, $ToEmail, $ToName, $Subject, $Body, $Attachment=null, $AttachmentType= "TEXT") { $this->Subject = $Subject; $this->ToName = $ToName; $this->FromName = $FromName; $this->Body = $Body; $this->Attachment = $Attachment; $this->AttachmentType = $AttachmentType; if ($this->Helo() == false){ return false; } if ($this->MailFrom($FromEmail) == false){ return false; } if ($this->RcptTo($ToEmail) == false){ return false; } if ($this->Body() == false){ return false; } if ($this->Quit() == false){ return false; } } function Open($Server, $Port) { $this->Socket = fsockopen($Server, $Port); if ($this->Socket < 0) return false; $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "2") return false; return true; } function Helo() { if (fputs($this->Socket, "helo\r\n") < 0 ){ return false; } $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "2") return false; return true; } function Ehlo() { /* Well, let's use "helo" for now.. Until we need the extra func's [Unk] */ if(fputs($this->Socket, "helo localhost\r\n")<0){ return false; } $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "2") return false; return true; } function MailFrom($FromEmail) { if (fputs($this->Socket, "MAIL FROM: <$FromEmail>\r\n")<0){ return false; } $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "2") return false; return true; } function RcptTo($ToEmail) { if(fputs($this->Socket, "RCPT TO: <$ToEmail>\r\n")<0){ return false; } $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "2") return false; return true; } function Body() { $FileSize = 0; $Attachment = null; $fp = null; $buffer = sprintf( "From: %s\r\nTo:%s\r\nSubject:%s\r\n", $this->FromName, $this->ToName, $this->Subject); if(fputs($this->Socket, "DATA\r\n")<0){ return false; } $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "3") return false; if(fputs($this->Socket, $buffer)<0){ return false; } if ($this->Attachment == null){ if(fputs($this->Socket, "MIME-Version: 1.0\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Transfer-Encoding: 7bit\r\n\r\n")<0){ return false; } if(fputs($this->Socket, "$this->Body\r\n\r\n")<0){ return false; } if(fputs($this->Socket, ".\r\n")<0){ return false; } $this->Line = fgets($this->Socket, 1024); if (substr($this->Line, 0, 1) <> "2"){ return false; }else{ return true; } }else{ if(fputs($this->Socket, "MIME-Version: 1.0\r\nContent-Type: multipart/mixed; boundary=\"----=_NextPart_000_01BCFA61.A3697360\"\r\n". "Content-Transfer-Encoding: 7bit\r\n\r\n". "This is a multi-part message in MIME format.\r\n". "\r\n------=_NextPart_000_01BCFA61.A3697360\r\n". "Content-Type: text/plain; charset=ISO-8859-1\r\n". "Content-Transfer-Encoding: 7bit\r\n". "\r\n")<0){ return false; } /* 输出邮件内容 */ if(fputs($this->Socket, "$this->Body\r\n\r\n")<0){ return false; } if ( fputs($this->Socket, "\r\n------=_NextPart_000_01BCFA61.A3697360\r\n")<0){ return false; } $FileSize = filesize($this->Attachment); if ($FileSize == false){ return false; } if (($fp = fopen($this->Attachment, "r"))== false) { return false; }else{ $Attachment = fread($fp,$FileSize); } // 如果没有附件的目录 if (($AttachName = strrchr($this->Attachment, '/')) == false){ $AttachName = $this->Attachment; } if( fputs($this->Socket, "Content-Type: application/octet-stream; \r\nname=\"$AttachName\"\r\n". "Content-Transfer-Encoding: quoted-printable\r\n". "Content-Description: $AttachName\r\n". "Content-Disposition: attachment; \r\n\tfilename=\"$AttachName\"\r\n". "\r\n")<0){ return false; } /* 输出附件*/ if( fputs($this->Socket, $Attachment)<0){ return false; } if ( fputs($this->Socket, "\r\n\r\n------=_NextPart_000_01BCFA61.A3697360--\r\n")<0){ return false; } if( fputs($this->Socket, ".\r\n")<0){ return false; } $this->Line = fgets($this->Socket, 1024); if (substr($this->Line, 0, 1) <> "2") return false; return true; } } function Quit() { if(fputs($this->Socket, "QUIT\r\n")<0){ return false; } $this->Line = fgets($this->Socket, 1024); $this->Status[ "LASTRESULT"] = substr($this->Line, 0, 1); $this->Status[ "LASTRESULTTXT"] = substr($this->Line, 0, 1024); if ($this->Status[ "LASTRESULT"] <> "2") return 0; return 1; } function Close() { fclose($this->Socket); } } /* 怎样使用这个程序的一个示例 $MailTo = new Smtp(); $MailTo->SmtpMail("Dave@micro-automation.net","Dave Cramer", "Dave@micro-automation.net","David", "Test Mail",$MailMessage,"service.tab",0); $MailTo->Close(); $MailTo=null; */ /* $pop3 = pop3_open("localhost", "110"); if (!$pop3) { printf("[ERROR] Failed to connect to localhost<BR>\n"); return 0; } if (!pop3_user($pop3, "unk")) { printf("[ERROR] Username failed!<BR>\n"); return 0; } if (!pop3_pass($pop3, "secret")) { printf("[ERROR] PASS failed!<BR>\n"); return 0; } $articles = pop3_list($pop3); if (!$articles) { printf("[ERROR] LIST failed!<BR>\n"); return 0; } for ($i = 1; $i < $articles ["count"] + 1; $i++) { printf("i=$i<BR>\n"); $data = pop3_retr($pop3,$i); if (!$data) { printf("data goes wrong on '$i'<BR>\n"); return 0; } for ($j = 0; $j < $data["count"]; $j++) { printf("$data[$j]<BR>\n"); } } */ ?> 分享给朋友:
49 queries in 6.892 seconds |