2009년 7월 29일 수요일

이벤트 핸들링

onAbort 이미지를 로딩하는 작업이 사용자의 행동으로 인해 취소되었을때
onBlur 문서나 윈도우, 프레임세트, 폼 요소에서 현재 입력 포커스가 사라질때
onChange 텍스트 필드나 텍스트 영역, 파일 업로드 필드, 선택 항목이 변경되어 현재 입력 포커스가 사라질 때
onClick 링크나 클라이언트측 이미지맵 영역, 폼 요소가 클릭되었을 때
onDbClick 링크나 클라이언트측 이미지맵 영역, 문서가 더블 클릭되었을 때
onDragDrop 드래그된 객체가 윈도우나 프레임에 드롭되었을 때
onError 이미지나 윈도우, 프레임을 로딩하는 동안 에러가 발생할 때
onFocus 문서나 윈도우, 프레임 세트, 폼 요소에 입력 포커스 놓였을 때
onKeyDown 키를 누를 때
onKeyPress 키를 눌렀다 놓았을 때
onKeyUp 키를 놓았을 때
onLoad 이미지나 문서, 프레임이 로드될 때
onMouseDown 마우스 버튼 누를 때
onMouseMove 마우스를 이동할 때
onMouseOut 링크나 클라이언트측 이미지맵에서 마우스를 옮길 때
onMouseOver 마우스를 링크나 클라이언트측 이미지맵으로 옮길 때
onMouseUp 마우스 버튼을 놓았을 때
onMove 사용자가 윈도우나 프레임에서 이동할 때
onReset 폼의 리셋 버튼을 클릭하여 폼을 리셋시킬 때
onResize 사용자가 윈도우나 프레임의 크기를 조절할 때
onSelect 텍스트는 텍스트 필드나 영역에서 선택되었을 때
onSubmit 폼이 제출될 때 (서브밋 버튼 눌렀을 때)
onUnload 사용자가 문서나 프레임 세트를 종료할 때

window.onload와 window::onload()

페이지 로딩시 시작할 스크립트 선언에 대해 <body onload="">의 onload를 많이 사용해 보았을 것입니다.

그리고 모든 페이지에서 공통으로 들어갈 스크립트는 페이지 마다 작성을 하지 않고, js 파일을 만들어 연결을 하여 사용을 할 것입니다.


여기서 그럼 모든 페이지에서 load시 공통으로 실행될 스크립트는 어떻게 작업을 할까요??

window.onload를 사용 하면 됩니다.


window.onload = function(){ 시작시 실행될 내용 }

이런식으로 말이죠.


그런데 문제는 window.onload와 <body onload="">는 동시에 사용을 할 수 없습니다.

<body onload="">가 실행이 되면 window.onload는 실행이 되지 않는 문제가 있습니다.


그래서 이를 해결하고자 할때 사용하는 것이

window::onload()입니다.

function window::onload(){ 시작시 실행될 내용 }

이렇게 사용을 하면 됩니다.


실행 순서는 <body onload="">가 먼저 실행되고, 이어서 window::onload()가 실행됩니다

모서리가 둥근 박스 (CSS)

