📄 chat1.0pre5.pl
字号:
my $id;
if ($nick ne "" && $nick ne "所有人"){
foreach $id (keys %CLIENTS) {
if ($CLIENTS{$id}->[1] eq $nick) {
return $id;
}
}
}
return undef;
}
sub sendmsg{
#___
# |----动作-----系统管理命令
# | |
# | |--普通动作
# |
# |
# |----说话-----对所有人
# |
# |--对某个人----公开说话
# |
# |--私聊
#sendmsg($sid,$FORM{'talkto'},$FORM{'message'},$FORM{'ws'});
my ($sid,$talkto,$msg,$ws)=@_;
#检查参数
if ($talkto eq "所有人"){
$ws="";
}
#先对msg进行必要的处理,禁止html,前后空格已经去掉了
if ($msg eq ""){
return;
}
$msg=~s/\</<\;/g;
$msg=~s/\>/>\;/g;
if (!id_ok($sid)){
return;
}
my $name=$CLIENTS{$sid}->[1];
if ($msg=~m,^/,){#动作
$msg=$';
my ($cmd,$para,$junk)=split(/\s+/,$msg,3);
if (length($para)>0){#动作可以带参数,如果带参数,那么将覆盖talkto的内容
$talkto=$para;
}
my $did=get_sid($talkto);#如果$talkto存在,则返回sid
my $did_ok;
if (id_ok($did)){
$did_ok=1;
}else{
$did_ok=0;
}
if ($cmd=~m,^/,){#系统管理命令
$cmd=$';
my $info="";
my $sock=$CLIENTS{$sid}->[0];
if (!($MOD{$name}||$ADMIN{$name})){#检查权限
$info="你的权限不够";
}elsif ($talkto eq "所有人"){#管理命令只能对某个人使用
$info="请先选择命令对象";
}else{
if ($cmd eq "ip"){
if ($did_ok){
my $dsock=$CLIENTS{$did}->[0];
my $ip_addr;
if (!eval{$ip_addr=$dsock->peerhost;}){
log_event("Get peer ip error!$@");
$ip_addr="N/A";
}
$info="$talkto的IP地址是$ip_addr";
}else{
$info="$talkto已经离开";
}
}elsif($cmd eq "filter"){
if ($did_ok){
$sys_filter{$talkto}=1;
my @ls=keys %sys_filter;
my $list="@ls";
if ($list ne ""){
$list="($list)";
}
$info="$talkto被加入系统过滤表$list";
}else{
$info="$talkto已经离开";
}
}elsif($cmd eq "unfilter"){
if (exists($sys_filter{$talkto})){
delete $sys_filter{$talkto};
$info="$talkto已从系统过滤名单中移出。";
}else{
$info="$talkto不在过滤名单里。";
}
}elsif($cmd eq "kick"){
if ($did_ok){#也许需要缺席审判
if ($name eq $talkto){
$info="干吗踢自己?";
}elsif($ADMIN{$talkto}){
$info="嘿嘿,你踢不了他:-)";
}else{
#需要广播这个消息,同时保存在blacklist里
$blacklist{$talkto}=1;
notice("$talkto被赶出聊天室");
log_event("$name kicked $talkto out");
exitclient($did);
}
}else{
$info="$talkto已经离开";
}
}elsif($cmd eq "unkick"){#释放以前踢过的人
delete $blacklist{$talkto};
$info="$talkto被放出来了:-)";
log_event("$name unkick $talkto");
}elsif($cmd eq "grant"){#授权,保存在内存里,重启以后失效
if (!$ADMIN{$name}){#检查权限,只有管理员(level=0)可以授权
$info="你的权限不够";
}else{
#if ($did_ok){
$MOD{$talkto}=1;
$info="$talkto成为室主";
#}else{
# $info="$talkto已经离开";
#}
}
}elsif($cmd eq "revoke"){
if (!$ADMIN{$name}){#检查权限,只有管理员(level=0)可以取消授权
$info="你的权限不够";
}else{
if ($MOD{$talkto}){
delete $MOD{$talkto};
$info="$talkto被取消室主权限";
}else{
$info="$talkto不是室主";
}
}
}else{#
$info="系统不支持这个命令";
}
}
if ($info ne ""){
$info="<font color=black>【系统消息】$info</font><br>";
$out_buf{$sock}.=$info;
}
}else{#普通动作〖〗
my $info="";
if ($cmd eq "filter"){
if ($talkto eq "所有人"){
$info="【系统消息】请选择过滤对象<br>";
}else{
if ($did_ok){
$CLIENTS{$sid}->[4]->{$talkto}=1;
my $f_ref=$CLIENTS{$sid}->[4];
my @ls=keys %{$f_ref};
my $list="@ls";
if ($list ne ""){
$list="($list)";
}
$info="【系统消息】$talkto已被加入$name的过滤名单$list,取消过滤请用命令/unfilter<br>";
}else{
$info="【系统消息】过滤对象不存在<br>";
}
}
my $sock=$CLIENTS{$sid}->[0];
$out_buf{$sock}.=$info;
}elsif($cmd eq "unfilter"){
if (exists($CLIENTS{$sid}->[4]->{$talkto})){
delete $CLIENTS{$sid}->[4]->{$talkto};
$info="【系统消息】$talkto已从$name的过滤名单中移出。<br>";
}else{
$info="【系统消息】$talkto不在过滤名单里。<br>";
}
my $sock=$CLIENTS{$sid}->[0];
$out_buf{$sock}.=$info;
}else{#其他动作,在@emote里,需要广播
if ($talkto ne "所有人"){#对某个人做动作
if (!$did_ok){#如果不在聊天室里
$info="【系统消息】$talkto已经离开<br>";
my $sock=$CLIENTS{$sid}->[0];
$out_buf{$sock}.=$info;
return;
}
}
$info=emote($name,$talkto,$cmd);
my $color=$CLIENTS{$sid}->[6];
if (!$info){
$info = qq(【系统消息】<a href="javascript:parent.d.csn('$name');" target=d>$name</a>自言自语不知在说什么。<br>);
my $sock=$CLIENTS{$sid}->[0];
$out_buf{$sock}.=$info;
return;
}
my $key;
foreach $key (keys %CLIENTS){
if (!id_ok($key)){
next;
}
if (($sys_filter{$name} && $key ne $sid)||$CLIENTS{$key}->[4]->{$name}){
next;
}
my $output=$info;
if ($key eq $sid || (defined($did) && $key eq $did)){#可以改写此处以区分相关内容
$output="【动作】$output";
}else{
$output="【动作】$output";
}
$output="<font color=$color>$output</font><br>";
my $sock=$CLIENTS{$key}->[0];
$out_buf{$sock}.=$output;
}
}
}
}else{#对话
if($talkto eq "所有人"){#对所有人说
my ($key,$output);
my $color=$CLIENTS{$sid}->[6];
foreach $key (keys %CLIENTS){
if (!id_ok($key)){
next;
}
if (($sys_filter{$name} && $key ne $sid)||$CLIENTS{$key}->[4]->{$name}){
next;
}
my $head;
if ($key eq $sid){
$head="【闲聊】";
}else{
$head="【闲聊】";
}
my $sock=$CLIENTS{$key}->[0];
$output=qq(<font color=$color>$head<a href="javascript:parent.d.csn('$name');" target=d>$name</a>:$msg</font><br>);
$out_buf{$sock}.=$output;
}
}else{#对某个人说
my $did=get_sid($talkto);#如果$talkto存在,则返回sid
if (id_ok($did)){
my $color=$CLIENTS{$sid}->[6];
if ($ws eq "on"){#私聊
my $output=qq(<font color=$color> [私人对话] <a href="javascript:parent.d.csn('$name');" target=d>$name</a>对<a href="javascript:parent.d.csn('$talkto');" target=d>$talkto</a>:$msg</font><br>);
if ($name ne $talkto){
if (!$sys_filter{$name} && !$CLIENTS{$did}->[4]->{$name}){
my $dsock=$CLIENTS{$did}->[0];
$out_buf{$dsock}.=$output;
}
}
my $sock=$CLIENTS{$sid}->[0];
$out_buf{$sock}.=$output;
}else{#公开对某人说
my $key;
foreach $key (keys %CLIENTS){
if (!id_ok($key)){
next;
}
if (($sys_filter{$name} && $key ne $sid)||$CLIENTS{$key}->[4]->{$name}){
next;
}
my ($head);
if ($key eq $sid || $key eq $did){
$head="【闲聊】";
}else{
$head="【闲聊】";
}
my $sock=$CLIENTS{$key}->[0];
my $output=qq(<font color=$color>$head<a href="javascript:parent.d.csn('$name');" target=d>$name</a>对<a href="javascript:parent.d.csn('$talkto');" target=d>$talkto</a>:$msg</font><br>);
$out_buf{$sock}.=$output;
}
}
}else{#用户已经离开
my $sock=$CLIENTS{$sid}->[0];
my $output=qq(<font color=black>【请注意】$talkto已经离开了</font><br>);
$out_buf{$sock}.=$output;
}
}
}
}
sub broadcast{
my $msg=shift;
my ($key);
foreach $key (keys %CLIENTS){
if (id_ok($key)){
$out_buf{$CLIENTS{$key}->[0]}.=$msg;
}
}
}
sub id_ok{
my $sid=shift;
if (defined($sid) && defined($CLIENTS{$sid})){
my $sock=$CLIENTS{$sid}->[0];
if (defined($sock) && $sock->opened && $sock->peername){
return 1;
}
}
return 0;
}
sub check_clients{
my ($key);
foreach $key (keys %CLIENTS){
if (!defined($CLIENTS{$key})){
delete $CLIENTS{$key};
next;
}
my $sock=$CLIENTS{$key}->[0];
my $name=$CLIENTS{$key}->[1];
if (!defined($sock)){
#print "Socket not defined\n";
if (time()-$config{'timeout'}>$CLIENTS{$key}->[5]){
notice("$CLIENTS{$key}->[1]断线离开") if ($name);
log_event("$name offline");
delete $CLIENTS{$key};
}
next;
}
if (!$sock->opened||!$sock->peername){
$sel->remove($sock);
$CLIENTS{$key}->[0]=undef;
$CLIENTS{$key}->[5]=time();#断线不马上通知,主要为刷新处理
next;
}
}
}
sub antiidle {#定时发送信息防止session time out,由在线名单调用
my ($msid) = $_[0];
if (!id_ok($msid)){
return;
}
my($sock) = $CLIENTS{$msid}->[0];
$out_buf{$sock}.="\n<!--antiidle-->\n";
}
sub rand_str{
my $num=shift;
my $i;
my $str="";
my @rand_chars=('a'..'z','A'..'Z','0'..'9');
for ($i=0;$i<$num;$i++){
$str.=$rand_chars[rand(@rand_chars)];
}
return $str;
}
sub check_pass{#检查密码,login时调用
#测试版本,不验证密码,只保留一个管理员admin,密码是"win3.11"
#...
#我们实际使用的版本用户数据库是放在MySql里,包括用户权限等数据都在数据库里,
#因此程序的身份验证及权限管理都需要做改动。
my ($name,$passwd)=@_;
if (!($name&&$passwd)){
return (0,2,1);
}
if ($name eq "admin" && $passwd eq crypt($config{'admin_pass'},$passwd)){
return (1,0,1);
}elsif($name eq "admin"){
return (0,2,1);
}else{
return (1,2,0);
}
}
sub check_auth{#检查身份,发言时调用,参数是sid,加密过的密码
my ($sid,$passwd)=@_;
if (!($sid&&$passwd)){
return 0;
}
if ($CLIENTS{$sid}->[2] eq $passwd) {
return 1;
}else{
return 0;
}
}
sub exitclient {
my $sid=shift;
my $sock=$CLIENTS{$sid}->[0];
if (defined $sock) {
$sel->remove($sock);
delete $chat_sock{$sock};
delete $out_buf{$sock};
$sock->close;
}
delete $CLIENTS{$sid};
}
sub notice{
my $msg=shift;
my $output=qq(
<font color=black>
【通知】$msg<br>
</font>
);
broadcast($output);
}
sub offline{
my $sid=shift;
if (id_ok($sid)){
my $nick=$CLIENTS{$sid}->[1];
notice("$nick离开了聊天室");
log_event("$nick left");
exitclient($sid);
}
}
sub trim{
my $str=shift;
$str=~s/^\s*//;
$str=~s/\s*$//;
return $str;
}
sub emote{
# 动作
# usage: emote(talker,listener,action),
# 其中action可以是中文,listener如果是"",就是对自己说
my ($talker,$listener,$action) = @_;
if ($action eq ""){
return "";
}
if ($listener eq "所有人"){
$listener="";
}
my $EMOTE="";
my $isEnglish;
if ($action=~/[\xA1-\xFE]/){#判断动作是否中文
$isEnglish=0;
}else{
$isEnglish=1;
}
foreach (@emote) {
my ($isdisp,$english,$chinese,$one,$two)=split(/~~~/,$_);
my $cmp;
if ($isEnglish){
$cmp=\$english;
}else{
$cmp=\$chinese;
}
if (${$cmp} eq $action) {
#find the emote words
#talk to listener
my $from=qq(<a href="javascript:parent.d.csn('$talker');" Target=d>$talker</a>);
if ($listener) {
my $to=qq(<a href="javascript:parent.d.csn('$listener');" Target=d>$listener</a>);
$two=~s/self/$from/g;
$two=~s/target/$to/g;
$EMOTE=$two;
}
#talk to oneself
else{#如果listener为"",或者是“所有人”,就是自言自语,
$one=~s/self/$from/g;
$EMOTE=$one;
}
last;
}
#Can not find the emote words
else{
$EMOTE="";
}
}
return $EMOTE;
}
# nonblock($socket) puts socket into nonblocking mode
sub nonblock {
return;
my $socket = shift;
my $flags;
$flags = fcntl($socket, F_GETFL, 0)
or die "Can't get flags for socket: $!\n";
fcntl($socket, F_SETFL, $flags | O_NONBLOCK)
or die "Can't make socket nonblocking: $!\n";
}
sub log_event{
my $msg=shift;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime();
$mon++;
$year+=1900;
my $logtime="$year-$mon-$mday $hour:$min:$sec";
$lh->log("$logtime $msg");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -