안녕하세요.^^

일반적으로 제로보드에서 채팅 쓰시려면

위젯으로 배포된 가가채팅을 쓰고 계실텐데,,

가가채팅은 플래시로 짜여져서 정말 복잡하게 만들어진거라

정말 그 제작자의 정성이 듬뿍 담겨져 보입니다. :-)




저는, 위젯도 아니고 애드온도 아니고

그냥 채팅소스를 팁으로 올려드립니다.

편한데로 쓰세요.



채팅소스는 사리님의 블로그에서 배포중이시고요.
(http://www2.ssam.biz/blog/?tb=1&ct=6)

by Anna 안나 2008. 6. 8. 14:44
그동안 요청이 많았는데,
채팅방id에 한글되도록 수정했습니다.
((채팅방id에는 "한글영문_-"만 되고 "~`!@#$%^&*()+=|[]{}" 이건 안됩니다.))
..
ie6하고, ie7하고 Firefox에서 테스트했습니다.
한글제목의 파일 업다운도 문제없이 됩니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.




타이틀에 현재시간의 초가 나오도록 했습니다.
혹시 브라우저가 먹통이 되면,, 새로고침하라고,,,
방문자목록에 시간나오는건,, 그냥 허전해서 갖다붙인거고...
새글확인하는 과정하고는 무관해서,
새글확인하는 ajax함수가 먹통이 되더라도, 그건 그냥 돌아갑니다.
그래서 먹통여부가 그걸로는 판별이 안됩니다.
.. 그래서 새글확인하는 함수에서,
타이틀에 현재시간의 초를 출력하도록 했습니다.
by Anna 안나 2008. 6. 8. 10:56
요청으로 두가지를 수정했습니다.
첫째, 이미지링크를 클릭했을때,
이미지넓이가 소스7번줄에 정해진 것보다 크면, 소스7번줄에 정해진 넓이로 줄입니다.
그리고 이미지위에 [새창으로] [다운로드] 버튼을 달았습니다.
새창으로 : 새창으로 이미지를 띄우는 것이고,
다운로드 : 업로드한 이미지파일일때(외부url이 아니라), 바로 다운로드창이 뜹니다.

둘째, .htaccess파일로 내부파일의 외부접근(직접적인)을 막고 있는데,
그게 아마 apache서버에서만 되는 것으로 알고 있습니다.
그래서 그게 되지 않는 경우가 있어서, 업로드파일의 확장자제한을 요청하셨는데,
문제는 서버의 파싱(스크립트해석)입니다.
어떤 서버에서는 htm확장자파일도 파싱하고, 어떤 서버에서는 하지 않는등,
서버에 따라, 파싱되는 확장자가 다릅니다.

그래서 확장자는 여전히 제한하지 않고,
대신 업로드파일이 저장되는 폴더이름을,, 숨기는 방식으로 했습니다.

방장이 채팅방을 개설했을때, 방장의 PHPSESSID를 이름으로 해서, 업로드저장경로를 만들고,
upload.php파일을 생성시켜서, 그 내역을 저장하도록 했습니다.
그래서 파일업로드/다운로드 할때, upload.php파일을 인클루드해서
업로드저장경로의 변수정의를 얻도록했습니다.

upload.php 파일은 원래는 외부접근도 안되지만,
혹시 되더라도, 파싱된 결과만 보여지기 때문에 아무것도 안나오게 됩니다.

그러니까,, 업로드파일의 경로를 감추는 것입니다.
FTP로 열어보기전에는 어떤 폴더가 있는지 알수없도록..
물론 디렉토리목록이 그냥 출력되면, 허당입니다.
(간혹 그런곳이 있더군요. 경로까지의 주소만 넣으면, 그 경로안의 파일이 그냥 주루룩 나열되는)

셋째, 채팅방 한글아이디되도록 요청하셨는데,
요건 해보니,, 폴더가 생성이 안되는등..문제가 있어서,
뭔가 좀 더 복잡한 처리가 필요할거 같아서,,, 다음으로 미뤘습니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 6. 8. 10:55
채팅방리스트에, 작은 채팅방.. 글이 두번씩 올라가길래 수정했습니다.


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 6. 8. 10:55
글쓰는 부분에 ajax함수를 비동기화에서 동기화로 바꿀라고 했는데,
하여튼 바꾸긴 했는데, 먼저도 그게 비동기식이었는지,, 잘 모르겠더군요..

하여튼 그래서, 자기가 글 올리고 새글바로 확인하는 간격을 0.2초로 했습니다.
.. 원래 읽어오는 주기가 0.2초 안에 있으면, 그냥 기다리고,
아니면 새글확인주기와 무관하게 다시 새글확인하도록 하는데,, 거기서의 기다리는 시간.
기존에 0.25초였었는데,, 0.2초로.. == 뭐 별 의미는 없습니다.

새글이 올라오면, document.title='새글이 올라왔습니다' 라고 표시됩니다.
새글이 없으면, 원래 채팅방에서 표시되는대로 '채팅방 - 채팅방id'로 돌아옵니다.
새글 확인주기가 대충 1초니까, 새글이 올라왔다는 표시도 1초동안 유지된다고 보면 되겠네요.


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 6. 8. 10:54
인코딩이 외부적으로 euc-kr / 내부적으로는 utf-8인
방문자목록없는 간단한 채팅소스를 수정한 것입니다.

새글이 올라오면 어떻게 표시해달라는 요청이 있어서,
document.title에 새글이 올라왔다는 문구를 적었습니다.
새글확인이 1초마다 이뤄지니까, 타이틀에 새글이 올라왔다는 문구는 1초동안 유지됩니다.
1초뒤에 새글이 없으면, 다시 채팅방으로 돌아가고..

간단한 수정인데, 꽤 유용하네요.
채팅소스에도 적용하면 좋을거 같습니다.

하여튼 좋은 기능을 제안해주셔서 감사합니다.
잘쓰세요...

아래는 소스. 위에는 업로드한 파일압축입니다.

그리고
FF에서 Enter로 글이 안올라가길래,
form을 달아서 Enter로 글이 올라가도록 했습니다.


<?
session_start();
$chat = "chat.php";
if($_POST[xname] || $_SERVER[QUERY_STRING]){
header ("Content-Type: text/html; charset=UTF-8");
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header ("Cache-Control: no-cache, must-revalidate");
header ("Pragma: no-cache");
if($_POST[xname] && $_POST[text]) {
if(!$_SESSION[name] || $_SESSION[name] != $_POST[xname]) {
$_POST[xname] = str_replace('<', '&lt;', str_replace(' ', '', stripslashes(trim($_POST[xname]))));
$_POST[xname] = preg_replace("` [\s]`i", "", $_POST[xname]);
$_POST[xname] = preg_replace("`[\x1b\x18\x7f\t]`", "", $_POST[xname]);
if($_SESSION[name]) $nickc = "--\x1b<font class=mc><font class=mm>".$_SESSION[name]."</font> ==> <font class=mm>".$_POST[xname]."</font></font>\n";
session_unregister("name");
$name = $_POST[xname];
session_register("name");
}
if($_POST[xname]) {
$_POST[text] = preg_replace("`[\x1b\x18\x7f<]`", "", stripslashes($_POST[text]));
$nickc .= $_POST[xname]."\x1b".$_POST[text]."\n";
$fp = fopen("./_text", "a");
fputs($fp, $nickc);
fclose($fp);
if(filesize("./_text") > 2048) {
$fp = fopen("./_text", "r");
fread($fp, 1536);
fgets($fp);
while(!feof($fp)) $fpo .= fgets($fp);
fclose($fp);
$fp = fopen("./_text", "w");
fputs($fp, $fpo);
fclose($fp);
}
}
exit;
}
if($_GET[tex]) {
if(file_exists("./_text")){
if($_GET[tex] == -1) $_GET[tex] = 0;
$fze = filesize("./_text");
if($fze != $_GET[tex]) {
echo $fze."\x7f";
$fp = fopen("./_text", "r");
while(!feof($fp)) {
if($_GET[tex] && $fze > $_GET[tex]) fread($fp, $_GET[tex]);
if($fpo = trim(fgets($fp))) echo $fpo."\x7f";
}
fclose($fp);
}
}
exit;
}
if($_GET[delete] == "text" && $_SESSION[admin_pass]) {
$fp = fopen("./_text", "w");
fclose($fp);
}
exit;
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<title>채팅방</title>
</head>
<body>
<script>
function go() {
var url = '<?=$chat?>?tex=' + document.getElementsByName('ntim')[0].value;
if(window.ActiveXObject) {
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest) {
var xmlHttp = new XMLHttpRequest();
}
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState==4 && xmlHttp.status==200) {
var str = xmlHttp.responseText;
if(str) {
var vew = str.split("\x7f");
allc = vew.length -1;
if(allc > 1) {
document.getElementsByName('ntim')[0].value = vew[0];
if(document.getElementById('AA').innerHTML == '') str = "<table border=0 cellspacing=0 cellpadding=0 width=100% style='margin-bottom:20;table-layout:fixed'>";
else str = "";
for(i = 1;i < allc;i++){
var nam = vew[i].split("\x1b");
str += "<tr class=trh><td class=name>"+ nam[0] +"</td><td width=10>:</td><td class=memo>"+ nam[1] +"</td></tr>";
str += "<tr><td colspan=3 bgcolor=#E6E6E6 height=1><img height=1></td></tr>";
}
str += "</table>";
document.getElementById('AA').innerHTML = document.getElementById('AA').innerHTML.substring(0,document.getElementById('AA').innerHTML.length-8) + str;
document.getElementById('AA').scrollTop = 10000000;
document.title='새글이 올라왔습니다';
}
} else document.title = '채팅방';
setTimeout('go()', 1000);
delete xmlHttp;
}
}
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}