.rtop, .rbottom{display:block; background: #FFFFFF;}
.rtop *, .rbottom *{display: block; height: 1px; overflow: hidden; }

.r { text-align: center; width:80px; font: bold 12px; color: #000000 }
.r1 { margin: 0 5px; background: #DEDEDE; height: 1px; }
.r2 { margin: 0 3px; border: solid #DEDEDE; border-width: 0 2px; }
.r3 { margin: 0 2px; border: solid #DEDEDE; border-width: 0 1px; }
.r4 { margin: 0 1px; border: solid #DEDEDE; border-width: 0 1px;  height: 2px}
.rc { border: solid #DEDEDE; border-width: 0 1px; }


<div class="r">

<b class="rtop"><b class="r1"></b><b class="r2"></b><b class="r3"></b>

<b class="r4"></b></b>

<div class="rc">
<a href='<? echo "$g_dir/index.php" ?>' target="_blank">상점가기</a>
</div>

<b class="rbottom"><b class="r4"></b><b class="r3"></b> <b class="r2"></b>

<b class="r1"></b></b></div>

팝업관련 스크립트 (팝업창 닫고, 부모 페이지로 이동)

function MovePage() {
  opener.location.href="member.php"
  window.close()
 }

<a href="javascript:MovePage();">글또는 이미지</a>

팝업창 닫고 부모창을 리로드

<script language="JavaScript" type="text/javascript">
opener.location.reload();
window.close();
</script>

팝업로그인 할때 팝업창을 닫고 부모창으로 리로드를 시켜줌

자바스크립트 php 연동 풍선도움말

<!-- 풍선도움말 스크립트 시작 -->
 <style>
 div.none { padding:15px 15px 15px 15px; width:200px; position:absolute; border-width:3; border-color:#cccccc; border-style:solid;font-size:9pt; background-color:#FFFFFF }
 </style>
 <script>
 <!--
 var preview="";
 var gobj="";
 function attachEvent_(obj, evt, fuc, useCapture) {
   if(!useCapture) useCapture=false;
   if(obj.addEventListener) { // W3C DOM 지원 브라우저
  return obj.addEventListener(evt,fuc,useCapture);
   } else if(obj.attachEvent) { // MSDOM 지원 브라우저
  return obj.attachEvent("on"+evt, fuc);
   } else { // NN4 나 IE5mac 등 비 호환 브라우저
  MyAttachEvent(obj, evt, fuc);
  obj['on'+evt]=function() { MyFireEvent(obj,evt) };
   }
 }

 function detachEvent_(obj, evt, fuc, useCapture) {
   if(!useCapture) useCapture=false;
   if(obj.removeEventListener) {
  return obj.removeEventListener(evt,fuc,useCapture);
   } else if(obj.detachEvent) {
  return obj.detachEvent("on"+evt, fuc);
   } else {
  MyDetachEvent(obj, evt, fuc);
  obj['on'+evt]=function() { MyFireEvent(obj,evt) };
   }
 }

 function MyAttachEvent(obj, evt, fuc) {
   if(!obj.myEvents) obj.myEvents= {};
   if(!obj.myEvents[evt]) obj.myEvents[evt]=[];
   var evts = obj.myEvents[evt];
   evts[evts.length]=fuc;
 }

 function MyFireEvent(obj, evt) {
   if(!obj.myEvents || !obj.myEvents[evt]) return;
   var evts = obj.myEvents[evt];
   for (var i=0;i<len;i++) {
  len=evts.length;
  evts[i]();
   }
 }

 function previewShow(e, obj, pv) {
   preview=pv;
   gobj=obj;
   attachEvent_(obj, "mousemove", previewMove, false);
   attachEvent_(obj, "mouseout", previewHide, false);
 }

 function previewMove(e) {
   var hb = document.getElementById(preview);
   if(hb.parentElement) hb.parentElement.style.display="";
   else hb.parentNode.style.display="";
   var evt = e ? e : window.event;
   var posx=0;
   var posy=0;

   if (evt.pageX || evt.pageY) { // pageX/Y 표준 검사
  posx = evt.pageX +8;
  posy = evt.pageY +16;
   } else if (evt.clientX || evt.clientY) { //clientX/Y 표준 검사 Opera
  posx = evt.clientX +10;
  posy = evt.clientY +20;
  if (window.event) { // IE 여부 검사
    posx += document.body.scrollLeft;
    posy += document.body.scrollTop;
   }
   }

   hb.style.left = posx + "px";
   hb.style.top = posy + "px";
 }

 function previewHide() {
   var hb = document.getElementById(preview);
   if(hb.parentElement) hb.parentElement.style.display="none";
   else hb.parentNode.style.display="none";

   detachEvent_(gobj,"mousemove", previewMove, false);
 }
 -->
 </script>
 <!-- 풍선도움말 스크립트 끝 -->


아래는 php부분에 입력

$i의 갯수만큼 출력되게 생성한다.


 echo "<td><a href='#' onmouseover=previewShow(event,this,'tt_kin_$i');><img src='img/icon3.gif' border=0></a><span style=display:none><div id=tt_kin_$i class=none>".$info2."</div></span></td>";

이미지가 지정크기보다 클 때만 자동 리사이즈

<img src="1.gif" width="187" height="32" alt="" border="0" onload="if(this.width>150){this.width=150}">

DOCTYPE HTML PUBLIC/....의 각 호환모드 DTD

HTML 4.01 호환모드


코드:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

가장 최근의 CSS 규격을 따름. 엘리먼트 배치가 자유로움, 스크롤링 레이어 같은건 사용불가능, position, display 속성과 구현 방법의 차이가 상이, frame 사용 불가능


HTML 4.01 엄격모드


코드:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

1999년 12월 24일 확정 규격. 권장하지 않는 element, attribute, frame 사용불가, 엘리먼트 배치가 엄격함, 일부태그가 완전히 먹통, 가장 이상적인 문서작성시 사용.



XHTML 1.0 호환모드


코드:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

1999년 12월 24일 확정된 프레임문서. frameset이 사용가능. 하지만 넷스케이프.. 파폭쪽의 frame은 전혀 작동 되지 않음



XHTML 1.0 엄격모드


코드:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

테이블 크기 고정하기[table-layout:fixed]

<table width="600" border="0" cellpadding="0" cellspacing="0" style="table-layout:fixed">
<tr>
<td height="auto" style="padding:20 20 20 20; word-break:break-all;"><%=contents%></td>
</tr>
</table>

1. style="table-layout:fixed"

    -> 테이블의 크기를 고정해 줍니다. 가로세로 모두 고정이 됩니다

2. style="word-break:break-all;"

    -> 1.의 방법으로 고정된 테이블에 긴 글을 넣을경우 가로가 고정되어 있으므로 글자가 잘려 보이는 경우가 발생.이것을 방지하고 글의 자동 줄바꿈 효과를 줍니다

3. height="auto"

   -> 1.의 방법으로 고정된 테이블의 세로때문에 글이 고정된 세로길이까지만 보입니다. 이것을 방지하기위해 세로의 길이를 오토로 조정해줍니다.

인풋텍스트 한글만 영문만 모드

style="ime-mode:auto"(자동변경)->한/영 전환가능

style="ime-mode:active"(한글모드) ->한/영전환가능

style="ime-mode:inactive"(영문모드)->오직영문

style="ime-mode:disabled"(영문모드)->한/영전환가능

style="ime-mode:deactivated"(한글모드)->한/영전환가능 

MySQL 데이터베이스 백업

MySQL 데이터베이스 백업 :

 

mysqldump -h서버 -u사용자 -p암호 [백업할 테이터베이스 이름] > [저장할 파일 이름(*.sql )]

 

>> mysqldump -hlocalhost -uroot -ppassword testdb1 > testdb1-2007-06-27.sql

 

MySQL 테이블 백업 :

 

mysqldump -h서버 -u사용자 -p암호 [테이타베이스] [백업할 테이블 이름] > [저장할 파일 이름(*.sql)]

 

>> mysqldump -hlocalhost -uroot -ppassword testdb1 tbl1 > testdb1-tbl1-2007-06-27.sql

 

MySQL 데이터베이스 복구:

 

mysql -h서버 -u사용자 -p암호 [복구할 테이터베이스] < [저장된 파일]

 

>> mysql -hlocalhost -uroot -ppassword testdb1 < testdb1-2007-06-27.sql 

sulinux 1.5 + 큐메일

큐메일에 대한 설치사례는 많지만 sulinux에서는 드문 경우라서 올려둔다.

http://www.qmailrocks.org/

위 사이트도 참고할만한 사이트이다. 내용도 잘정리되어 있고 기본적으로 레드햇이나 다른 버전의 설명도
함께 담고 있다.

아래는 내가 큐메일을 설치하면서 설정했던 값들과 설치했던 방법을 간략하게 적어보았다.
한번해보라 큐메일은 한번 설치가 되었다고 해서 간단하게 운영되지 않는다.
최근 네이버도 큐메일로 바꾼것 같던데 아니면 그이전부터 사용했는지도 모르겠다.
장점은 많다. 하지만 단점도 만만치 않은 설치부터 운영의 어려움까지 어느것하나 쉽지는 않다.
만일 운영을 할꺼라면 윈도우서버의 메일서버를 추천한다. 간단한 설치에 운영도 편하다.
메일서버의 가장 핵심기능은 뭐니뭐니 해도 스팸기능일 것이다.
이부분에 대해서는 큐메일도 마찬가지다. 결국 걸러서 받아낼 수 밖에 없다.
스팸메일서버로 사용될 일은 없겠지만 그래서 스팸이 안들어온다는 것은 아니다.
테스트해본 결과 무지막지하게 들어온다. 다른 스팸차단기를 사용해야 한다면 큐메일은 비추천이다.
연동하기 어려운 것보다는 쉬운게 좋다.
또 속도에 대해서는 그리 빠르다라고 느낄만한 수준이 아니다. 서버사양의 문제도 있겠지만
같은 서버로 테스트해본 결과 샌드메일서버나 큐메일이나 별반 차이가 없었다.
테스트는 3만건정도 했었다. 이정도라면 윈도우서버가 더 나은 편이다. 현재 회사의 메일서버는
윈도우메일서버를 운영하고 있다. 기존 샌드메일서버가 스팸서버로 해킹되는 바람에 어쩔 수 없이
갈아탔다. 이렇게 길게 설명했는데도 큐메일이 좋다고 생각한다면 어쩔수 없다.
한번 해보라 그래도 좋다고 한다면 메뉴얼을 잘 만들어서 여러 사람이 쓸 수 있도록 해주면 좋겠다.

1. openssl-devel 설치
yum install openssl-devel

2. Qmailrocks 설치
http://www.qmailrocks.org/download.htm

3. 다람쥐메일 설치

==============아래는 설치시 필요했는 설정값==================================

./config-fast webmail.adbank.co.kr

Country Name (2 letter code) [GB]: ko
State or Province Name (full name) [Berkshire]: adbank
Locality Name (eg, city) [Newbury]: adbank
Organization Name (eg, company) [My Company Ltd]: adbank.co.kr
Organizational Unit Name (eg, section) []: webmail
Common Name (eg, your name or your server's hostname) []: webmail.adbank.co.kr
Email Address []: postmaster@adbank.co.kr


echo "localhost|0|admin|5555|vpopmail" > ~vpopmail/etc/vpopmail.mysql

GRANT select,insert,update,delete,create,drop ON vpopmail.* TO admin@localhost IDENTIFIED BY '5555';

mysql -u admin -p

./configure --enable-cgibindir=/usr/local/apache_2.0.59/cgi-bin/ --enable-htmldir==/var/www/html

<Directory "/usr/local/apache_2.0.59/cgi-bin/vqadmin">
deny from all
Options ExecCGI
AllowOverride AuthConfig
Order deny,allow
</Directory>

cd /usr/local/apache_2.0.59/cgi-bin/vqadmin

/var/www/html/.htpasswd

chown nobody .htaccess

htpasswd -bc /var/www/html/.htpasswd admin 5555

chmod 644 /var/www/html/.htpasswd

./configure --enable-cgibindir=/usr/local/apache_2.0.59/cgi-bin/ --enable-htmldir=/var/www/html

echo postmaster@adbank.co.kr > /var/qmail/alias/.qmail-root

echo postmaster@adbank.co.kr > /var/qmail/alias/.qmail-postmaster

echo postmaster@adbank.co.kr > /var/qmail/alias/.qmail-mailer-daemon

rpm -e --nodeps sendmail-8.13.1-3.RHEL4.5.SULinux.1

rpm -e --nodeps sendmail-cf-8.13.1-3.RHEL4.5.SULinux.1

courierpassd 106/tcp #for /etc/xinetd.d/courierpassd

chown -R nobody:nobody /var/sqattachements

chown -R nobody:nobody data

<VirtualHost 211.203.170.86:80>
ServerName webmail.adbank.co.kr
ServerAlias mail.*
ServerAdmin postmaster@adbank.co.kr
DocumentRoot /var/www/webmail
</VirtualHost>

[php+웹메일]RoundCube Webmail

대부분 다람쥐메일을 사용해왔을 것이다.
하지만 디자인의 한계로 인해 많은 어려움이 있을 것이다. 나도 다람쥐메일로 웹메일을 개발해본적이 있지만
여간 귀찮은 일이 아니었다.

라운큐브웹메일은 그런 의미에서 상당한 웹메일일 것이다.
중소형의 웹메일를 운영하기를 원한다면 만족할 수 있을 것이다.

참고사이트 http://roundcube.net/

계속해서 버젼업을 하고 있는 중이다.
자세한 것은 사이트에서 참고하면 될 것이다.

단점으로는 다람쥐메일에서의 스팸기능이나 주소록등의 기능이 미약한 것이 흠이다.
하지만 AJAX로 연동되어 미려한 디자인은 그런 부분을 감수할 수 있을 것이다.

납품을 해야할 경우라면 좀 더 보완이 되어야 겠지만 개인적인 목적이라면
회사내의 웹메일로 써도 괜찮을 듯하다.

현재 roundcubemail-0.2.2.tar.gz 버젼까지 나와있다.

[php+검색엔진]orcasearch_2.3a 검색엔진

대학사이트를 개발하면 검색엔진이 필요해서 자료를 찾던 중 아주 뛰어난 검색엔진을 발견했다.
물론 GPL이다.

기존에는 SearchBlox 라는 검색엔진을 사용했는데 이것은 윈도우 서버용만 있고 리눅스서버용으로는
개발이 되지 않았다. (홈페이지에는 유닉스용으로는 있었다.) 결과적으로 중요한 것은
검색되는 페이지양이 제한되어 있다. 1000페이지로 말이다. 이런 난감한 상황에서
찾게 된것이 orcasearch 이다.

http://www.greywyvern.com/orca#search

위의 사이트에서 다운받을 수 있다. 영문버젼과 이탈이아버젼만 있다.
특징으로는 검색제한이 없다는 것과 자유로운 검색페이지 디자인 될 것이다.

그리고 환경은 php+mysql 로 비교적 설치도 간단하다. 윈도우서버에 apm 를 올리고 해봤지만
필요한 라이브러리가 제한적이어서 사용이 안된다.

그렇다고 방법이 없지는 않다. 리눅스서버에 올려서 검색하려는 사이트 주소만 넣어주면 얼마든지
연결해서 사용할 수 있기 때문이다.

검색속도도 만족할만하다. 기존 SearchBlox와 비교해서 속도의 차이가 없었다. 오히려 더 빠르고 정확한
검색결과를 보여주기도 했다.

현재는 영동대학교와 거창 승강기대학에 설치되어 운영중에 있다.
상용검색엔진에 비해서 손색없는 성능을 갖추었다고 할 수 있겠다.
포털사이트나 커뮤니티사이트를 개발시에는 연동해볼만 하겠다.

설치파일을 첨부한다.

[php+보안]한국정보보호진흥원 CASTLE 사용법

□ CASTLE의 주요기능
o 보안성 강화
- OWASP 10대 주요 취약점 해결
- 소스코드 수준의 웹 어플리케이션 보안성 강화
o 사용자 편리성 강화
- 관리기능으로 편리한 정책 설정 지원
- 운영 중인 프로그램 소스의 최소 수정으로도 적용 가능
o 높은 호환성 지원
- 다양한 웹 서버 환경과 웹 어플리케이션에서 동작할 수 있는 호
환성 지원

캐슬에 대한 진흥원에 기능설명이다. 실제 사용해본 결과 만족할 만한 수준이었고
현재 모대학 학과사이트에 적용해서 잘쓰고 있다.

기본에는 악성스팸글이 하루에도 수십건에 달했지만 현재는 전혀 올라오지 않고 있다.
로그를 살펴보면 완전히 차단되는 걸 알수 있다.

194.8.75.145 - [12/Jul/2009:00:47:58 +0900] /board/job/board.php: html_body = Hello,\r\ntortilia.info\r\nbuster! long one!  \r\nhttp://petheal: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: Fre...]
194.8.74.130 - [12/Jul/2009:01:20:44 +0900] /board/notice/board.php: html_body = <a href=\"http://forums.yahala.co.il/showthread.php?p=16749\">va: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: Buy]
194.8.74.130 - [12/Jul/2009:03:14:12 +0900] /board/notice/board.php: html_body = <a href=\"http://forums.yahala.co.il/showthread.php?p=16749\">va: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: Buy]
194.8.74.130 - [12/Jul/2009:05:14:20 +0900] /board/notice/board.php: html_body = <a href=\"http://forums.yahala.co.il/showthread.php?p=16749\">dr: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: sex]
194.8.74.130 - [12/Jul/2009:07:21:14 +0900] /board/notice/board.php: html_body = <a href=\"http://forums.yahala.co.il/showthread.php?p=16749\">ge: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: sex]
194.8.74.130 - [12/Jul/2009:09:33:34 +0900] /board/notice/board.php: html_body = <a href=\"http://forums.yahala.co.il/showthread.php?p=16749\">en: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: Buy]
99.250.211.177 - [12/Jul/2009:11:52:10 +0900] /board/job/board.php: html_body = buy tadalafil levitra buy levitra generic cheap allegra cialis v: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: Buy]
194.8.74.130 - [12/Jul/2009:11:55:47 +0900] /board/notice/board.php: html_body = <a href=\"http://forums.yahala.co.il/showthread.php?p=16749\">va: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: Buy]
194.8.74.130 - [12/Jul/2009:14:24:35 +0900] /board/notice/board.php: html_body = <a href=\"http://forums.yahala.co.il/showthread.php?p=16749\">va: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: Buy]
210.51.47.187 - [12/Jul/2009:16:33:45 +0900] /board/notice/board.php: subject = 【무료자료】유망자격증, 10급공무원, 독학사, 영어자료: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: 유망자격증]
210.51.47.187 - [12/Jul/2009:16:33:45 +0900] /board/faq/board.php: subject = 【무료자료】유망자격증, 10급공무원, 독학사, 영어자료: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: 유망자격증]
210.51.47.187 - [12/Jul/2009:18:15:37 +0900] /board/faq/board.php: html_body = 신청서가 보이지 않는분은 이쪽으로~ http://sawhi.co1.kr\r\n\r\n\r: XSS 공격 패턴 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: src[[:space:]]*=]
210.51.47.187 - [12/Jul/2009:18:16:03 +0900] /board/notice/board.php: html_body = 신청서가 보이지 않는분은 이쪽으로~ http://sawhi.co1.kr\r\n\r\n\r: XSS 공격 패턴 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: src[[:space:]]*=]
194.8.74.130 - [12/Jul/2009:19:43:51 +0900] /board/notice/board.php: html_body = <a href=\"http://forums.yahala.co.il/showthread.php?p=16749\">va: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: sex]
59.151.97.6 - [12/Jul/2009:21:01:21 +0900] /board/notice/board.php: subject = ♥로얄더비 ◆황금성 ♠바다이야기 ♣바카라: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: 바카라]
59.151.97.6 - [12/Jul/2009:21:01:22 +0900] /board/pds_class/board.php: subject = ♥로얄더비 ◆황금성 ♠바다이야기 ♣바카라: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: 바카라]
59.151.97.6 - [12/Jul/2009:21:01:22 +0900] /board/faq/board.php: subject = ♥로얄더비 ◆황금성 ♠바다이야기 ♣바카라: 금칙어 탐지
 -> [Method: POST]
 -> [Policy: 기본정책]
 -> [Pattern: 바카라]

사용법과 관련해서는 압축파일을 올려두겠다.
자세한 내용은 메뉴얼을 참고하면 될듯 하다.
참고사이트 http://www.krcert.or.kr




게시판 리스트 부분 프로그램

예전에 10만건인가 백만건 게시물부분에 대한 프로그램을 해본적이 있다.
뭐 여러 방법들이 많이 있고 어떤 부분에서는 상당히 알고리즘을 가진 것도 본적이 있다.
하지만 게시판이 무엇인가? 이 고민을 하게되니 10만건 혹인 백만건의 의미가 사라졌다.
자유게시판에 10만건 이상이 등록될 일도 없을 뿐더러 몇천건이라도 쌓이면 다행일 게시판을 위해
복잡한 프로그램을 할 필요는 없겠다. 싶어 간단하고 수정이 편한 게시판을 만들어 보았다.
아래는 그 일부분을 올려둔다.

 <table width=100% align=center border=0 cellpadding=4 cellspacing=1>
  <tr height=25>
   <td width=40 align=center class=board_title_bg>번호</td>
   <td align=center class=board_title_bg>제목</td>
   <td width=120 align=center class=board_title_bg>작성자</td>
   <td width=120 align=center class=board_title_bg>작성일시</td>
   <td width=100 align=center class=board_title_bg>조회수</td>
  </tr>
  <?
   if($qa_text) {
    $whereis = "where ".$state_str_sql." title like '%".$qa_text."%'";
   } else {
    $whereis = "where ".$state_str_sql;
   }
   $nTotalCount = selectCount("_webhard_bbs","idx",$whereis);

   $num_tt = $nTotalCount;
   $nPage = ceil($nTotalCount / $g_list_rows);
   if ($pg == "") $pg = 1;
   $nFrom = ($pg - 1) * $g_list_rows;
   $num_tt = $num_tt - (($pg - 1) * $g_list_rows);

   $contents = selectQuery("select * from $table ".$whereis." ".$order_txt." limit ".$nFrom.", ".$g_list_rows);

   if($nTotalCount < 1) {
    echo "<tr>
      <td colspan=7 height=40 align=center>자료가 없습니다.</td>
     </tr>";
   } else {
    for($i=0;$i<$g_list_rows;$i++) {
  ?>
  <tr>
   <td height="30" align="center" class=line_board_bottom><? echo $num_tt?></td>
   <td style="padding:0 0 0 10 " class=line_board_bottom><?=$contents[title][$i]?></td>
   <td align="center" class=line_board_bottom><?=$contents[writer][$i]?></td>
   <td align="center" class=line_board_bottom><?=date("Y-m-d H:i:s", $contents[regdate][$i])?></td>
   <td align="center" class=line_board_bottom><?=number_format($contents[hit][$i])?></td>
  </tr>
  <?
    $num_tt--;
    }
   }
  ?>
  <tr>
   <td>&nbsp;</td>
  </tr>
  <tr>
   <form name=frm_qa_search method=get action=file_list.php>
   <input type=hidden name="code" value="<?=$code?>">
   <input type=hidden name="qa_text" value="<?=$qa_text?>">
   <input type=hidden name="pg" value="<?=$pg?>">
   <td align=center colspan=7><input type=text name=qa_text value='<?=$qa_text?>' size=30> <input type=image src='./img/button/bt_seach.gif' align=absmiddle></td>
   </form>
  </tr>
  <tr>
   <td align=center colspan=6><?echo pageListing($pg, $nPage, $g_list_rows, "./file_list.php?code=$code&qa_text=$qa_text&pg=")?></td>
  </tr>
 </table>

게시판의 속도는 보통인 편이다. 그러나 적은 게시물을 가지고 있는 게시판에 응용해서 사용한다면
얼마든지 백만건게시판도 가능할 것이다. 어차피 디비는 가져오는 방식의 문제가 아닌가!
있는 디비를 손대기 어렵다면 어떻게 잘 가져올지 생각해보면 될 것 이다.

넉두리라면... 프로그램초기에는 디비를 어떻게 튜닝하는지 프로그램을 어떻게 짜는지도 몰랐지만
이제 몇년 하다보니 약간씩 눈에 들어오는 것은 대규모가 아니라면 역시 유지보수가 편한 심플형이
좋다라는 거다 사이트를 하루에 몇개씩 찍어내는 공장이나 혹은 중소형 홈페이지라도
결국은 가장 기본적인 부분에 출발하니 말이다.

게시물이 백만건이 쌓이기 전에 테이블을 분리하던지 게시판을 몇개를 더 만들어서 카테고리를 만드는것이
더 현명할 것이다. 디비튜닝보다는 회사에 하드웨어를 추가해달라고 하는게 더 정신건강에 좋을듯
그렇게 투자하기 싫다면 어쩔 수 없겠지만 말이다.

좋은 알고리즘을 가지고 프로그램 천라인을 써서 만들건지 기본적인 알고리즘으로 백라인안에
프로그램을 할지는 선택하는 사람의 몫이다.

[php+mysql]쿼리로 데이터 배열 받아오기

#쿼리로 데이터 배열 받아오기
function selectQuery($query){
 $result = mysql_query($query);
 while ($data = mysql_fetch_array($result,MYSQL_ASSOC)) {
  foreach ($data as $key => $value){
   $List[$key][] = $value;
  }
 }
 //print $query;
 return $List;  // example) <loop>print list[field][$i]</loop>;
}

[php+mysql]쿼리 총갯수 가져오기

#갯수 가져오기
function selectCount($table,$field="num",$where=""){
 $query = "SELECT count(".$field.") FROM ".$table." ".$where;
 $data = mysql_fetch_array(mysql_query($query));
 $return = $data[0];
 return $return;
}

용량계산

//용량계산
function parseSize($size){
 if($size < 1024){
  return $size."B";
 }elseif($size < pow(1024,2)){
  return number_format($size / pow(1024,1),'1')."K";
 }elseif($size < pow(1024,3)){
  return number_format($size / pow(1024,2),'1')."M";
 }elseif($size < pow(1024,4)){
  return number_format($size / pow(1024,3),'1')."G";
 }else{
  return number_format($size / pow(1024,4),'1')."T";
 }
}

[php+보안]XSS 공격 방어

//XSS 공격 방어
function RemoveXSS($val) {
   // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
   // this prevents some character re-spacing such as <java\0script>
   // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
   $val = preg_replace('/([\x00-\x08][\x0b-\x0c][\x0e-\x20])/', '', $val);

   // straight replacements, the user should never need these since they're normal characters
   // this prevents like <IMG SRC=&#X40&#X61&#X76&#X61&#X73&#X63&#X72&#X69&#X70&#X74&#X3A&#X61&#X6C&#X65&#X72&#X74&#X28&#X27&#X58&#X53&#X53&#X27&#X29>
   $search = 'abcdefghijklmnopqrstuvwxyz';
   $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
   $search .= '1234567890!@#$%^&*()';
   $search .= '~`";:?+/={}[]-_|\'\\';
   for ($i = 0; $i < strlen($search); $i++) {
      // ;? matches the ;, which is optional
      // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars

      // &#x0040 @ search for the hex values
      $val = preg_replace('/(&#[x|X]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
      // &#00064 @ 0{0,7} matches '0' zero to seven times
      $val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
   }

   // now the only remaining whitespace attacks are \t, \n, and \r
   $ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
   $ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
   $ra = array_merge($ra1, $ra2);

   $found = true; // keep replacing as long as the previous round replaced something
   while ($found == true) {
      $val_before = $val;
      for ($i = 0; $i < sizeof($ra); $i++) {
         $pattern = '/';
         for ($j = 0; $j < strlen($ra[$i]); $j++) {
            if ($j > 0) {
               $pattern .= '(';
               $pattern .= '(&#[x|X]0{0,8}([9][a][b]);?)?';
               $pattern .= '|(&#0{0,8}([9][10][13]);?)?';
               $pattern .= ')?';
            }
            $pattern .= $ra[$i][$j];
         }
         $pattern .= '/i';
         $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag
         $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
         if ($val_before == $val) {
            // no replacements were made, so exit the loop
            $found = false;
         }
      }
   }
   return $val;
}

2009년 7월 28일 화요일

웹페이지 압축

// 웹페이지 압축
ob_start('ob_gzhandler');

현재페이지,총페이지수,한페이지에 보여줄 목록수,URL

// 현재페이지,총페이지수,한페이지에 보여줄 목록수,URL
function pagelisting($cur_page, $total_page, $n, $url) {
 $retValue = "<table border='0' cellpadding='0' cellspacing='0'><tr>";
 if ($cur_page > 1) {
  $retValue .= "<td><a href='" . $url . "1'>[처음]</a>&nbsp;</td>";
  $retValue .= "<td><a href='" . $url . ($cur_page-1) . "'>[이전]</a></td>";
 } else {
  $retValue .= "<td>&nbsp;</td>";
  $retValue .= "<td>&nbsp;</td>";
 }
 $retValue .= "<td>&nbsp;";
 $start_page = ( ( (int)( ($cur_page - 1 ) / 10 ) ) * 10 ) + 1;
 $end_page = $start_page + 9;
 if ($end_page >= $total_page) $end_page = $total_page;
 if ($start_page > 1) $retValue .= "<a href='" . $url . ($start_page-1) . "'>[이전10개]</a> ";
 if ($total_page > 1) {
  for ($k=$start_page;$k<=$end_page;$k++) {
   if ($cur_page != $k) {
    $retValue .= " <a href='$url$k'> [$k] </a> ";
   } else {
    $retValue .= " <b>$k</b> ";
   }
  }
 }
 if ($total_page > $end_page) $retValue .= "<a href='" . $url . ($end_page+1) . "'>[다음10개]</a>";
 $retValue .= "&nbsp;</td>";
 if ($cur_page < $total_page) {
  $retValue .= "<td><a href='$url" . ($cur_page+1) . "'>[다음]</a></td>";
  $retValue .= "<td>&nbsp;<a href='$url$total_page'>[마지막]</a></td>";
 } else {
  $retValue .= "<td>&nbsp;</td>";
  $retValue .= "<td></td>";
 }
 $retValue .= "</tr></table>";
 return $retValue;
}

글자자르기

// 글자자르기
// cutstr("글내용", "글자수", "...") {
function cutstr($msg, $cut_size, $tail="...") {
 if ($cut_size<=0) return $msg;

 // 계속이어쓰는 문자열을 자른다.
 $max_len = 70;
 if(strlen($msg) > $max_len) {
  if(!eregi(" ", $msg)) {
   $msg = substr($msg,0,$max_len);
  }
 }

 for($i=0;$i<$cut_size;$i++) {
  if(@ord($msg[$i])>127) {
   $han++;
  } else {
   $eng++;
  }
 }

 $cut_size=$cut_size+(int)$han*0.6;

 $snow=1;
 for($i=0;$i<strlen($msg);$i++) {
  if ($snow>$cut_size) { return $snowtmp.$tail;}
  if (ord($msg[$i])<=127) {
   $snowtmp.= $msg[$i];
   if ($snow%$cut_size==0) { return $snowtmp.$tail; }
  } else {
   if ($snow%$cut_size==0) { return $snowtmp.$tail; }
   $snowtmp.=$msg[$i].$msg[++$i];
   $snow++;
  }
  $snow++;
 }
 return $snowtmp;
}

샌드메일서버를 이용한 메일보내기

// 샌드메일서버를 이용한 메일보내기
// authMail("보내는 사람 이메일", "보내는 사람 이름 ", "받는 사람 이메일", "받는 사람 이름", "제목", "내용");
function authMail($from, $namefrom, $to, $nameto, $subject, $message) {
 //환경설정
 $smtpServer = "메일서버주소 아이피 혹은 도메인"; //ip accepted as well
 $port = "25"; // should be 25 by default
 $timeout = "30"; //typical timeout. try 45 for slow servers
 $username = "아이디"; //the login for your smtp
 $password = "비밀번호"; //the pass for your smtp
 $localhost = "127.0.0.1"; //this seems to work always
 $newLine = "\r\n"; //var just for nelines in MS
 $secure = 0; //change to 1 if you need a secure connect

 //connect to the host and port
 $smtpConnect = fsockopen($smtpServer, $port, $errno, $errstr, $timeout);
 $smtpResponse = fgets($smtpConnect, 4096);
 if(empty($smtpConnect)) {
    $output = "Failed to connect: $smtpResponse";
    return $output;
 } else {
    $logArray['connection'] = "Connected to: $smtpResponse";
 }

 //say HELO to our little friend
 fputs($smtpConnect, "HELO $localhost". $newLine);
 $smtpResponse = fgets($smtpConnect, 4096);
 $logArray['heloresponse'] = "$smtpResponse";

 //start a tls session if needed
 if($secure) {
    fputs($smtpConnect, "STARTTLS". $newLine);
    $smtpResponse = fgets($smtpConnect, 4096);
    $logArray['tlsresponse'] = "$smtpResponse";

    //you have to say HELO again after TLS is started
    fputs($smtpConnect, "HELO $localhost". $newLine);
    $smtpResponse = fgets($smtpConnect, 4096);
    $logArray['heloresponse2'] = "$smtpResponse";
 }

 //request for auth login
 fputs($smtpConnect,"AUTH LOGIN" . $newLine);
 $smtpResponse = fgets($smtpConnect, 4096);
 $logArray['authrequest'] = "$smtpResponse";

 //send the username
 fputs($smtpConnect, base64_encode($username) . $newLine);
 $smtpResponse = fgets($smtpConnect, 4096);
 $logArray['authusername'] = "$smtpResponse";

 //send the password
 fputs($smtpConnect, base64_encode($password) . $newLine);
 $smtpResponse = fgets($smtpConnect, 4096);
 $logArray['authpassword'] = "$smtpResponse";

 //email from
 fputs($smtpConnect, "MAIL FROM: $from" . $newLine);
 $smtpResponse = fgets($smtpConnect, 4096);
 $logArray['mailfromresponse'] = "$smtpResponse";

 //email to
 fputs($smtpConnect, "RCPT TO: $to" . $newLine);
 $smtpResponse = fgets($smtpConnect, 4096);
 $logArray['mailtoresponse'] = "$smtpResponse";

 //the email
 fputs($smtpConnect, "DATA" . $newLine);
 $smtpResponse = fgets($smtpConnect, 4096);
 $logArray['data1response'] = "$smtpResponse";

 //construct headers
 $headers = "MIME-Version: 1.0" . $newLine;
 $headers .= "Content-type: text/html; charset=euc-kr" . $newLine;
 $headers .= "To: $nameto <$to>" . $newLine;
 $headers .= "From: $namefrom <$from>" . $newLine;

 //observe the . after the newline, it signals the end of message
 fputs($smtpConnect, "To: $to\r\nFrom: $from\r\nSubject: $subject\r\n$headers\r\n\r\n$message\r\n.\r\n");
 $smtpResponse = fgets($smtpConnect, 4096);
 $logArray['data2response'] = "$smtpResponse";

 // say goodbye
 fputs($smtpConnect,"QUIT" . $newLine);
 $smtpResponse = fgets($smtpConnect, 4096);
 $logArray['quitresponse'] = "$smtpResponse";
 $logArray['quitcode'] = substr($smtpResponse,0,3);
 fclose($smtpConnect);
 //a return value of 221 in $retVal["quitcode"] is a success
 return($logArray);
}

파일업로드

// 파일업로드
// upload_file("업로드파일", "저장할 파일명", "저장위치");
function upload_file($srcfile, $destfile, $dir) {
 if ($destfile == "") return false;
 // 업로드 한후 , 퍼미션을 변경함
 @move_uploaded_file($srcfile, "$dir/$destfile");
 @chmod("$dir/$destfile", 0666);
 return true;
}

파일 확장자 검사

// 파일 확장자 검사--------------------------------------------------------------------------------
// check_file_ext("파일명", "허용확장자리스트 ;로 구분");
function check_file_ext($filename, $allow_ext) {
 if ($filename == "") return true;
 $ext = get_file_ext($filename);
 $allow_ext = explode(";", $allow_ext);
 $sw_allow_ext = false;
 for ($i=0; $i<count($allow_ext); $i++) {
  if ($ext == $allow_ext[$i]) { // 허용하는 확장자라면
   $sw_allow_ext = true;
   break;
  }
 }
 return $sw_allow_ext;
}
function get_file_ext($filename) {
 if ($filename == "") return "";
 $type = explode(".", $filename);
 $ext = strtolower($type[count($type)-1]);
 return $ext;
}

경고메세지 출력

// 경고메세지 출력
// alert_msg("정상적인 접근이 아닙니다.", "/index.php");
function alert_msg($msg, $url="") {
    if($url == "") {
  $url = "history.go(-1)";
 } else {
  $url = "document.location.href = '".$url."'";
 }

 if($msg != "") {
  echo "<script language='javascript'>alert('".$msg."');".$url.";</script>";
 } else {
  echo "<script language='javascript'>".$url.";</script>";
 }
}

php에서 날짜 계산하기

echo strftime("%Y-%m-%d", strtotime("now")), "<br>\n";
echo strftime("%Y-%m-%d", strtotime("10 September 2000")), "<br>\n";
echo "하루전 ".strftime("%Y-%m-%d", strtotime("-1 day")), "<br>\n";
echo "내일 ".strftime("%Y-%m-%d", strtotime("+1 day")), "<br>\n";
echo "일주일 전 ".strftime("%Y-%m-%d", strtotime("-1 week")), "<br>\n";
echo "일주일 후 ".strftime("%Y-%m-%d", strtotime("+1 week")), "<br>\n";
echo "일주일 + 2일 + 4시간 +2초 ".strftime("%Y-%m-%d %H:%M:%S", strtotime("+1 week 2 days 4 hours 2 seconds")), "<br>\n";
echo "다음주 수요일 ".strftime("%Y-%m-%d", strtotime("next Thursday")), "<br>\n";
echo "마지막 월요일 ".strftime("%Y-%m-%d ", strtotime("last Monday")), "<br>\n";

PHP $_SERVER[] 함수

$_SERVER['DOCUMENT_ROOT'] = 현재 사이트가 위치한 서버상의 위치 => /webapp/include

$_SERVER['HTTP_ACCEPT_ENCODING'] = 인코딩 방식 => gzip, deflate

$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 언어 => ko

$_SERVER['HTTP_USER_AGENT'] = 사이트 접속한 사용자 환경 => Mozilla/4.0(compatible; MSIE 6.0; Windows NT 5.1; Q312461; .NET CLR 1.0.3705

$_SERVER['REMOTE_ADDR'] = 사이트 접속한 사용자 IP => xxx.xxx.xxx.xxx

$_SERVER['SCRIPT_FILENAME'] = 실행되고 있는 위치와 파일명 => webapp/include/index.php

$_SERVER['SERVER_NAME'] = 사이트 도메인 => www.crazy-cupid.com

$_SERVER['SERVER_PORT'] = 사이트가 사용하는 포트 => 80

$_SERVER['SERVER_SOFTWARE'] = 서버의 소프트웨어 환경 => Apache/1.3.23 (Unix) PHP/4.1.2 mod_fastcgi/2.2.10 mod_throttle/3.1.2 mod_ssl/2.8.6 OpenSSL/0.9.6c

$_SERVER['GATEWAY_INTERFACE'] = cGI 정보 => CGI/1.1

$_SERVER['SERVER_PROTOCOL'] = 사용된 서버 프로토콜 => HTTP/1.1

$_SERVER['REQUEST_URI'] = 현재페이지의 주소에서 도메인 제외 =>  /index.php?user=???&name=???

$_SERVER['PHP_SELF'] = 현재페이지의 주소에서 도메인과 넘겨지는 값 제외 =/ index.php

$_SERVER['APPL_PHYSICAL_PATH'] = 현재페이지의 실제 파일 주소 => D:\webapp/

HTML 특수문자코드표

HTML 특수문자코드표

 

표현문자

숫자표현

문자표현

설명

-

&#00;-&#08;

-

사용하지 않음

space

&#09;

-

수평탭

space

&#10;

-

줄 삽입

-

&#11;-&#31;

-

사용하지 않음

space

&#32;

-

여백

!

&#33;

-

느낌표

"

&#34;

&quot;

따옴표

#

&#35;

-

숫자기호

$

&#36;

-

달러

%

&#37;

-

백분율 기호

&

&#38;

&amp;

Ampersand

'

&#39;

-

작은 따옴표

(

&#40;

-

왼쪽 괄호

)

&#41;

-

오른쪽 괄호

*

&#42;

-

아스트릭

+

&#43;

-

더하기 기호

,

&#44;

-

쉼표

-

&#45;

-

Hyphen

.

&#46;

-

마침표

/

&#47;

-

Solidus (slash)

0 - 9

&#48;-&#57;

-

0부터 9까지

:

&#58;

-

콜론

;

&#59;

-

세미콜론

<

&#60;

&lt;

보다 작은

=

&#61;

-

등호

>

&#62;

&gt;

보다 큰

?

&#63;

-

물음표

@

&#64;

-

Commercial at

A - Z

&#65;-&#90;

-

A부터 Z까지

[

&#91;

-

왼쪽 대괄호

\

&#92;

-

역슬래쉬

]

&#93;

-

오른쪽 대괄호

^

&#94;

-

탈자부호

_

&#95;

-

수평선

`

&#96;

-

Acute accent

a - z

&#97;-&#122;

-

a부터 z까지

{

&#123;

-

왼쪽 중괄호

|

&#124;

-

수직선

}

&#125;

-

오른쪽 중괄호

~

&#126;

-

꼬리표

-

&#127;-&#159;

-

사용하지 않음

&#160;

&nbsp;

Non-breaking space

¡

&#161;

&iexcl;

거꾸로된 느낌표

&#162;

&cent;

센트 기호

&#163;

&pound;

파운드

¤

&#164;

&curren;

현재 환율

&#165;

&yen;

|

&#166;

&brvbar;

끊어진 수직선

§

&#167;

&sect;

섹션 기호

¨

&#168;

&uml;

움라우트

&#169;

&copy;

저작권

ª

&#170;

&ordf;

Feminine ordinal

&#171;

&laquo;

왼쪽 꺾인 괄호

&#172;

&not;

부정

­

&#173;

&shy;

Soft hyphen

?

&#174;

&reg;

등록상표

&hibar;

&#175;

&macr;

Macron accent

°

&#176;

&deg;

Degree sign

±

&#177;

&plusmn;

Plus or minus

²

&#178;

&sup2;

Superscript two

³

&#179;

&sup3;

Superscript three

´

&#180;

&acute;

Acute accent

μ

&#181;

&micro;

Micro sign (Mu)

&#182;

&para;

문단기호

·

&#183;

&middot;

Middle dot

¸

&#184;

&cedil;

Cedilla

¹

&#185;

&sup1;

Superscript one

º

&#186;

&ordm;

Masculine ordinal

&#187;

&raquo;

오른쪽 꺾인 괄호

¼

&#188;

&frac14;

4분의 1

½

&#189;

&frac12;

2분의 1

¾

&#190;

&frac34;

4분의 3

¿

&#191;

&iquest;

거꾸로된 물음표

A

&#192;

&Agrave;

Capital A, grave accent

A

&#193;

&Aacute;

Capital A, acute accent

A

&#194;

&Acirc;

Capital A, circumflex accent

A

&#195;

&Atilde;

Capital A, tilde

A

&#196;

&Auml;

Capital A, dieresis or umlaut mark

A

&#197;

&Aring;

Capital A, ring (Angstrom)

Æ

&#198;

&AElig;

Capital AE diphthong (ligature)

C

&#199;

&Ccedil;

Capital C, cedilla

E

&#200;

&Egrave;

Capital E, grave accent

E

&#201;

&Eacute;

Capital E, acute accent

E

&#202;

&Ecirc;

Capital E, circumflex accent

E

&#203;

&Euml;

Capital E, dieresis or umlaut mark

I

&#204;

&Igrave;

Capital I, grave accent

I

&#205;

&Iacute;

Capital I, acute accent

I

&#206;

&Icirc;

Capital I, circumflex accent

I

&#207;

&Iuml;

Capital I, dieresis or umlaut mark

Ð

&#208;

&ETH;

Capital Eth, Icelandic

N

&#209;

&Ntilde;

Capital N, tilde

O

&#210;

&Ograve;

Capital O, grave accent

O

&#211;

&Oacute;

Capital O, acute accent

O

&#212;

&Ocirc;

Capital O, circumflex accent

O

&#213;

&Otilde;

Capital O, tilde

O

&#214;

&Ouml;

Capital O, dieresis or umlaut mark

×

&#215;

&times;

Multiply sign

Ø

&#216;

&Oslash;

width="130"Capital O, slash

U

&#217;

&Ugrave;

Capital U, grave accent

U

&#218;

&Uacute;

Capital U, acute accent

U

&#219;

&Ucirc;

Capital U, circumflex accent

U

&#220;

&Uuml;

Capital U, dieresis or umlaut mark

Y

&#221;

&Yacute;

Capital Y, acute accent

Þ

&#222;

&THORN;

Capital Thorn, Icelandic

ß

&#223;

&szlig;

Small sharp s, German (sz ligature)

a

&#224;

&agrave;

Small a, grave accent

a

&#225;

&aacute;

Small a, acute accent

a

&#226;

&acirc;

Small a, circumflex accent

a

&#227;

&atilde;

Small a, tilde

a

&#228;

&auml;

Small a, dieresis or umlaut mark

a

&#229;

&aring;

Small a, ring

æ

&#230;

&aelig;

Small ae diphthong (ligature)

c

&#231;

&ccedil;

Small c, cedilla

e

&#232;

&egrave;

Small e, grave accent

e

&#233;

&eacute;

Small e, acute accent

e

&#234;

&ecirc;

Small e, circumflex accent

e

&#235;

&euml;

Small e, dieresis or umlaut mark

i

&#236;

&igrave;

Small i, grave accent

i

&#237;

&iacute;

Small i, acute accent

i

&#238;

&icirc;

Small i, circumflex accent

i

&#239;

&iuml;

Small i, dieresis or umlaut mark

ð

&#240;

&eth;

Small eth, Icelandic

n

&#241;

&ntilde;

Small n, tilde

o

&#242;

&ograve;

Small o, grave accent

o

&#243;

&oacute;

Small o, acute accent

o

&#244;

&ocirc;

Small o, circumflex accent

o

&#245;

&otilde;

Small o, tilde

o

&#246;

&ouml;

Small o, dieresis or umlaut mark

÷

&#247;

&divide;

Division sign

ø

&#248;

&oslash;

Small o, slash

u

&#249;

&ugrave;

Small u, grave accent

u

&#250;

&uacute;

Small u, acute accent

u

&#251;

&ucirc;

Small u, circumflex accent

u

&#252;

&uuml;

Small u, dieresis or umlaut mark

y

&#253;

&yacute;

Small y, acute accent

þ

&#254;

&thorn;

Small thorn, Icelandic

y

&#255;

&yuml;

Small y, dieresis or umlaut mark