Thinkai's Blog

Autohotkey|Python|php|aardio|VOIP|IT 爱好者

正在浏览分类 IT

总共找到 159 篇

简单的cmd ftp上传工具 AAuto 3299

作者为 发表

AAuto快手

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();


Asterisk队列监控的简单实现 Autohotkey+php+cli 5052

作者为 发表

AutohotkeyVOIP

首先你得有个获取队列情况的接口。如果使用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验证用户名密码 Autohotkey 4269

作者为 发表

Autohotkey

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安卓短信接口 3379

作者为 发表

Autohotkey安卓应用

;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
}

Autohotkey+Web Short Message安卓短信接口.zip

QQ截图20150409212038.jpg

Centos安装Denyhosts屏蔽恶意暴力破解root密码 3204

作者为 发表

Linux

#下载
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


修改Linux Centos的root用户名 3895

作者为 发表

Linux

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保存退出

Centos6安装STUN服务器 8789

作者为 发表

LinuxVOIP

虽然免费的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 smtp&pop3收发邮件代码 2410

作者为 发表

网站建设

<?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"); 
} 
} 
*/ 
?>
分享给朋友:



友情链接:Autohotkey中文帮助Autohotkey官网Autohotkey中文网联系作者免GooglePlay APK下载

 主题设计 • skyfrit.com  Thinkai's Blog | 保留所有权利

49 queries in 6.892 seconds |