function wte(){
if(window.ActiveXObject) {
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest) {
var xmlHttp = new XMLHttpRequest();
}
var param = '<?=$chat?>?&xname='+ document.getElementsByName("xname")[0].value.replace(/[&'"]/gi,"") +'&text='+ document.getElementsByName("text")[0].value.replace("&","%26");
xmlHttp.open("POST", param, true);
xmlHttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xmlHttp.setRequestHeader("Content-length", param.length);
xmlHttp.setRequestHeader("Connection", "close");
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState==4 && xmlHttp.status==200) {
document.getElementsByName('text')[0].value = '';
document.getElementsByName('text')[0].focus();
delete xmlHttp;
}
}
xmlHttp.send(param);
}
window.onload = function(){setTimeout("document.getElementsByName('ntim')[0].value='-1';", 50);}
setTimeout('go()', 100);
</script>
<center>
<table border=0 cellspacing=0 cellpadding=5 width=330 style='border:1px solid black'>
<tr height=200><td colspan=3><div id=AA style='width:320;height:200'></div></td></tr>
<tr height=30><td colspan=3><form onsubmit="wte();return false;" style="margin:0"><input type=text name='xname' maxlength=10 style='width:65' value='<?=iconv('UTF-8', 'CP949//IGNORE', $_SESSION[name])?>'>
<input type='text' name='text' style='width:200;'>
<input type='submit' value='쓰기' onclick="wte();return false;" class='button'>
<input type='hidden' name='ntim' value='-1'></form>
</td></tr>
</table>
</center>
<style>
body {font-size:9pt;font-family:gulim;word-break:break-all;}
td {word-break:break-all;font-size:9pt;}
.mm {color:#D7D7D7;font-weight:bold;font-family:gulim;text-align:center;padding-top:5}
.mc {color:#D7D7D7;font-family:gulim;text-align:center;padding-top:5}
.button {background-color:#D7D7D7;border:0;border:1px solid black;margin-right:4px;margin-left:4px;width:35px}
.name {width:50;padding-left:5;font-weight:bold;}
.memo {padding:5px 0px 5px 5px;width:210;}
.trh {padding:6px 0px 6px 0px;}
#AA {overflow-x: hidden; overflow-y: auto;background-color:#FFFFFF;border:1px solid black; }
</style>
</body>
</html>
by Anna 안나 2008. 6. 8. 10:54
예제는 우선 여기:http://whoami.webzero.co.kr/chat_/small.php

euc-kr 찾는 분이 있어서,, 만들었습니다. (물론 기존꺼 수정해서)

iconv를 많이 쓰게 될줄 알았는데,
별로 안쓰게 됐습니다.

하여튼,, 보여지는 부분은 euc-kr 이고,
보여지지 않는 기능적인 부분은 utf-8입니다.
뭐.. 그래도 브라우저에 인코딩은 euc-kr로 나오니까요......

이걸 인클루드하는 실험은 하지 않았는데,
아마 그냥저냥 될거 같습니다. (물론 euc-kr에)

소스 3줄에,
$chat = "index.php";
이렇게 있는데, 혹시 이걸 팝업등으로 독립적으로 띄우질 않고,
다른 곳에 이 소스를 인클루드할때라도,
처리하는 부분은 인클루드되지 않은, 이 파일 단독으로 작동시키기 위해섭니다.

아래가 소스인데,,, 아래내용을 텍스트에디터에 붙여넣고,
$chat = "index.php";
여기 이름하고 맞춰서 저장하면 됩니다. 저장되는 경로(폴더)의 권한은 777 주시고....

------
icov() -- php에서 텍스트의 인코딩바꾸는 함수 --
함수는 세션에 저장한 닉네임에 사용합니다.
닉네임이 바뀌었는지 계속 확인하니까,, 세션닉네임을 자주 거기서 쓰게 되는데,
그래서 세션닉네임을 UTF-8로 저장했습니다.
그래놓고, 창을 새로고침하거나 할때, 닉네임칸에 자동으로 들어갈 세션닉네임은
인코딩을 euc-kr로 바뀌어서 ... 들어가도록 했구요...

문제가 조금 있는게,
닉네임을 바꿨을때, 닉네임 바뀌었다고 뜨고, 그거 바꾸면서 올린 글이 안보입니다.
F5 새로고침해보면,, 나오는걸로 봐서,
저장이 안된건 아닌데, 읽을때,,, 이상하게 못읽어오는군요..
아마 닉네임을 바꾼 본인에게만 그럴겁니다.
우선은 닉네임 바꾸면 F5 (새로고침) 하세요.....

혹시나 그 문제인가해서,
글 올리는 부분이 ajax함수를 비동기화였던거에서 동기화로 바꿔봤는데,
마찬가지더군요...
어쨌거나,, 이왕 바꿨으니까,, 그건 그대로 갑니다.

<?
session_start();
$chat = "index.php";
if($_POST[xname] || $_GET[tex] || $_GET[delete]){
header ("Content-Type: text/html; charset=UTF-8");
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header ("Cache-Control: no-cache, must-revalidate");
header ("Pragma: no-cache");
if($_POST[xname] && $_POST[text]) {
if(!$_SESSION[name] || $_SESSION[name] != $_POST[xname]) {
$_POST[xname] = str_replace('<', '&lt;', str_replace(' ', '', stripslashes(trim($_POST[xname]))));
$_POST[xname] = preg_replace("` [\s]`i", "", $_POST[xname]);
$_POST[xname] = preg_replace("`[\x1b\x18\x7f\t]`", "", $_POST[xname]);
if($_SESSION[name]) $nickc = "--\x1b<font class=mc><font class=mm>".$_SESSION[name]."</font> ==> <font class=mm>".$_POST[xname]."</font></font>\n";
session_unregister("name");
$name = $_POST[xname];
session_register("name");
}
if($_POST[xname]) {
$_POST[text] = preg_replace("`[\x1b\x18\x7f<]`", "", stripslashes($_POST[text]));
$nickc .= $_POST[xname]."\x1b".$_POST[text]."\n";
$fp = fopen("./_text", "a");
fputs($fp, $nickc);
fclose($fp);
if(filesize("./_text") > 2048) {
$fp = fopen("./_text", "r");
fread($fp, 1536);
fgets($fp);
while(!feof($fp)) $fpo .= fgets($fp);
fclose($fp);
$fp = fopen("./_text", "w");
fputs($fp, $fpo);
fclose($fp);
}
}
exit;
}
if($_GET[tex]) {
if(file_exists("./_text")){
if($_GET[tex] == -1) $_GET[tex] = 0;
$fze = filesize("./_text");
if($fze != $_GET[tex]) {
echo $fze."\x7f";
$fp = fopen("./_text", "r");
while(!feof($fp)) {
if($_GET[tex] && $fze > $_GET[tex]) fread($fp, $_GET[tex]);
if($fpo = trim(fgets($fp))) echo $fpo."\x7f";
}
fclose($fp);
}
}
exit;
}
if($_GET[delete] == "text" && $_SESSION[admin_pass]) {
$fp = fopen("./_text", "w");
fclose($fp);
}
exit;
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<title>채팅방</title>
</head>
<body>
<script>
function go() {
var url = '<?=$chat?>?tex=' + document.getElementsByName('ntim')[0].value;
if(window.ActiveXObject) {
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest) {
var xmlHttp = new XMLHttpRequest();
}
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState==4 && xmlHttp.status==200) {
var str = xmlHttp.responseText;
if(str) {
var vew = str.split("\x7f");
allc = vew.length -1;
if(allc > 1) {
document.getElementsByName('ntim')[0].value = vew[0];
if(document.getElementById('AA').innerHTML == '') str = "<table border=0 cellspacing=0 cellpadding=0 width=100% style='margin-bottom:20;table-layout:fixed'>";
else str = "";
for(i = 1;i < allc;i++){
var nam = vew[i].split("\x1b");
str += "<tr class=trh><td class=name>"+ nam[0] +"</td><td width=10>:</td><td class=memo>"+ nam[1] +"</td></tr>";
str += "<tr><td colspan=3 bgcolor=#E6E6E6 height=1><img height=1></td></tr>";
}
str += "</table>";
document.getElementById('AA').innerHTML = document.getElementById('AA').innerHTML.substring(0,document.getElementById('AA').innerHTML.length-8) + str;
document.getElementById('AA').scrollTop = 10000000;
}
} else window.status = '새 글이 없습니다.';
setTimeout('go()', 1000);
delete xmlHttp;
}
}
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}

function wte(){
if(window.ActiveXObject) {
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest) {
var xmlHttp = new XMLHttpRequest();
}
var param = '<?=$chat?>?&xname='+ document.getElementsByName("xname")[0].value.replace(/[&'"]/gi,"") +'&text='+ document.getElementsByName("text")[0].value.replace("&","%26");
xmlHttp.open("POST", param, true);
xmlHttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xmlHttp.setRequestHeader("Content-length", param.length);
xmlHttp.setRequestHeader("Connection", "close");
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState==4 && xmlHttp.status==200) {
document.getElementsByName('text')[0].value = '';
document.getElementsByName('text')[0].focus();
delete xmlHttp;
}
}
xmlHttp.send(param);
}
window.onload = function(){setTimeout("document.getElementsByName('ntim')[0].value='-1';", 50);}
setTimeout('go()', 100);
</script>
<center>
<table border=0 cellspacing=0 cellpadding=5 width=330 style='border:1px solid black'>
<tr height=200><td colspan=3><div id=AA style='width:320;height:200'></div></td></tr>
<tr height=30><td colspan=3><input type=text name='xname' maxlength=10 style='width:65' value='<?=iconv('UTF-8', 'CP949//IGNORE', $_SESSION[name])?>'>
<input type='text' name='text' style='width:200;'>
<input type='submit' value='쓰기' onclick="wte()" class='button'>
<input type='hidden' name='ntim' value='-1'>
</td></tr>
</table>
</center>
<style>
body {font-size:9pt;font-family:gulim;word-break:break-all;}
td {word-break:break-all;font-size:9pt;}
.mm {color:#D7D7D7;font-weight:bold;font-family:gulim;text-align:center;padding-top:5}
.mc {color:#D7D7D7;font-family:gulim;text-align:center;padding-top:5}
.button {background-color:#D7D7D7;border:0;border:1px solid black;margin-right:4px;margin-left:4px;width:35px}
.name {width:50;padding-left:5;font-weight:bold;}
.memo {padding:5px 0px 5px 5px;width:210;}
.trh {padding:6px 0px 6px 0px;}
#AA {overflow-x: hidden; overflow-y: auto;background-color:#FFFFFF;border:1px solid black; }
</style>
</body>
</html> 보기 / 닫기
by Anna 안나 2008. 6. 8. 10:52
-
by Anna 안나 2008. 5. 26. 18:14
크게 바뀐건 없습니다.,
1. 채팅방목록에 작은채팅창 - 0.1초후에 뜨도록 했고,
- - - 0.2초후에 체크해서 안떴으면 다시 뜨도록 하는거 --- 추가했고,

2. 폴더삭제 함수에서, 경로값끝이 / 이게 아니면, 추가하도록 했습니다.
- - - 예제에 보니까, 삭제된 채팅방인데 폴더가 남아있어서
- - - 에러나는 경우가 있던데, 그 문제를 잡은 것입니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:11
채팅방 예제에 보면
채팅방목록에 방문자목록없는 작은 채팅창이 있는데,
홈페이지나 등등에 넣어서 쓸수 있게,
그 부분만 짤라봤습니다.
소스길이는 143줄

다운로드 : http://www2.ssam.biz/blog/img/c.rar

아래가 소스입니다.
<?
session_start();
header ("Content-Type: text/html; charset=UTF-8");
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header ("Cache-Control: no-cache, must-revalidate");
header ("Pragma: no-cache");
if($_POST[xname] && $_POST[text]) {
if(!$_SESSION[name] || $_SESSION[name] != $_POST[xname]) {
$_POST[xname] = str_replace('<', '&lt;', str_replace(' ', '', stripslashes(trim($_POST[xname]))));
$_POST[xname] = preg_replace("` [\s]`i", "", $_POST[xname]);
$_POST[xname] = preg_replace("`[\x1b\x18\x7f\t]`", "", $_POST[xname]);
$nickc = "";
if($_SESSION[name]) $nickc = "--\x1b<font class=mc><font class=mm>".$_SESSION[name]."</font> → <font class=mm>".$_POST[xname]."</font>로 닉변경함</font>\n";
session_unregister("name");
$name = $_POST[xname];
session_register("name");
}
if($_POST[xname] && $_POST[text]) {
$_POST[text] = preg_replace("`[\x1b\x18\x7f<]`", "", stripslashes($_POST[text]));
$fp = fopen("./_text", "a");
fputs($fp, $nickc.$_POST[xname]."\x1b".$_POST[text]."\n");
fclose($fp);
if(filesize("./_text") > 2048) {
$fp = fopen("./_text", "r");
fread($fp, 1536);
fgets($fp);
while(!feof($fp)) $fpo .= fgets($fp);
fclose($fp);
$fp = fopen("./_text", "w");
fputs($fp, $fpo);
fclose($fp);
}
}
exit;
}
if($_GET[tex]) {
if(file_exists("./_text")){
if($_GET[tex] == -1) $_GET[tex] = 0;
$fze = filesize("./_text");
if($fze != $_GET[tex]) {
echo $fze."\x7f";
$fp = fopen("./_text", "r");
while(!feof($fp)) {
if($_GET[tex] && $fze > $_GET[tex]) fread($fp, $_GET[tex]);
if($fpo = trim(fgets($fp))) echo $fpo."\x7f";
}
fclose($fp);
}
}
exit;
}
if($_GET[delete] == "text" && $_SESSION[admin_pass]) {
$fp = fopen("./_text", "w");
fclose($fp);
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>채팅방</title>
</head>
<body>
<script>
function go() {
var url = '?tex=' + document.getElementsByName('ntim')[0].value;
if(window.ActiveXObject) {
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest) {
var xmlHttp = new XMLHttpRequest();
}
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState==4 && xmlHttp.status==200) {
var str = xmlHttp.responseText;
if(str) {
var vew = str.split("\x7f");
allc = vew.length -1;
if(allc > 1) {
document.getElementsByName('ntim')[0].value = vew[0];
if(document.getElementById('AA').innerHTML == '') str = "<table border=0 cellspacing=0 cellpadding=0 width=100% style='margin-bottom:20;table-layout:fixed'>";
else str = "";
for(i = 1;i < allc;i++){
var nam = vew[i].split("\x1b");
str += "<tr class=trh><td class=name>"+ nam[0] +"</td><td width=10>:</td><td class=memo>"+ nam[1] +"</td></tr>";
str += "<tr><td colspan=3 bgcolor=#E6E6E6 height=1><img height=1></td></tr>";
}
str += "</table>";
document.getElementById('AA').innerHTML = document.getElementById('AA').innerHTML.substring(0,document.getElementById('AA').innerHTML.length-8) + str;
document.getElementById('AA').scrollTop = 10000000;
}
} else window.status = '새 글이 없습니다.';
setTimeout('go()', 1000);
delete xmlHttp;
}
}
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}

function wte(){
if(window.ActiveXObject) {
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest) {
var xmlHttp = new XMLHttpRequest();
}
var param = '?&xname='+ document.getElementsByName("xname")[0].value.replace(/[&'"]/gi,"") +'&text='+ document.getElementsByName("text")[0].value.replace("&","%26");
xmlHttp.open("POST", param, false);
xmlHttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xmlHttp.setRequestHeader("Content-length", param.length);
xmlHttp.setRequestHeader("Connection", "close");
xmlHttp.send(param);
document.getElementsByName('text')[0].value = '';
document.getElementsByName('text')[0].focus();
return false;
}
window.onload = function(){setTimeout("document.getElementsByName('ntim')[0].value='-1';", 50);}
setTimeout('go()', 100);
</script>
<center>
<table border=0 cellspacing=0 cellpadding=5 width=330 style='border:1px solid black'>
<tr height=200><td colspan=3><div id=AA style='width:320;height:200'></div></td></tr>
<tr height=30><td colspan=3><input type=text name='xname' maxlength=10 style='width:65' value='<?=$_SESSION[name]?>'>
<input type='text' name='text' style='width:200;'>
<input type='submit' value='쓰기' onclick="wte()" class='button'>
<input type='hidden' name='ntim' value='-1'>
</td></tr>
</table>
</center>
<style>
body {font-size:9pt;font-family:gulim;word-break:break-all;}
td {word-break:break-all;font-size:9pt;}
.mm {color:#D7D7D7;font-weight:bold;font-family:gulim;text-align:center;padding-top:5}
.mc {color:#D7D7D7;font-family:gulim;text-align:center;padding-top:5}
.button {background-color:#D7D7D7;border:0;border:1px solid black;margin-right:4px;margin-left:4px;width:35px}
.name {width:50;padding-left:5;font-weight:bold;}
.memo {padding:5px 0px 5px 5px;width:210;}
.trh {padding:6px 0px 6px 0px;}
#AA {overflow-x: hidden; overflow-y: auto;background-color:#FFFFFF;border:1px solid black; }
</style>
</body>
</html>
보기 / 닫기

소스 53줄에 데이타초기화하는 부분이 있는데,
이건 각 홈페이지의 관리자만 가능해야 하니까,,
링크도 현재 안넣었습니다.

<a href='?delete=text'>본문초기화</a>
이렇게 링크를 적당한 곳에 넣어주면 됩니다.

인코딩이 이건 utf-8로 저장되어야 합니다.
아마 홈페이지들하고 인코딩이 다를거 같은데,
iframe으로 불러들이면 되잖을까 합니다.
높이가 고정된 것이니까..

소스에 데이타를 "_text" 파일에 저장하도록 되어 있는데,
하여튼 쓰기권한이 열린( -- 707 또는 777) 폴더로 경로를 잡으면 됩니다.
by Anna 안나 2008. 5. 26. 18:10
예제에 색깔이 바뀐게 젤 눈에 들어오겠는데,
소스위쪽에 색깔을 좀 더 다양화했습니다.
$color_1 ~ $color_6 까지.
이거외에 쓰인 색상은,, 채팅방목록에서 비번으로 잠긴방 표시하는 붉은(?)색밖에 없습니다.

기능적으로는 사소한거 몇가지 수정했습니다.
- - 파일업로드하면 - 업로드창 닫히는거 + 그러면서 포커스를 글쓰는 부분으로 주는거
- - 채팅방삭제 링크를 버튼으로 바꾼거
- - 강퇴버튼에다가 스타일준거
- - 비번걸린방 들어갈때 비번넣은 창- 조금 보기좋게 다듬은거
- - <b>,<i>,<s>,<u> 버튼(?) 눌렸는지 표시해서
- - 연속적으로 쓸수있게 한거
- - 폰트나 사이즈같은 태그지원항목 선택할때, 블록설정된 부분없으면 전체적용하도록 한거


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:10
기능적 오류 하나 찾아서 고쳤습니다.
FF에서 채팅방목록 - 실시간메모에 글이 안올라가는 문제.

그리고 디자인을 조금 바꿔봤는데,
...... 어떨라나 모르겠습니다.

외곽선 굵기나 외곽선 종류(solid,dotted,,) 배경색 같은거 수정하기 쉽도록 했습니다.
외곽선 굵기는 $w, 배경색은 $color_2, 나머지는 스타일class에..

수정해서 쓰기는 더 복잡해졌는지도 모르겠습니다.
table이 많아져서,, (삐쭉삐죽 모양 만드니라고)

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

((-------IMAGE-------))
by Anna 안나 2008. 5. 26. 18:08
78버전--에서 별다른 에러는 나타나지 않았습니다.
다만 어떤 경우에, 인코딩을 제대로 UTF-8로 인식하지 못하는 경우가 있더군요.
그래서 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
이 html소스를 추가했습니다.

78버전까지는 그냥 php에서
header ("Content-Type: text/html; charset=UTF-8");
이렇게 헤더주고,, 말았는데,,

어쨌거나,, 그거 하나 수정했습니다.

아 또,, 혹시 원인이 스타일소스에 폰트이름 "굴림"을 인식못해서 였을까 해서,
굴림을 gulim으로 바꿔봤는데,,,
원인이 그게 아니었지만,, 하여튼 그래서 폰트이름이 gulim으로 표시가 바뀌었습니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

by Anna 안나 2008. 5. 26. 18:07
77버전에서 - 방문자목록에서 닉네임을 클릭했을때,
귓속말하고,강퇴버튼이 있는 창이 안열리는 에러가 있었습니다.
알려주신 흠님., 감사드립니다.

뭔일인가 소스를 열어보니 어처구니없게도, </form>을 빼먹었더군요.
그래서 에러는 수정하고......

간혹 접속이 안좋은 경우에, 글은 올라가는데,
30초동안 방문자목록 접속이 없었다고 짤리는 경우가 있길래,
글을 올릴때, 방문자목록에 접속시간도 갱신되도록 했습니다.

대신에 방문자목록 접속간격을 새글확인 열번에 한번 -- 대략 10초마다 한번씩 하도록 했습니다.

...

사용자가 읽은 본문의 크기가 서버에 파일로 저장되니까,,,
혼자서 브라우저 두개 열어놓고 있으면- 제대로 출력이 안됩니다.
이쪽 브라우저에서 x만큼 읽어가면, 저쪽 브라우저에서는 그만큼 출력이 안됐는데,
이미 읽어간걸로 서버의 파일이 기록되어 있으니까, 그만큼 빼먹는거지요.
저쪽에서 읽으면, 이쪽에서 빼먹고......

브라우저하나로 사용해야 제대로 됩니다.


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

by Anna 안나 2008. 5. 26. 18:07
75버전까지는 인터넷회선 상태가 안좋을때는
- 퇴장했다,입장했다하는 문구가 자꾸 나왔는데,
(10초안에 접속이 없으면 그냥 나간걸로 표시했기 때문입니다.)

이번에는 window.onunload = function() {}
이렇게 onunload 이벤트에 함수를 실행시켜서,,
방문자데이타파일에 뭔가 기록을 하고,
그 상태로 갱신없이 10초가 지나면 나간걸로 판단하도록 했습니다.

10초 여유를 둔건, 브라우저 새로고침했을때도 그 이벤트가 발생하기 때문입니다.
그리고 FF에서 탭을 클릭해서 닫거나, FF자체를 종료시켜서 닫을때는
그 이벤트가 작동하지 않더군요.
(IE의 경우엔 모든 경우에 다 작동하던데)

그래서 그런 경우에 대비하기위해서
30초동안 접속이 없는 상태면 -
30초동안 접속이 없다고 표시하고, 나간걸로 판단하도록 했습니다.

프록시설정하고 테스트해보니까,, 그래도 30초동안 접속이 없었다고 표시되더군요.
((프록시가 워낙 늦고,상태가 안좋아서))

FF에서 새로고침하면
기존의 글이 안떴는데,
알고보니 FF에서는 새로고침해도, 출력된 인풋값들이 초기화되질 않는거 같더군요.
그래서 새글출력에 관련된 것들은 강제로 초기화되도록 소스를 넣었습니다.

기존에 새글읽는게, 그 파일크기를 클라이언트에 저장했다가,
그 값으로 호출해서, 파일크기가 그거보다 크면, 그 차이만큼 읽어오도록 했었는데,,,,,
프록시를 써서 해보니까,
워낙 상태가 안좋아가지고... 중복출력되는 경우가 가끔 있었습니다.
그니까 파일크기의 값이 서버에서 클라이언트로 왔다갔다하는게 잘 안되다보니까...

그래서 왔다갔다 안시키고, 그냥 서버에 저장되도록 했습니다.
(얼마만큼 읽어갔는지가 각자가 다르니까,, 사용자마다 각각의 파일로)
그래서 상태가 안좋아도, 중복출력되는 경우는 안생깁니다.

외관은 변하지 않았습니다.

--------------------

여기까지가 76버전의 설명이었습니다.
근데 76버전에서 파일업로드 문제가 발견되서,

파일업로드관련 문제랑, 몇몇가지 더.. 에러를 잡아서 77버전으로 올립니다.
76버전은 문제가 드러났으니까, 비공개하고..



mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:06
채팅방id가 숫자만으로 되면
"~~님이 입장하셨습니다" 라는 문구가 계속 반복되는 문제가 있었습니다.
....
$_SESSION[$id] 라는 것에 그 채팅방에 입장순번을 담아서
그 사람을 특정하고 있었습니다.
그래서 $$id = "_".순번; 이렇게 채팅방id자체를 변수로 만들어서,
session_register($id); 이렇게 등록하는데,,,,
예를들어 채팅방id가 1234라면,
$$id 가 $1234가 되어서,,, 변수가 성립하지 않는 문제였던거 같습니다.
(아마 $다음 첫글자가 숫자면 안되던가,,?? 였던걸로 기억납니다.)

그래서 자꾸 $_SESSION[$id]가 풀리면서
닉네임은 있되, 그 방에 새로 입장한 사람으로 판단하고
계속 "입장하셨습니다"라는 문구를 띄운 것입니다.

-- 그래서
$xd = "_".$id;
$$xd = "_".순번;
session_register($xd);
이렇게 바꾸고,
$_SESSION[$id] 대신에 $_SESSION["_".$id]로 호출하도록 바꿨습니다.
(요런거 할줄 몰랐는데, 필요해서 해보니까 되는군요)
더불어서 채팅방개설자를 구분하는 세션값도
비슷한 과정으로 조금 변동을 줬습니다.

채팅방id가 숫자라도, 변수로 쓸때는 앞에 "_" 이게 위치하니까
이제 에러가 안납니다.


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:06
대충 1초당 한번꼴로 서버에 접속해서
(GET으로 접속-출력된 filesize정보 보냄)
----- filesize가 보내온거하고 다르면
----- 새로 올라온 글이 있으면, filesize가 그만큼 늘어났을테니까
----- 그 차이만큼만 읽어오고,
----- 아니면
----- 구분자만 가지고 오는데,
----- 그 접속 다섯번에 한번 꼴로
----- 방문자목록 데이타를 읽고,편집,기록 합니다.
----- 방문자가 입장한 경우엔, 자기가 접속해서, 자기가 기록하지만
----- 퇴장한 경우엔, 그 사람은 이미 나갔기 때문에
----- 방문자목록에서의 삭제는 다른 사람의 접속때 이뤄집니다.
----- ----- 그래서 예제-채팅방에서 혼자 있다가, 나간경우 퇴장했다고 표시가 안됩니다.
----- ----- 그리고 중간에 다른 사람이 들어오지 않은채로, 다시 들어왔을때는
----- ----- ip나 같거나, 세션이 살아있으면, 동일인으로 취급해서, 역시 퇴장표시가 안됩니다.
.....

실제로 읽어오는 자료의 양은 많지 않습니다.
5초마다 한번 방문자목록,
----- 방문자의 닉네임하고 1byte짜리 구분자셋하고 그 사람의 순번세션값(99번 안쪽이면 3byte)
----- 닉네임이 한글이면 utf-8에서 3byte인데(여기서는 2byte인지 3byte인지 모르겠지만, 하여튼 3byte 잡고)
----- 닉네임이 한글 네자면 12 + 구분자 셋 3 + 순번값 3 = 18
----- 넉넉하게 한 사람에 20byte
----- 열명이면 200byte
----- 1초당으로 나누면, 40byte
그리고 새글이 올라왔을때, 올라온 글과 파일의 새크기.
----- 파일의 크기는 10240byte면 백업하고, 새로 생성하니까
----- 5자리까지 거의 안가고, 넉넉잡아 4byte
----- 1초당 새글이 한글 20자(3byte로 계산) 60byte 잡고,
----- 60byte + 구분자 두개 + 파일크기 4 + 방문자 초당 40 = 106
----- 106byte 인데,,,
----- 아주 많이 넉넉하게 잡아서 200byte라고 했을때,
----- 1시간 = 3600초로 계산하면
----- 703.125kb
----- 열명 잡았으니까 그거 열배라고 한다면 7031.25kb = 6.8664MB
----- 1시간 열명사용에 트래픽이 대충 7메가바이트
----- 라고 계산되는데.

트래픽 분석하는 프로그램으로 보면
혼자 예제에 방을 열어두고, 아무 글도 안올라오는 상태여도
초당 한 1KB쯤 되더군요.
내용말고 헤더정보 때문에,.

그래서 헤더정보가 트래픽계산에 들어가는지 궁금해서
찾아봤더니 - 못찾겠더군요.

혹시 이거 트래픽에 들어간다고 하면,
넉넉잡았을때 초당 200이 아니라, 1200으로 잡아야 합니다.
그럼 위의 계산보다 6배....
6.8664MB * 6 = 41.198MB

그니까 헤더정보가 포함된다고 할때
1시간동안 열명이서 넉넉하게 썼을때,
열명의 접속을 다 포함해서 41MB
by Anna 안나 2008. 5. 26. 18:05
알고보니 레이아웃을 박살내고
채팅방을 못쓰게 만들수 있는 태그가 많더군요.

그래서 고심끝에
위지윅으로 바꿔봤는데,
키보드로 내용을 치고, 바로 엔터(키보드)를 누르면
줄바꿈으로 가는 겁니다.. submit이 안되고,,

어찌저찌 onkeydown을 캡춰해다가, 이벤트를 걸어서 해볼라고도 해봤는데,
불안정적이더군요. 이벤트를 잡았다가 못잡았다가 하고...
-- 위지윅에서 글이 작성되는 곳은 iframe안의 공간이라서...
FF에서는 특히 더 안되고...

해서 위지윅은 포기하고,
위지윅은 아니고, 소스가 나열되는 식이긴 하지만, 여튼 비슷하게 태그지원기능을 해놨습니다.
그래서 거기서 버튼이나 선택상자로 추가한 html태그가 아닌 것은
거의 걸러서 작동하지 않도록 했습니다.

<img src=''> <a href=''> 이것도 안먹힙니다.
이미지를 넣거나, 링크를 걸고 싶을때는 그냥 http://~~ 주소를
내용에 넣어서 올리면 됩니다.


태그지원기능- 은.
그냥 이게 일회적인 게시판과는 달리,, 연속적인 성격이 있기 때문에,.
이전에 색상 선택하면 계속 이어졌듯이..
어떻게 할거냐... 고심을 했었는데,

내용중에 일부분을 블록(마우스긁음)으로 선택하면
그 영역안에만 적용되도록,
그렇지 않은 경우에는 전체적으로 적용되도록 했습니다.

연속성을 갖는건, 색상, 글꼴, 글자크기 입니다.(선택상자로 된 것)
딱히 영역을 선택하지 않고, 이 셋중에 하나를 선택했을때는
내용에 아무 변화가 없지만,
선택한 값이 $_POST로 전송되서, 올린글을 처리할때 전체를 감싸게 됩니다.

연속성이 없는 b, i, s, u 의 버튼은
영역을 따로 블록으로 잡지 않았을때, 전체적으로 앞뒤로 쌉니다.
--- 소스에 이미지를 되도록 포함하지 않을려고, span에다가 스타일로 버튼 비슷하게 만들었는데,
보기 싫으면 이미지파일을 만들거나 해서 바꿔주시면 됩니다.. (소스 726줄 근처)


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

((-------IMAGE-------))
by Anna 안나 2008. 5. 26. 18:04
- - '실시간메모'라고 이름붙였는데, 채팅방목록에
방문자리스트없는 간단한 채팅방을 달았습니다.
내용이 2KB에 도달하면, 512byte만 남기고 나머지는 삭제합니다.-채팅방에서처럼 백업되는게 아니라-
그래서 덩치가 거기서 더 불어나지 않으면서 계속적으로 존속합니다.
저장파일은 chat폴더안에 _xext
관리자가 저장파일 삭제-리셋할수 있는 버튼을 달았습니다.
금지닉네임 제한은 하고, 금칙어 제한은 안걸었습니다.
본문에 html태그는 허용되지 않습니다.

- - 글올리는 자바스크립트함수에서 군더더기로 남아있던거 지웠고...

- - $_POST로 올라온 닉네임에서 이것저것 삭제하고,
금지닉네임하고 같은지 판별하는 과정을
종전엔 모두 다 거치게 했었는데,,
세션닉네임이 없거나, 세션닉네임과 $_POST로 올라온 이름이 다른 경우에만 그 과정을 거치도록 수정...

- - 치명적인 실수 수정
$dpi=foepn()으로 열었다가 fclose($dpi)로 닫지 않고, fclose($dph)로 해둔 오류 발견
자칫하면 파일이 삭제되는데,, 이런 실수가 있었더군요. 바로잡았습니다.

- - 닉네임에는 탭문자 모두 삭제, 공백문자만으로 된 경우도 삭제합니다만
본문에는 삭제하지 않습니다. 어찌보면 그것도 표현의 방법일수 있기 때문에...
단,, 채팅방 레이아웃이 깨지는 것들은 막았습니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:04
1. 강퇴당했을때, 채팅방목록으로 돌아왔다가, 재차 클릭했을때
기존엔 화면에 x 글자 하나 있었는데, 다시 채팅방목록으로 되돌아오도록(자바스크립트로) 수정했습니다.

2. 금칙어 서버에서 처리하던걸, 자바스크립트로 되도록 바꿨습니다.
서버부하를 줄이고, 서버의 처리속도를 올리기 위해서.

3. 중복되는 내용 막는걸, 서버에서가 아니라 자바스크립트로 클라이언트에서 이뤄지도록 바꿨습니다.
역시 서버부하를 줄이고, 서버의 처리속도를 올리기 위해서.

4. 71버전에서 "채팅방아이디_순번" 형태였던 $_SESSION[$id] 값을 "_순번" 형태로 바꿨습니다.
줄어든만큼 트래픽이나 처리속도가 좋아집니다.

5. 체감속도를 빠르게하기 위한 여러가지 조치가 있었습니다.
체감속도를 빠르게하면서 또한, 안정적으로 동작하게 하기 위해서
자바스크립트의
new Date(); getTime(); 함수를 이용해서 1/1000 초까지 측정한 값을 사용합니다.

글을 확인하고-읽어오는 주기가 있는데
소스의 6번줄 $refresh = 1000; 이 값입니다. = 1초.
글을 확인하고 setTimeout으로 다시 호출하면서, 그 시점의 시간 + $refresh 값을 어딘가 저장합니다.

글을 작성완료했을때, 역시 그 시점의 시간을 재서,
앞서 저장된 시간(= 새글확인할 예정시간)이 가까우면(=0.25초 이하) 그냥 기다리고,
멀면(=0.25초 초과) 그 즉시 새글확인하는 함수를 호출합니다.

이렇게해도 같은 내용이 중복출력되는 등의 문제가 있길래,
글을 올린시점의 시간을 어딘가에 저장하고, = 새글확인을 호출한 시간
다시 글을 작성완료했을때의 시간이 먼저번에 작성완료한 시간에 너무 가까우면(0.35초이하)
새글확인하는 함수를 호출하지 않도록 했습니다.

소스의 586줄에 "350" 이란 숫자가 그겁니다.

하여튼 투다다닥하고.. 예제에서 테스트해봤더니,,
내용이 중복출력되었을때는 새로고침하면 줄수가 줄어드는데,,
그런 문제가 더이상 안보이더군요...

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:03
1. 전버전부터 본문에 시간표시되도록 했는데, 채팅기록에는 적용되지 않았던걸 고쳤습니다.

2. FF에서 padding이 <tr>에 안먹는거 때문에, 닉네임나오는 <td>에 padding:5px 0px 5px 0px를 줬었는데,
이름이 없는 경우 (안내문)도 있어서 본문에 걸었습니다.

3. 채팅방에 입장하는 사람의 ip를 전부 기록해서, 입장순으로 번호를 메겨서 세션에 저장하고,
그 번호로 그 사람을 특정하도록 했습니다. ip나 세션아이디를 대체해서..
입장순으로 발급하는 세션값이 없을때, ip저장된 파일을 열어서, 중복되는 ip가 있는지 확인하고,
없으면 새 번호, 있으면 그 ip가 있는 순서의 번호로 세션을 생성합니다.
ip가 중간에 달라지더라도, 세션값이 있으면 계속 동일인으로 간주합니다.
(이 값은 "채팅방아이디_번호"로 되어있고,
--그러고보니 굳이 이럴필요까진 없었군요,그냥 번호만으로도 충분할걸--
호출하는 값이 $_SESSION[$id]라서, 다른 방에서 만들어진거와 중복되질 않습니다.$id가 다르기 때문에)

4. 닉네임 바뀌었다는 안내문을 고쳤습니다.
다른 채팅방에 들어갔다가 닉을 바꾸고, 다시 그 채팅방으로 들어오는 경우에도 안내문이 뜨도록 했습니다.
물론 그냥 닉네임을 바꾸는 경우에도 뜹니다.

// 하여튼 내부적으로 많이 달라졌습니다. 외관은 달라진게 없지만...

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

((-------IMAGE-------))
by Anna 안나 2008. 5. 26. 18:03
우측에 작게 시간표시(시:분) 되살렸습니다.
본문에 ..........................................................................................~~계속~~................
이렇게 넣으니까 레이아웃이 깨지길래,
table-layout:fixed를 내용출력되는 테이블에 추가했습니다.

그렇게하니까
내용이 길때도 tr height=24 로 고정되고 글이 안보이길래,
height 정의한거 지우고 <tr class=h> 로 해서,
아래쪽에서 padding:6px 0px 6px 0px을 줬습니다.

그렇게했더니,
FF에서는 안먹히길래, <td class=n>에 padding:5px 0px 5px 0px 줘서
대충 ie랑 비슷하게 맞췄습니다.

session_id()를 보조적으로 사용하도록 했습니다.
중간에 ip가 바뀌는 경우에도 "퇴장했습니다. 입장했습니다" 하는게 반복되지 않도록..

귓속말 받은거 볼때는 여전히 ip를 기준으로 합니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

by Anna 안나 2008. 5. 26. 18:02
요구사항을 반영해서
ie6에서 먹히는 src="javascript:
ie7에서도 먹히는 href="javascript:
를 막았습니다.

그리고 내부적으로 구분자를 바꿨습니다.
(키보드상에 있지만, 기록될수 없는 문자 \x1b등으로)
-- 그래서 소스가 대폭적으로 수정되었습니다.

소스 9번줄부터
채팅에 쓰이는 색상 네가지를 변수로 담았습니다.
색상을 바꿀때 거기만 바꾸면, 전체적으로 바뀌도록 했습니다.
그 이상의 수정을 원할때는
이거에다가 소스 맨 아래쪽에 스타일부분 수정하면 어느정도 될거 같습니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:02
요구사항을 반영해서,
닉네임을 공백만으로는 설정되지 않도록,
닉네임에 <를 &lt;로 바뀌도록해서 태그사용 못하도록,
그리고 본문에 iframe 못쓰도록,
운영자는 금칙어제한을 받지 않도록
수정했습니다.


본문에 태그를 제한하는 부분은
소스 280줄에
$_POST[content] = preg_replace('`<(/?)(sc|!|co|t|if|x|p)`i', '&lt;$1$2', $_POST[content]);
이 부분입니다.
script, 주석, comment, textarea(table tr td), iframe, xmp, pre를 막기위해서 저렇게 설정했습니다.

그리고 채팅방개설할때 채팅방id 적는부분은 한글전환이 안되도록 했습니다.
(스타일에 ime-mode:disabled 추가해서)
비밀번호는 한글도 됩니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

by Anna 안나 2008. 5. 26. 18:02
"퇴장하셨습니다. 입장하셨습니다."
하고 나오는 방문자목록에서의 오류를 최대한 잡아봤습니다.
그 부분에 소스가 바뀌었습니다.

아마 이번에는..


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:01
채팅방 예제에서 보다보면,
"xxx님이 입장하셨습니다. 퇴장하셨습니다." 하는 구문이 너무 자주 나와서
보기가 좋지 않길래.
body에다가 onload, onUnload 이벤트에 걸었던거 삭제하고,
방문자목록에 연동해서 처리하도록 했습니다.

그리고 방문자목록에서 처리할때,
동일인이 퇴장하셨습니다. 입장하셨습니다. 이렇게 나오는 경우 많은데,
ip가 같으면 시간불문하고 그렇게 표시되지 않도록 했습니다.

방문자목록확인은 대략 4초// 새글확인 네번째마다// 되도록 했고,
방문자기록에서 삭제는 현시간 - 10초로 좀 넉넉하게 했습니다.

혼자서 테스트하느라고, FF에 프록시설정해서 해보니까,
프록시때문인지 너무 늦어서, 넉넉하게 줬음에도 자꾸 들어왔다니, 나갔다니 하는 표시가 되더군요.
뭐 워낙 접속속도가 느리니까 그랬던 것이고,
일반적인 접속환경에서는 거의 그럴일이 없을겁니다.

하여튼 그래서 좀 더 안정성을 높였습니다.

외관은 변한게 없구요.
내부적으로 수정된게 있으니까,,
디자인 수정해서 쓰시던 분들은 이전 버전하고 대조해서 수정하시기 바랍니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:01
대폭수정했습니다.
외관은 바뀐거 없고,,,,
내부에서 처리하는 것만.

기존에 ajax로 호출하는거 뭔가 분산되어 있던걸 하나로 통합했습니다.
자기가 글 올릴때 즉각 확인하도록 하는거-- 뺐습니다만,,
뭐 그래도 많이 느리진 않을겁니다.
속썩이던 방문자 목록이 어떻게 되었는지 확실히는 모르겠지만,
아마 안정되지 않았을까,, 추정합니다.


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:01
머리속에서 굴리자니 면적이 부족해서,,
말로 풀어서 벌려놓으면,,
좀 더 개요가 잘 드러날거 같아서..


음.. 기존에 그니까
채팅 이거 방식이
1초 또는 그 이하의 주기로 서버에 접속해서 filesize로 채팅내용이 저장된 파일크기를 재고
기존크기와 다르면 새글 올라온걸로 판단해서
새파일크기 가지고 들어와서 새글 읽는 과정으로 넘기고
..
방문자 목록은 또 따로 주기적으로 체크하고...
글쓰는부분 빼고, 요거만 세개가 따로따로 갔는데,

요걸 하나로 통합하면,, 좀 더 안정적으로 되지 않을까,, 하는 구상
filesize재서 크기가 다르면, 클라이언트로 끌고 들어오지 않고, 서버에서 그 즉시 새글 읽는 과정으로 가고,
.... 파일크기하고 새글부분을 구분자등으로 구분해서 가지고 들어오면
우선 두개는 통합될수 있겠는데,

방문자 목록은 1초 또는 그 이하의 주기로 새글 확인하는데,
그때마다 방문자목록 파일을 까뒤집는게... 뭔가 좀 소모적인것도 같고..

지금 방문자가 채팅방을 나갔을때, 거기 방문자목록에서 그 방문자기록이 빠져야 하니까,
filemtime으로 방문자목록파일 수정된게 있으면, 그때만 어떻게 처리하는 방향은
영 맞질 않고,,
자바스크립트에서 onunload에 이벤트거는게 쉽지만, FF 에서는 안돼고...

지금 불안정해서 문제가 되는 부분이 방문자 목록이고...


쇠똥이와 개똥이가 있다가
쇠똥이가 방을 나갔으면,
개똥이 혼자 있는걸로 표시돼야 하는데,
그러자니 방문자 목록에서 쇠똥이가 빠져야하고,
쇠똥이는 먼저 나갔으니까,,
방문자목록에서 쇠똥이가 빠지는건 개똥이가 접속했을때 서버에서 처리해야하는 것이고.
개똥이가 접속했을때 쇠똥이를 뺀다.....

현재는 기존 2.7초 (수정후 3.5초) 간격으로 주기적으로 접속하게 해서,
시간과 이름을 기록해서, 기록된 시간이 5초(4초/3초)이전의 것이면 삭제하도록 하고 있는데,,
조금 불안정한 모습을 보인다.

쇠똥이가 방문자목록에 마지막으로 접속해서 기록한 시간이 10시10분10초라면,
개똥이가 만약 10시10분13초에 거기 접속했을때, 5초 이전의 기록은 삭제하도록 하고 있으니까, 그때까진 쇠똥이 기록이 삭제되지 않고, -- 짤리는거건 8초이전까지.
개똥이가 3.5초 약 4초 이후에 10시10분17초에 접속했을때, 12초 이전이 짤리니까 쇠똥이의 목록이 그때 사라지도록 되어 있다.
쇠똥이가 만약에 나가지 않았다면 13초~14초에 다시 접속해서, 시간을 갱신하게 되니까 12초로 짜를때,,
짤리지 않게되는데,,,
이게 이론상으론 문제가 없는데, 실제로는 가끔 깜빡깜빡한다...

되도록 출입상황을 빨리 반영하도록 해야 하면서,,,
착오/오류 깜빡임없이 안정적으로 반영해야 하는데,,,,

만약에 3초주기/5초로 짜른다고 했을때
쇠가 0---3---6---9
개가 --2---5---8---11
로 접속한다고 하면,
개가 접속한 5초에 접속했을때, 이전 5초를 짜르니까, 0초를 마지노선으로 해서,
쇠의 경우는 3초에서 여유간격 2초.
개 본인의 경우는 2초에서 여유간격 3초.
충분히 여유간격이 되는거 같은데,, 가끔가다 문제가 생기곤 한다.

4초주기/6초기준으로 짜른다면,,
0---4---8---12---16---20---24---
-1---5---9---13---17---21---25---
--2---6---10---14---18---22---26---
---3---7---11---15---19---23---27---

7에서 짜를때, 7 - 6 =1
1 ~ 7초 사이에 접속이 없는걸 짜르니까
4- 여유 3/3초 앞으로 3, 뒤로 3
5- 여유 4/2
6- 여유 5/1
3- 여유 0/4

3초주기라면
0---3---6---9---12---15---18---21---
-1---4---7---10---13---16---19---22
--2---5---8---11---14---17---20---23
8초에서 5초기준으로 짜른다면
3 ~ 8초사이 접속없는 경우 짜르게 되니까
6- 3/2
7- 4/1
5- 0/3

접속간격을 일정하게 소스에 정해놨더라도, 실제로는 여건에 따라서
간격이 고무줄처럼 늘어날수가 있으니까,,
뭔가 좀 넉넉하게 해놓을 필요가 있는거다.


근데 어떻할까,,
음.. filesize 접속 세번에 한번꼴로 방문자목록 뒤엎는 방식?


filesize접속은 1초마다 되니까
서버에서 filesize체크해서 새글 올라왔으면 새글 읽어들이면서
filesize접속이 1,2,3 이렇게 횟수를 재서, 3번째면, 방문자목록을 갱신하는 방식..

음..
by Anna 안나 2008. 5. 26. 18:00
가끔 먹통이 되어서 F5(새로고침)이 필요하다는 얘기가 채팅방에 있길래.
새글 확인 주기를 700 (= 0.7초) 에서 1000 (=1초)로 바꾸면서,
그 확인주기=시간간격을 $refresh 라는 변수로 소스 7번째 줄에서 바꿀수 있도록 했습니다.
본인이 글을 올렸을때는, 그 즉시 읽어오도록 했습니다.

이게 특성상 테스트할려면 조력자가 있어야 하기 때문에,
테스트를 제대로 거치질 못하고 있습니다.
혹시 1초 주기에도 먹통이 되거나, 새로고침이 필요해진다면, 소스 7번째줄에 1000 이라는 값을
1200 이나 1500 으로 바꿔주면 좀 나을겁니다.

그리고 덧글에 얼마로 바꿨다는 얘기를 해주시면 감사하겠습니다.


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

by Anna 안나 2008. 5. 26. 18:00
여기저기 문제점이 몇군데 발견되어서 수정했습니다.
강퇴기능 미흡했던거 개선했습니다.
업로드파일만 삭제하는 기능은 없앴습니다.. 의미가 없는거 같아서.
(그냥 채팅방 삭제하면 전부 삭제됩니다.)

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 17:59
| 1 2 3 |