Three, PHP to establish a socket in the process of explaining
1, in PHP, client and server to establish socket communication, first in PHP to create a socket and listen to the port information, the code is as follows:
To create a socket operation by sending the appropriate IP and port
function WebSocket ($address, $port) {
$server = Socket_create (Af_inet, Sock_stream, sol_tcp);
Socket_set_option ($server, Sol_socket, SO_REUSEADDR, 1);//1 means accept all packets
Socket_bind ($server, $address, $port);
Socket_listen ($server);
return $server;
}
2. Design a loop to suspend the WebSocket channel to receive, process and send data
Monitor the created socket loop to process the data
function Run () {
Dead loop until the socket is disconnected
while (true) {
$changes = $this->sockets;
$write =null;
$except =null;
/*
This function is the key to accepting multiple connections at the same time, and I understand it to block programs from going down.
Socket_select ($sockets, $write = null, $except = NULL, NULL);
$sockets can be understood as an array in which the file descriptor is stored. When it changes (that is, a new message or a client connection/disconnect), the Socket_select function returns and continues to execute.
$write is listening for client write data, incoming NULL is not concerned about whether there is a write change.
$except is the element in the $sockets to be excluded, and incoming null is "listening" all.
The last parameter is the timeout time
If 0: End immediately
If n>1: Then ends after n seconds, and returns in advance if a connection has a new dynamic
If null: If a connection has a new dynamic, return
*/
Socket_select ($changes, $write, $except, NULL);
foreach ($changes as $sock) {
If a new client connection comes in, the
if ($sock = = $this->master) {
Accept a socket connection
$client =socket_accept ($this->master);
A unique ID for the newly connected socket
$key =uniqid ();
$this->sockets[]= $client; To deposit a newly connected socket in a connection pool
$this->users[$key]=array (
' Socket ' => $client,//record the socket information of the newly-connected client
' Shou ' =>false//flag The socket resource does not complete the handshake
);
Otherwise 1. Disconnect socket for client, 2.client send message
}else{
$len = 0;
$buffer = ';
Read the information for the socket, note: The second parameter is the reference to receive the data, the third parameter is the length of the received data
do{
$l =socket_recv ($sock, $buf, 1000,0);
$len + + $l;
$buffer. = $buf;
}while ($l ==1000);
According to the socket in the user pool to find the appropriate $k, that is, the health ID
$k = $this->search ($sock);
If the received message length is less than 7, the client's socket is disconnected
if ($len <7) {
Disconnect the client socket and delete it in $this->sockets and $this->users
$this->send2 ($k);
Continue
}
Determine if the socket has been shaken
if (! $this->users[$k] [' Shou ']) {
If there is no handshake, the handshake is handled
$this->woshou ($k, $buffer);
}else{
This is where the client sends the message, Uncode the received information.
$buffer = $this->uncode ($buffer, $k);
if ($buffer ==false) {
Continue
}
If not empty, a message push operation is performed
$this->send ($k, $buffer);
}
}
}
}
}
3, the above server-side completion of the websocket work, waiting for the client connection, client creation WebSocket is very simple, the code is as follows:
var ws = new WebSocket ("WS://IP: Port");
Handshake Listener function
Ws.onopen=function () {
Status 1 Proof handshake successful, then send client custom name to the past
if (so.readystate==1) {
Send a message to the server after the handshake is successful
So.send (' type=add&ming= ' +n);
}
}
Error return information function
Ws.onerror = function () {
Console.log ("error");
};
Listening for server-side push messages
Ws.onmessage = function (msg) {
Console.log (msg);
}
Disconnect WebSocket Connection
Ws.onclose = function () {
WS = FALSE;
}
Four, chat room instance code
1. PHP part
<?php
Error_reporting (e_all ^ e_notice);
Ob_implicit_flush ();
Address and interface, which requires the IP and port of the server when creating a socket
$sk =new sock (' 127.0.0.1 ', 8000);
Monitor the created socket loop to process the data
$sk->run ();
Below is the sock class
Class sock{
Public $sockets; Socket connection pool, which is the client-connected socket flag
Public $users; All client-connected information, including socket, client name, etc.
Public $master; Resource of the socket, that is, the socket resource that was returned when the socket was initialized earlier
Private $SDA =array (); Data that has been received
Private $slen =array (); Total data length
Private $sjen =array (); The length of the received data
Private $ar =array (); Encryption key
Private $n =array ();
Public function __construct ($address, $port) {
Create the socket and save the socket resource in the $this->master
$this->master= $this->websocket ($address, $port);
Creating a Socket Connection pool
$this->sockets=array ($this->master);
}
Monitor the created socket loop to process the data
function Run () {
Dead loop until the socket is disconnected
while (true) {
$changes = $this->sockets;
$write =null;
$except =null;
/*
This function is the key to accepting multiple connections at the same time, and I understand it to block programs from going down.
Socket_select ($sockets, $write = null, $except = NULL, NULL);
$sockets can be understood as an array in which the file descriptor is stored. When it changes (that is, a new message or a client connection/disconnect), the Socket_select function returns and continues to execute.
$write is listening for client write data, incoming NULL is not concerned about whether there is a write change.
$except is the element in the $sockets to be excluded, and incoming null is "listening" all.
The last parameter is the timeout time
If 0: End immediately
If n>1: Then ends after n seconds, and returns in advance if a connection has a new dynamic
If null: If a connection has a new dynamic, return
*/
Socket_select ($changes, $write, $except, NULL);
foreach ($changes as $sock) {
If a new client connection comes in, the
if ($sock = = $this->master) {
Accept a socket connection
$client =socket_accept ($this->master);
A unique ID for the newly connected socket
$key =uniqid ();
$this->sockets[]= $client; To deposit a newly connected socket in a connection pool
$this->users[$key]=array (
' Socket ' => $client,//record the socket information of the newly-connected client
' Shou ' =>false//flag The socket resource does not complete the handshake
);
Otherwise 1. Disconnect socket for client, 2.client send message
}else{
$len = 0;
$buffer = ';
Read the information for the socket, note: The second parameter is the reference to receive the data, the third parameter is the length of the received data
do{
$l =socket_recv ($sock, $buf, 1000,0);
$len + + $l;
$buffer. = $buf;
}while ($l ==1000);
According to the socket in the user pool to find the appropriate $k, that is, the health ID
$k = $this->search ($sock);
If the received message length is less than 7, the client's socket is disconnected
if ($len <7) {
Disconnect the client socket and delete it in $this->sockets and $this->users
$this->send2 ($k);
Continue
}
Determine if the socket has been shaken
if (! $this->users[$k] [' Shou ']) {
If there is no handshake, the handshake is handled
$this->woshou ($k, $buffer);
}else{
This is where the client sends the message, Uncode the received information.
$buffer = $this->uncode ($buffer, $k);
if ($buffer ==false) {
Continue
}
If not empty, a message push operation is performed
$this->send ($k, $buffer);
}
}
}
}
}
Specifies that the $k corresponding socket is closed
function Close ($k) {
Disconnect the corresponding socket
Socket_close ($this->users[$k] [' socket ']);
Delete the appropriate user information
unset ($this->users[$k]);
Redefining the sockets Connection pool
$this->sockets=array ($this->master);
foreach ($this->users as $v) {
$this->sockets[]= $v [' socket '];
}
Output log
$this->e ("Key: $k close");
}
According to Sock, find the corresponding $k within the users
function Search ($sock) {
foreach ($this->users as $k => $v) {
if ($sock = = $v [' socket '])
return $k;
}
return false;
}
To create a socket operation by sending the appropriate IP and port
function WebSocket ($address, $port) {
$server = Socket_create (Af_inet, Sock_stream, sol_tcp);
Socket_set_option ($server, Sol_socket, SO_REUSEADDR, 1);//1 means accept all packets
Socket_bind ($server, $address, $port);
Socket_listen ($server);
$this->e (' Server started: '. Date (' y-m-d h:i:s '));
$this->e (' listening on: '. $address. ' Port ' $port);
return $server;
}
/*
* Function Description: The client's request to respond, that is, handshake operation
* @ $k Clien socket corresponding to the health, that is, each user has a unique $k and corresponding socket
* @ $buffer Receive all information from client requests
*/
function Woshou ($k, $buffer) {
Intercepts the value of the Sec-websocket-key and encrypts it, where the $key part of the following 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 string should be fixed
$buf = substr ($buffer, Strpos ($buffer, ' Sec-websocket-key: ') +18);
$key = Trim (substr ($buf, 0,strpos ($buf, "\ r \ n"));
$new _key = Base64_encode (SHA1 ($key.) 258eafa5-e914-47da-95ca-c5ab0dc85b11 ", true));
Return according to Protocol combination information
$new _message = "http/1.1 switching protocols\r\n";
$new _message. = "upgrade:websocket\r\n";
$new _message. = "sec-websocket-version:13\r\n";
$new _message. = "connection:upgrade\r\n";
$new _message. = "Sec-websocket-accept:". $new _key. "\r\n\r\n";
Socket_write ($this->users[$k] [' socket '], $new _message,strlen ($new _message));
Sign the client who has already shook hands
$this->users[$k] [' Shou ']=true;
return true;
}
decoding functions
function Uncode ($STR, $key) {
$mask = Array ();
$data = ';
$msg = Unpack (' h* ', $str);
$head = substr ($msg [1],0,2);
if ($head = = ' Bayi ' &&!isset ($this->slen[$key])) {
$len =substr ($msg [1],2,2);
$len =hexdec ($len);//convert hexadecimal to decimal
if (substr ($msg [1],2,2) = = ' Fe ') {
$len =substr ($msg [1],4,4);
$len =hexdec ($len);
$msg [1]=substr ($msg [1],4);
}else if (substr ($msg [1],2,2) = = ' ff ') {
$len =substr ($msg [1],4,16);
$len =hexdec ($len);
$msg [1]=substr ($msg [1],16);
}
$mask [] = Hexdec (substr ($msg [1],4,2));
$mask [] = Hexdec (substr ($msg [1],6,2));
$mask [] = Hexdec (substr ($msg [1],8,2));
$mask [] = Hexdec (substr ($msg [1],10,2));
$s = 12;
$n = 0;
}else if ($this->slen[$key] > 0) {
$len = $this->slen[$key];
$mask = $this->ar[$key];
$n = $this->n[$key];
$s = 0;
}
$e = strlen ($msg [1])-2;
for ($i = $s; $i <= $e; $i + 2) {
$data. = Chr ($mask [$n%4]^hexdec (substr ($msg [1], $i, 2));
$n + +;
}
$dlen =strlen ($data);
if ($len > 255 && $len > $dlen +intval ($this->sjen[$key)) {
$this->ar[$key]= $mask;
$this->slen[$key]= $len;
$this->sjen[$key]= $dlen +intval ($this->sjen[$key]);
$this->sda[$key]= $this->sda[$key]. $data;
$this->n[$key]= $n;
return false;
}else{
unset ($this->ar[$key], $this->slen[$key], $this->sjen[$key], $this->n[$key]);
$data = $this->sda[$key]. $data;
unset ($this->sda[$key]);
return $data;
}
}
Relative to the Uncode
function code ($MSG) {
$frame = Array ();
$frame [0] = ' 81 ';
$len = strlen ($msg);
if ($len < 126) {
$frame [1] = $len <16? ' 0 '. Dechex ($len):d Echex ($len);
}else if ($len < 65025) {
$s =dechex ($len);
$frame [1]= ' 7e '. Str_repeat (' 0 ', 4-strlen ($s)). $s;
}else{
$s =dechex ($len);
$frame [1]= ' 7f '. Str_repeat (' 0 ', 16-strlen ($s)). $s;
}
$frame [2] = $this->ord_hex ($msg);
$data = Implode (", $frame);
Return Pack ("h*", $data);
}
function Ord_hex ($data) {
$msg = ';
$l = strlen ($data);
for ($i = 0; $i < $l; $i + +) {
$msg. = Dechex (Ord ($data {$i}));
}
return $msg;
}
The user joins or the client sends the information
function Send ($k, $msg) {
Resolves the query string into a second parameter variable, as an array: Parse_str ("name=bill&age=60", $arr)
Parse_str ($msg, $g);
$ar =array ();
if ($g [' type ']== ' add ') {
The first time to add a chat name, save the name in the appropriate users
$this->users[$k] [' name ']= $g [' Ming '];
$ar [' type ']= ' add ';
$ar [' name ']= $g [' Ming '];
$key = ' all ';
}else{
Send information behavior, which $g[' key '] to show that the face of everyone or a person, is the message from the previous paragraph passed over
$ar [' Nrong ']= $g [' nr '];
$key = $g [' key '];
}
Push information
$this->send1 ($k, $ar, $key);
}
Client pushed already online for the newly joined client
function Getusers () {
$ar =array ();
foreach ($this->users as $k => $v) {
$ar []=array (' Code ' => $k, ' name ' => $v [' name ']);
}
return $ar;
}
$k sender of the Socketid $key the Socketid of the recipient, according to this socketid can find the corresponding client for message push, that is, specify the client to send
function Send1 ($k, $ar, $key = ' all ') {
$ar [' Code1 ']= $key;
$ar [' Code ']= $k;
$ar [' Time ']=date (' m-d h:i:s ');
Encode and process the sent information
$str = $this->code (Json_encode ($ar));
In the face of everyone, that is, all online send information
if ($key = = ' All ') {
$users = $this->users;
If the add represents the newly added client
if ($ar [' type ']== ' add ') {
$ar [' type ']= ' Madd ';
$ar [' Users ']= $this->getusers (); Take out all online users for display in the online user list
$str 1 = $this->code (Json_encode ($ar)); Separate code processing for new client, data is different
Send the new client himself separately, because some data is not the same
Socket_write ($users [$k] [' socket '], $str 1,strlen ($str 1));
The above has been sent to the client itself, the back is not sent again, so unset
Unset ($users [$k]);
}
Send information to other client in addition to the new client. When the volume of data is large, we should consider the problem of delay.
foreach ($users as $v) {
Socket_write ($v [' socket '], $STR, strlen ($STR));
}
}else{
Send a message individually to a person, that is, a conversation between two parties
Socket_write ($this->users[$k] [' socket '], $STR, strlen ($STR));
Socket_write ($this->users[$key] [' socket '], $STR, strlen ($STR));
}
}
User exits the push message to the client being used
function Send2 ($k) {
$this->close ($k);
$ar [' type ']= ' rmove ';
$ar [' Nrong ']= $k;
$this->send1 (False, $ar, ' all ');
}
Record log
function e ($str) {
$path =dirname (__file__). ' /log.txt ';
$str = $str. " \ n ";
Error_log ($STR, 3, $path);
Code processing
echo iconv (' Utf-8 ', ' Gbk//ignore ', $str);
}
}
?>
2. Client part
<!doctype html>
<html>
<head>
<meta charset= "Utf-8" >
<meta name= "viewport" content= "Width=device-width, initial-scale=1, User-scalable=no"/>
<TITLE>HTML5 WebSocket web chat room JavaScript php</title>
<style type= "Text/css" >
body,p{margin:0px padding:0px; font-size:14px; color: #333; font-family:arial, Helvetica, Sans-serif;}
#ltian,. rin{width:98%; margin:5px Auto;
#ltian {border:1px #ccc solid;overflow-y:auto; overflow-x:hidden; position:relative;}
#ct {margin-right:111px; Height:100%;overflow-y:auto;overflow-x: Hidden;}
#us {width:110px; overflow-y:auto; overflow-x:hidden; float:right; border-left:1px #ccc solid; height:100%; Background-color: #F1F1F1;}
#us p{padding:3px 5px; color: #08C; line-height:20px; height:20px; cursor:pointer; overflow:hidden; white-space:nowrap; Text-overflow:ellipsis;}
#us P:hover, #us p:active, #us p.ck{background-color: #069; color: #FFF;}
#us P.my:hover, #us p.my:active, #us p.my{color: #333; background-color:transparent;}
Button{float:right; width:80px; height:35px; font-size:18px;}
input{width:100% height:30px; padding:2px; line-height:20px; outline:none; border:solid 1px #CCC;}
. Rin p{margin-right:160px;}
. Rin span{float:right; padding:6px 5px 0px 5px; position:relative;}
. Rin span img{margin:0px 3px; cursor:pointer;}
. Rin span Form{position:absolute; width:25px; height:25px; overflow:hidden; opacity:0; top:5px; right:5px;}
. Rin span input{width:180px; height:25px; margin-left:-160px; Cursor:pointer}
#ct p{padding:5px; line-height:20px;}
#ct a{color: #069; cursor:pointer;}
#ct span{color: #999; margin-right:10px;}
. C2{color: #999;}
. C3{background-color: #DBE9EC; padding:5px;}
Qp{position:absolute font-size:12px; color: #666; top:5px; right:130px; text-decoration:none; color: #069;}
#ems {position:absolute; z-index:5; display:none; top:0px; left:0px; max-width:230px; Background-color: #F1F1F1; border : solid 1px #CCC; padding:5px;}
#ems img{width:44px height:44px; border:solid 1px #FFF; cursor:pointer;}
#ems Img:hover, #ems img:active{border-color: #A4B7E3;}
#ems a{color: #069; border-radius:2px; display:inline-block; margin:2px 5px; padding:1px 8px; text-decoration:none; Background-color: #D5DFFD;}
#ems a:hover, #ems a:active, #ems a.ck{color: #FFF; Background-color: #069;}
. tc{text-align:center; margin-top:5px;}
</style>
</head>
<body>
<div id= "Ltian" >
<div id= "Us" class= "JB" ></div>
<div id= "CT" ></div>
<a href= "javascript:;" class= "QP" onclick= "this.parentnode.children[1].innerhtml=" "" > Clear screen </a>
</div>
<div class= "Rin" >
<button id= "SD" > Send </button>
<span><img src= "http://www.yxsss.com/ui/sk/t.png" title= expression "id=" Imgbq "><img src=" http:// Www.yxsss.com/ui/sk/e.png "title=" Upload picture "><form><input type=" file "title=" Upload picture "id=" upimg "></form ></span>
<p><input id= "Nrong" ></p>
</div>
<div id= "EMS" ><p></p><p class= "TC" ></p></div>
<script>
if (typeof (WebSocket) = = ' undefined ') {
Alert (' Your browser doesn't support WebSocket, recommend Google Chrome or Mozilla Firefox ');
}
</script>
<script src= "Http://www.yxsss.com/ui/p/a.js" type= "Text/javascript" ></script>
<script>
(function () {
var key= ' all ', mkey;
var users={};
var url= ' ws://127.0.0.1:8000 ';
var So=false,n=false;
var lus=a.$ (' Us '), lct=a.$ (' ct ');
Function St () {
N=prompt (' Please give yourself a loud name: ');
N=n.substr (0,16);
if (!n) {
return;
}
Create a socket, note the format of the URL: ws://ip: Port
So=new WebSocket (URL);
Handshake Listener function
So.onopen=function () {
Status 1 Proof handshake successful, then send client custom name to the past
if (so.readystate==1) {
So.send (' type=add&ming= ' +n);
}
}
Handshake failed or other reason connection socket failed, clear so object and make appropriate prompt action
So.onclose=function () {
So=false;
Lct.appendchild (a.$$ (' <p class= "C2" > Exit chat Room </p>));
}
The data receives the monitor, the receiving server pushes over the information, the returned data gives MSG, then carries on the display
So.onmessage=function (msg) {
Eval (' var da= ' +msg.data);
var Obj=false,c=false;
if (da.type== ' add ') {
var obj=a.$$ (' <p> ' +da.name+ ' </p> ');
Lus.appendchild (obj);
Cuser (Obj,da.code);
obj=a.$$ (' <p><span>[' +da.time+ ']</span> welcome <a> ' +da.name+ ' </a> join </p> ');
C=da.code;
}else if (da.type== ' Madd ') {
Mkey=da.code;
Da.users.unshift ({' Code ': ' All ', ' name ': ' Everyone '});
for (Var i=0;i<da.users.length;i++) {
var obj=a.$$ (' <p> ' +da.users[i].name+ ' </p> ');
Lus.appendchild (obj);
if (Mkey!=da.users[i].code) {
Cuser (Obj,da.users[i].code);
}else{
Obj.classname= ' my ';
Document.title=da.users[i].name;
}
}
obj=a.$$ (' <p><span>[' +da.time+ ']</span> welcome ' +da.name+ ' to join </p> ');
Users.all.classname= ' CK ';
}
if (Obj==false) {
if (da.type== ' Rmove ') {
var obj=a.$$ (' <p class= ' C2 "><span>[' +da.time+ ']</span> ' +users[da.nrong].innerhtml+ ') exit chat room </p > ');
Lct.appendchild (obj);
Users[da.nrong].del ();
Delete Users[da.nrong];
}else{
Da.nrong=da.nrong.replace (/{\\ (\d+)}/g,function (a,b) {
Return ' <img src= ' sk/' +b+ '. gif ' > ';
}). replace (/^data\:image\/png;base64\,.{ 50,}$/i,function (a) {
Return ' <img src= ' +a+ ' ">";
});
Da.code the code of the person who sent the message
if (Da.code1==mkey) {
obj=a.$$ (' <p class= "C3" ><span>[' +da.time+ ']</span><a> ' +users[da.code].innerhtml+ ') </a > said to me: ' +da.nrong+ ' </p> ');
C=da.code;
}else if (da.code==mkey) {
if (da.code1!= ' all ')
obj=a.$$ (' <p class= ' C3 ' ><span>[' +da.time+ ']</span> me to <a> ' +users[da.code1].innerhtml+ ' </a> said: ' +da.nrong+ ' </p> ');
Else
obj=a.$$ (' <p><span>[' +da.time+ ']</span> i to <a> ' +users[da.code1].innerhtml+ ' </a> said: ' +da.nrong+ ' </p> ');
C=da.code1;
}else if (da.code==false) {
obj=a.$$ (' <p><span>[' +da.time+ ']</span> ' +da.nrong+ ' </p> ');
}else if (da.code1) {
obj=a.$$ (' <p><span>[' +da.time+ ']</span><a> ' +users[da.code].innerhtml+ ' </a> pair ' + users[da.code1].innerhtml+ ' said: ' +da.nrong+ ' </p> ');
C=da.code;
}
}
}
if (c) {
Obj.children[1].onclick=function () {
Users[c].onclick ();
}
}
Lct.appendchild (obj);
Lct.scrolltop=math.max (0,lct.scrollheight-lct.offsetheight);
}
}
a.$ (' SD '). Onclick=function () {
if (!SO) {
Return St ();
}
var da=a.$ (' Nrong '). Value.trim ();
if (da== ') {
Alert (' content cannot be empty ');
return false;
}
a.$ (' Nrong '). value= ';
So.send (' nr= ' +esc (DA) + ' &key= ' +key);
}
a.$ (' Nrong '). Onkeydown=function (e) {
var e=e| | Event
if (e.keycode==13) {
a.$ (' SD '). onclick ();
}
}
function Esc (DA) {
Da=da.replace (/</g, ' < '). Replace (/>/g, ' > '). replace (/\ "/g, '");
Return encodeURIComponent (DA);
}
function Cuser (t,code) {
users[code]=t;
T.onclick=function () {
T.parentnode.children.rcss (' ck ', ');
T.rcss (', ' ck ');
Key=code;
}
}
a.$ (' Ltian '). style.height= (document.documentelement.clientheight-70) + ' px ';
St ();
var bq=a.$ (' Imgbq '), ems=a.$ (' EMS ');
var L=80,r=4,c=5,s=0,p=math.ceil (l/(r*c));
var pt= ' sk/';
Bq.onclick=function (e) {
var e=e| | Event
if (!SO) {
Return St ();
}
ems.style.display= ' block ';
Document.onclick=function () {
GB ();
}
CT ();
Try{e.stoppropagation ();} catch (o) {}
}
for (Var i=0;i<p;i++) {
var a=a.$$ (' <a href= "javascript:;" > ' + (i+1) + ' </a> ');
Ems.children[1].appendchild (a);
EF (a,i);
}
Ems.children[1].children[0].classname= ' CK ';
function ct () {
var Wz=bq.weiz ();
With (Ems.style) {
top=wz.y-242+ ' px ';
left=wz.x+bq.offsetwidth-235+ ' px ';
}
}
Function EF (t,i) {
T.onclick=function (e) {
var e=e| | Event
S=i*r*c;
Ems.children[0].innerhtml= ';
HH ();
This.parentNode.children.rcss (' ck ', ');
This.rcss (', ' ck ');
Try{e.stoppropagation ();} catch (o) {}
}
}
function hh () {
var z=math.min (l,s+r*c);
for (Var i=s;i<z;i++) {
var a=a.$$ (' <img src= "' +pt+i+ '. gif ' > ');
HH1 (A,i);
Ems.children[0].appendchild (a);
}
CT ();
}
function HH1 (t,i) {
T.onclick=function (e) {
var e=e| | Event
a.$ (' Nrong '). value+= ' {\ \ ' +i+ '} ';
if (!e.ctrlkey) {
GB ();
}
Try{e.stoppropagation ();} catch (o) {}
}
}
function GB () {
Ems.style.display= ';
a.$ (' Nrong '). focus ();
Document.onclick= ';
}
HH ();
A.on (window, ' Resize ', function () {
a.$ (' Ltian '). style.height= (document.documentelement.clientheight-70) + ' px ';
CT ();
})
var fimg=a.$ (' upimg ');
var img=new Image ();
var dw=400,dh=300;
A.on (fimg, ' Change ', function (EV) {
if (!SO) {
St ();
return false;
}
if (key== ' all ') {
Alert (' Only private chat due to resource constraints ');
return false;
}
var f=ev.target.files[0];
if (F.type.match (' image.* ')) {
var r = new FileReader ();
R.onload = function (e) {
Img.setattribute (' src ', e.target.result);
};
R.readasdataurl (f);
}
});
Img.onload=function () {
Ih=img.height,iw=img.width;
if (Iw/ih > Dw/dh && iw > DW) {
IH=IH/IW*DW;
IW=DW;
}else if (ih > DH) {
IW=IW/IH*DH;
IH=DH;
}
var rc = a.$$ (' canvas ');
var ct = rc.getcontext (' 2d ');
RC.WIDTH=IW;
Rc.height=ih;
Ct.drawimage (IMG,0,0,IW,IH);
var da=rc.todataurl ();
So.send (' nr= ' +esc (DA) + ' &key= ' +key);
}
})();
</script>
</body>
</html>