일단 코드먼저...
getFileList (Language : java)
  1. private void getFileList(File targetPath, ArrayList arr) {
  2.     long timeBefore = 86400;        //하루(86400초) 이전 수정된 파일만.
  3.  
  4.     if(targetPath.isDirectory()) {
  5.         String [] fl = targetPath.list();
  6.         File tmpFile = null;
  7.         long nTmp;
  8.         int filecnt = 0;
  9.        
  10.         for(int i=0;i<fl.length;i++) {
  11.             tmpFile = new File(targetPath.getAbsolutePath()+"/"+fl[i]);
  12.             if(tmpFile.isDirectory()) {
  13.                 getFileList(tmpFile, arr);
  14.             } else {
  15.                 if(fl[i].substring(fl[i].lastIndexOf(".")).toUpperCase().equals(".JPG")) {    //확장자가 jpg인 경우만
  16.                     nTmp = tmpFile.lastModified();
  17.                     nTmp = new java.util.Date().getTime() - nTmp;
  18.                     nTmp /= 1000;   //ms를 초단위로 변경
  19.                     if(nTmp <= timeBefore) {                //시간내 변경된 파일만
  20.                         arr.add(targetPath.getAbsolutePath()+"/"+fl[i]);
  21.                         filecnt++;
  22.                     }
  23.                 }
  24.             }
  25.         }
  26.  
  27.     } else {
  28.     }
  29. }
  30.  


이녀석 역시 재귀호출로 디렉토리 안에 디렉토리디렉토리....줄줄이 엮어들어가서 죄다 뽑아오는 로직..
24시간 이전 변경된 JPG파일 리스트만 뽑아오지만 뭐 쓰기나름임다... 수정은 알아서...

유닉스기반에서 작성한거라 디렉토리구분자가 다른 윈도우(역슬래쉬..죠..)에서 잘 작동할지는 의문?

간단하게 어케쓰느냐 궁금하신분들을 위해...


이~그잼플. (Language : java)
  1. ArrayList arr = new ArrayList();
  2. // /home/hy054nz는 반드시 디렉토리.
  3. // hy054nz안의 디렉토리와 파일들 목록이 절대경로로 arr로 들어감
  4. getFileList(new File("/home/hy054nz"), arr);
  5.  
  6. for(int i=0;i<arr.size();i++) {
  7.     out.println((String)arr.get(i));
  8. }


뭐.. 이런식으로 쓰면 되겠죠?
Posted by [czar]
,

Enterprised Distributed Technologies(이하 EDT)의 FTPClient 클래스를 이용해
자바 내에서 FTP전송(업로드)하는 방법을 알아보세~

공식 사이트는 http://www.enterprisedt.com/products/edtftpj/overview.html (새 창으로 열기)

그리고 API는 http://www.enterprisedt.com/products/edtftpj/doc/api/index.html (새 창으로 열기)

EDT의 메인페이지로 가면 HTML/JS버전과 .net을 위한 버전도 있으므로 참고하자.


먼저 연결,

FTP 접속 및 로그인 (Language : java)
  1. FTPClient ftp = new FTPClient("localhost");
  2. ftp.login("account", "password");


버뜨,
호스트를 바로 주어 연결하는건 deprecated되었단다,
인자 없이 생성하여 setter메소드를 사용하는걸 api에선 추천한다.

또 버뜨,
테스트로 개발한 녀석이 deprecated되기 전 jar라서 그냥 이대로 설명을...-_-;

어쨌든, 연결을 하고 나면 저 ftp라는 변수로 여러 작업을 할 수 있다.
자세한건 doc을 참고하고, 메소드로 만들어놓은걸 보면,


파일 업로드하기 (Language : java)
  1. private boolean TransferFile(FTPClient ftp, String toSend) {
  2.     try{
  3.         String ext = toSend.substring(toSend.lastIndexOf(".")+1).toUpperCase();
  4.         if(ext.equals("TXT")) {
  5.             // 전송모드 ASCII로 설정.
  6.             ftp.setType(FTPTransferType.ASCII);
  7.         } else {
  8.             // 전송모드 BINARY로 설정
  9.             ftp.setType(FTPTransferType.BINARY);
  10.         }
  11.  
  12.         String relativePath = toSend.substring(strClientRoot.length());
  13.  
  14.         String upPath;
  15.         if(relativePath.lastIndexOf("/") < 0)
  16.             upPath = strServerRoot;
  17.         else
  18.             upPath = strServerRoot + relativePath.substring(0, relativePath.lastIndexOf("/"));
  19.  
  20.         String [] dir = ftp.dir(upPath);
  21.         if(dir == null || dir.length == 0) {
  22.             // 업로드 패스 없음, 생성
  23.             mkDir(ftp, upPath);
  24.         }
  25.  
  26.         // 파일 업로드
  27.         ftp.put(strClientRoot+relativePath, strServerRoot+relativePath);
  28.        
  29.         return true;
  30.     }catch(Exception e) {
  31.         e.printStackTrace();
  32.         return false;
  33.     }
  34. }
  35.  


FTPClient 인스턴스와 로컬 파일명을 주면 샤삭.. 업로드 해준다.
ASCII와 BINARY는 txt확장자만 되어 있으나 if문에 html이나 htm이나 뭐 암튼 추가하면 되고....
strServerRoot나 strClientRoot.. 뭐 이런 변수는 클래스 전역으로 있는 녀석들이고... 대충 보면 알껌다.

요기서 중요한건,
전송모드(ASCII/BINARY)설정하는거랑
FTPClient.put 메소드라는거. put()메소드도 인자 따라 오버라이드 되어있으므로 역시 api참고.


저기서 사용한 mkDir()메소드는 만든겁니다.
FTPClient에도 mkdir()이라는 메소드가 있지만 2depth이상 존재하지 않을땐 여지없이 Exception을 띄우길래
허접하게나마 작성. 한 코드를 공개하자면,


리모트 디렉토리 생성 (Language : java)
  1. private boolean mkDir(FTPClient ftp, String path) {
  2.     if(path.charAt(path.length()-1) == '/')
  3.         path = path.substring(0, path.length()-1);
  4.  
  5.     String parentPath = path.substring(0, path.lastIndexOf("/"));
  6.     String [] dir;
  7.  
  8.     try{
  9.         dir = ftp.dir(parentPath);
  10.     }catch(Exception e) {
  11.         dir = null;
  12.     }
  13.  
  14.     if(dir == null || dir.length == 0) {
  15.         while(!mkDir(ftp, parentPath));
  16.         try{
  17.             ftp.mkdir(path);
  18.         }catch(Exception e) { }
  19.         return false;
  20.     } else {
  21.         try{
  22.             ftp.mkdir(path);
  23.         }catch(Exception e) { }
  24.         return true;
  25.     }
  26. }
  27.  


이래 됨다... 역시나 재귀호출이죠,
ftp.mkdir()을 다 따로 try-catch절로 묶어놓은 이유는
테스트컴 jar가 구버전이라 FTPClient.exists()메소드를 지원하지 않아서
FTPClient.dir()메소드를 사용해서 존재/미존재 여부를 파악하는데
디렉토리 내부에 파일이 없을 경우 legnth가 0이 되기 때문에 FTPClient.mkdir()을 실행합니다.
근데! 이미 존재할 경우 mkdir()에서 예외가 발생하기 땀시... 각기 따로따로...


어쨌든, 클래스 만든애들이 제공하는 apidoc만큼 정확한 정보는 없으니
api document를 참고하시고...
뭐 대충 이런게 있다라는것만... -ㅅ-; (글싸질러놓고 도망가기..)
Posted by [czar]
,
var img = new Image();
  img.dynsrc = fileName;
  setTimeout("funcDummy()",1000);
  var fileSize = img.fileSize;


  document.all.FileUp.disabled = false;
  var fso = new ActiveXObject("Scripting.FileSystemObject");
  var f = fso.GetFile(fileName);
  var fileSize = f.size;
  f = null;
  fso = null;

  ※ 단! 보안설정에서 스크립트에 대한 사용권한을 허용해주어야 작동됩니다.

Posted by [czar]
,

text-align

카테고리 없음 2008. 4. 28. 11:49

text-align


텍스트를 포함한, 적용 가능한 요소들의 가로 또는 세로의 정렬에 대한 설명과 함께 텍스트의 들여쓰기 및 행처리에 관한 내용을 살펴보도록 합니다.


[ 텍스트의 가로 정렬 ]

text-align: left (default value);

이 값은 하위 요소로 상속이 되며, 모든 요소에 적용할 수 있는 값입니다. 예를 들어, 블록 레벨 요소인 박스에 설정을 해두면, 해당 박스 안쪽에 있는 모든 요소에 적용이 됩니다. 디폴트 값은 브라우저와 글자의 표기 방향에 따라 다르지만, 일반적으로 left인 경우가 많습니다.


* left, right, center, justify

테이블의 tr, td태그에 사용되는 HTML속성값인 align과 비슷한 방법으로 박스등에 사용할 수 있습니다.

justify는 브라우저에 의해 자동으로 줄바꿈 되는 하나의 행을, 좌우 배분 정렬합니다. 블록 레벨 요소나 라인 브레이크와 같이, 강제적으로 줄바꿈 되는 부분까지 좌우 배분하는 것은 아닙니다. 그리고, justify속성값은 letter-spacing(자간), word-spacing(단어 간격)설정보다 우선시 됩니다.

[ 텍스트의 세로 정렬 ]

vertical-align: baseline (default value);

값을 지정한 요소가 표시되는 하나의 행에서 세로 방향의 위치 정렬에 관한 속성입니다.

단, 인라인 요소에만 적용되며, 테이블의 tr, th, td등의 요소에는 적용됩니다. 값은 상속되지 않습니다.


tr, HTML tr CSS
align="center" text-align: center;
valign="top" vertical-align: top;

위에서와 같이, text-align속성은 모든 요소에 적용할 수 있으며, vertical-align속성은 tr, td등의 요소에는 적용이 됩니다. 따라서, HTML의 align, valign을 대치하여 같은 효과를 얻을 수 있습니다.

주) tr, td등에 사용되는 vertical-align의 경우, 속성값 top, middle, bottom만이 valign값에 대응하여 적용됩니다. 브라우저간의 차이는 있으나, 기타 속성값은 대부분 무효화되며 기본값으로 처리됩니다.


아래와 같이 블록레벨 요소인 박스에 vertical-align속성을 부여하는 경우, tr, td등에 적용했던 것과 같은 결과를 얻을 수 없습니다. vertical-align은 tr, td에 적용할 수는 있으나, 인라인 요소에만 사용할 수 있기 때문입니다. 즉, 해당 요소가 표시되는 하나의 행에서의 세로 방향의 위치 정렬을 설정하는 것이 vertical-align의 정의입니다.

text-align: center; vertical-align: text-bottom;

박스 안에서의 세로 정렬은, 박스의 세로 크기를 지정하기 보다는, 다음과 같이 적절한 패딩값을 이용합니다.

text-align: center; margin: 0; padding: 10px 0;
* baseline, bottom, text-bottom
인라인 요소간의 베이스 라인을 맞추는 값입니다.
<img src="naver_logo.gif" style="border: 1px solid #000000; vertical-align:xxxx;"/>
  • vertical-align:not used;
  • vertical-align:baseline;
  • vertical-align:bottom;
  • vertical-align:text-bottom;
위와 같이, 텍스트 사이에 있는 이미지에 vertical-align옵션을 주었습니다.
디폴트 값은 baseline이기 때문에, 아무런 설정을 하지 않으면 baseline과 같이 표현됩니다. 참고할 점은 baseline과 text-bottom의 차이입니다. baseline은 텍스트의 ex(소문자 x의 상하)의 아래에 맞추기 때문에, 외곽 박스와는 맞아 떨어지지 않습니다. 그러나, text-bottom은 텍스트의 em(전각: 전체의 상하)에 맞추기 때문에, 외곽 박스와도 맞아 떨어지게 됩니다.
주) bottom 속성값은 IE7의 경우 정상적으로 적용되지 않습니다. 그러나, Firefox2.0의 경우 text-bottom과 같은 결과를 보여 줍니다.
* top, text-top
인라인 요소간의 탑 라인을 맞추는 값입니다.
<img src="naver_logo.gif" style="border: 1px solid #000000; vertical-align:xxxx;"/>
  • vertical-align:not used;
  • vertical-align:top;
  • vertical-align:text-top;
위와 같이, 텍스트 사이에 있는 이미지에 vertical-align옵션을 주었습니다.
별다른 차이없이, 텍스트의 em(전각: 전체의 상하)에 맞추어 표시해 줍니다. IE7과 Firefox2 사이의 차이도 없습니다. 단, 앞서 설명하였듯이 text-top속성값은 tr, td태그에는 적용되지 않습니다.
* 실수값+단위
디폴트 상태(baseline)에서, 해당 요소를 세로 방향으로 어느정도 이동시킬 것인지를 결정합니다.
양수값은 해당요소를 위쪽으로 이동시키게 되며, 음수값은 아래쪽으로 이동시킵니다.
<img src="naver_logo.gif" style="border: 1px solid #000000; vertical-align:xxxx;"/>
  • vertical-align:not used;
  • vertical-align:0px;
  • vertical-align:-1px;
이미지를 기본정렬 상태에서 1px만큼 아래쪽으로 내려보았습니다.
퍼센티지(%)의 경우는, 디폴트 상태(baseline)에서, line-height의 비율만큼 이동시킵니다. 예를 들어, line-height가 20px이고, vertical-align: 10%으로 설정하면 2px만큼 위쪽으로 올리게 됩니다.
* middle, super, sub
세로의 가운데 정렬을 하는 속성값으로 middle이 있으며, 위첨자(super), 아래첨자(sub)속성으로 해당 요소를 배치하는 값입니다.
<img src="naver_logo.gif" style="border: 1px solid #000000; vertical-align:xxxx;"/>
  • vertical-align:middle;
  • vertical-align:super
  • vertical-align:sub
middle의 경우, baseline과 같이 ex(소문자 x의 상하)의 중심을 기준으로 정렬합니다. 위와 같이, IE7에서는 1px정도의 어긋남이 발견됩니다. super, sub 속성값은, HTML의 sup, sub태그와 비슷한 용도로 사용이 가능합니다. 다만, 첨자 요소에 이미지를 사용한다거나, 첨자의 글꼴, 색상, 크기를 자유롭게 조절할 수 있다는 점이 CSS의 vertical-align: super, sub이 갖는 장점이라고 할 수 있습니다.

[ 문단 들여쓰기 ]

text-indent: 0 (default value);

하위 레벨 요소에 값이 상속되며, 블록 레벨 요소에 지정하여, 해당 요소에 포함된 문잔의 첫번 째 라인을 들여쓰기 해줍니다. 따라서, 음수값을 지정할 수도 있으며, 문단 들여쓰기라는 특성상 인라인 레벨 요소에는 설정되지 않습니다.

* 실수값+단위

<div style="width: 500px; line-height: 15px; text-indent: 1em; text-align:justify;">

Wie has been mixing school and tour golf since she played three LPGA Tour events at age 12. She turned professional in October 2005 and earned close to $20 million this year from endorsements, earnings and appearance money overseas.

And while she still hasn't won on the LPGA Tour -- she had three close calls in the majors -- Wie said her nerves were never more jangled than
waiting to see if she had been accepted. She got the news Friday.

위 예는 <p></p>로 묶인 2개의 문단이 있으며, 그 외곽을 <div></div>태그로 감싸고 있습니다.
외곽 박스(div)에 text-index: 1em즉, 전각 1개의 문자 만큼 들여쓰기 설정을 해 두었습니다. 안쪽의 모든 문단(<p></p>로 묶인 2개의 문단)에 들여쓰기가 적용됩니다. 중간의 빨간색으로 설정한 텍스트에는 라인브레이크(<br/>)가 적용되어 있습니다. 들여쓰기는, 문단의 첫줄에만 적용되기 때문에, 라인브레이크에는 영향을 주지 않습니다.
* 퍼센티지(%)
기본적으로, 적용된 요소(박스)를 포함하는 상위 박스의 너비값에 대한 비율로 지정합니다.
그러나, Firefox는 적용한 요소(박스)의 너비값을 기준으로 들여쓰기를 하고 있으며, IE의 경우, 마크업에 에러를 종종 경험하게 됩니다. 그다지, 퍼센티지(%)를 사용해야할 이유는 없어 보입니다.

[ 공백 및 행 처리 ]

white-space: normal (default value);

HTML의 <Pre>태그와 비슷한 역할을 수행할 수 있으며, nowrap이라는 추가적인 속성을 사용할 수 있습니다. 모든 요소에 적용할 수 있으며, 하위 요소에 설정값이 상속됩니다.

* normal, nowrap, pre

<div style="width: 500px; margin: 0; padding: 10px; white-space: normal;">

function resetRadio(){ for(var i=0; i<document.form1.type.length; i++){ if(document.form1.type[i].defaultChecked == true) document.form1.type[i].checked = true else document.form1.type[i].checked = false } }

일 반적으로, 박스안에 스크립트 코드와 같은 내용을 입력하면, HTML을 기본 마크업에 따라, 연속된 공백이나 탭, 줄바꾸기(소스상 줄바꾸기)가 하나의 공백으로 변환되어 표시됩니다. 또한, 박스의 너비에 따라 자동으로 줄바꾸기가 됩니다.

<div style="width: 500px; white-space: nowrap; overflow: hidden;">

function resetRadio(){ for(var i=0; i<document.form1.type.length; i++){ if(document.form1.type[i].defaultChecked == true) document.form1.type[i].checked = true else document.form1.type[i].checked = false } }

디폴트 상태와 같이 연속된 공백이나 탭, 줄바꾸기(소스상 줄바꾸기)를 하나의 공백으로 변환하여 표시합니다. 그러나, 박스의 너비를 무시하고 줄바꾸기를 하지 않습니다. (박스 외곽으로 넘치는 부분은 overflow속성을 이용해, 숨김설정으로 해두었습니다.)

<div style="width: 500px; margin: 0; padding: 10px; white-space: pre; overflow: hidden;">

function resetRadio(){
  for(var i=0; i<document.form1.type.length; i++){
    if(document.form1.type[i].defaultChecked == true) document.form1.type[i].checked = true
    else document.form1.type[i].checked = false
  }
}

HTML 소스에 입력한 데로 공백이나 탭, 줄바꾸기를 그대로 표시합니다. 이 경우도, 박스의 너비를 무시하고 줄바꾸기를 하지 않습니다. (박스 외곽으로 넘치는 부분은 overflow속성을 이용해, 숨김설정으로 해두었습니다.)

<div style="width: 500px; margin: 0; padding: 10px; white-space: pre; overflow: hidden;">

function resetRadio(){

...

}

</div>

위와 같이, 박스 태그와 내용의 첫번째 줄바꿈의 경우 IE7은 표기하지 않지만, Firefox2는 표기합니다.

따라서, 다음과 같이 박스 태그와 박스 내용 사이의 소스에 줄바꿈을 없도록 해주어야 합니다.

<div style="width: 500px; margin: 0; padding: 10px; white-space: pre; overflow: hidden;">function resetRadio(){

...

}

</div>

[ 참고 ]

HTML :: pre

다음은, HTML의 pre태그를 사용한 예입니다.

<div style="width: 500px; margin: 0; padding: 10px;">

<pre style="margin: 0; padding: 0; width: 480px; overflow: hidden;">

위와 같이 pre태그 역시, 글꼴등의 기본스타일을 따로 지정해 사용해야 합니다. 따라서, 상위레벨에서 지정된 스타일을 적용받으면서, 공백 및 행처리를 하는데에는 white-space를 이용하는 것이 유리합니다.

pre태그는 white-space와 달리, 박스 태그와 내용의 첫번째 줄바꿈에 대하여, IE7, Firefox2 모두 표기하지 않습니다.


Posted by [czar]
,

1) 자바스크립트 지시자나 스타일시트 지시자에 타입정보가 꼭 필요하다.
<script language="JavaScript" type="text/javascript">
<style type="text/css">

2) img,  map 태그등에 모두 alt 속성이 필요하다.

3) td는 background 속성을 지원하지 않으므로 스타일 시트형태로 표현한다.
<td style="background-image:url('/img/img.gif');"></td>

4) table은 height 속성을 지원하지 않는다.
<table height="100%"> <-- 에러

5) tr은 colspan, height 속성을 지원하지 않는다.
<tr height="30" colspan="2"> <-- 에러

6) body태그는 2개이상있으면 안된다.
body에 onLoad때문이라면 body태그대신
<script language="JavaScript" type="text/javascript">
window.onload = funcName(arg1,arg2);
</script>
형식으로 한다.

7) 스타일시트 font-family 에 한글 parsing이 안되는 문제가 있다
font-family:돋움 의경우 font-family:Dotum 으로 변경한다.

8) 스타일시트 선언은 <head> 안에서 해줘야한다. <body> 안에서 선언하면 에러 -_-
<head>
<link href="./style.css" rel=stylesheet type='text/css'>
</head>

9) html 안에 bgcolor나 width,height값을 %단위로 속성 삽입시 코텐션빠지면 에러
<td height="1" colspan="2" bgcolor="#ffffff"></td>
<table width="100%">
위와같이 "" 또는 '' 로 감싸줘야한다.

10) form 태그가 table 안에 있으면 에러 table을 감싸고 있어야한다. table 안에 있으면 에러
<form>
<table><tr><td></td></tr></table>
</form>
또한 form태그안에는 name속성과 action 속성이 모두 존재해야한다.
<map 태그역시 table 바깥에 위치해야함

11) 이미지서브밋에 width, height, border 속성을 쓰면 에러.
<input type="image" src="images/button_search.gif" align="bottom">
위와같이 align 속성은 쓸수 있음

13) url 쿼리스트링의 경우 & 기호는 다음과같이 인코드해주어야한다.
&
<a href="/dir/file.php?id=111&pwd=222">xxxxxxxx</a>

14) img태그나 기타 태그 속성중에 align="absmiddle" 는 비표준 middle 로 수정

15) 스타일을 표현할때 width, height 값에 px 안붙이면 에러, 색상코드에 # 안붙이면 에러
style="width:10px;height:20px;#FFFFFF;"

16) hidden 태그경우 <table 안에 들어있으면 에러.. 즉 form 안에 table 밖에 위치
즉 form태그 안에 table태그 밖에 위치해야함

17) body태그에 leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" 부분 있으면 에러
style="margin:0px;" 형태로 바꿔준다.

18) 자바스크립트 변수에 html 닫힘태그 쓸때는 escape문자로 표현한다.
<a href='url'>url<\/a>

19) 플래쉬 삽입
<object type="application/x-shockwave-flash" data="<?=$IndexImg?>/index_main.swf" width="260" height="487">
  <param name="movie" value="<?=$IndexImg?>/index_main.swf">
  <param name="quality" value="high">
</object>
플래쉬 태그에 classid나 codebase를 쓰면 에러. 다만 js형태로 밖으로 빼놓으면 에러 못찾음 -_-;;

20) 주석에 + 기호달면 에러
<!-- ----------- + ---------------- -->
위의 형태 에러남..

21) DocType를 페이지 맨상단(html태그 밖)에 정의해야함
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

22) TEXT-DECORATION 의 스타일 표현형태
TEXT-DECORATION: none
TEXT-DECORATION: yes(x) -> TEXT-DECORATION: underline

Posted by [czar]
,
아직도 System.out.println()으로 디버그용 메시지를 화면에 출력한다면, 이제 삽질 그만하고 로깅 API들을 사용해 볼 것을 권장하고 싶다.

그 중에서도 난 Log4j를 사용한다. (사실 이거밖에 모른다... ;) )

혹 여 log4j.properties 설정이 귀찮아서 Log4J를 사용하지 않는다면 다음의 기본적인 log4j.properties를 사용해보자. 이것만으로도 System.out.println과는 비교할 수 없는 강력하고 편리한 로깅 기능을 사용할 수 있다.

기본적인 log4j.properties
아래 로그설정은 로깅 메시지를 화면에도 출력하고 파일로도 출력한다. 파일의 경우에는 매일매일 날짜별로 다른 파일을 사용하므로 한개의 로그 파일이 무한정 커지는 것을 걱정할 필요는 없다.

이 설정대로 하면 로깅 메시지에 로그를 남긴 소스파일의 이름과 소스에서 메소드 이름과 줄 번호까지 출력된다. System.out.println()으로는 꿈도 못꾸는 기능들이다.

log4j.rootLogger = DEBUG, stdout, dailyfile

log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p (%F[%M]:%L) [%d] - %m%n

log4j.appender.dailyfile.Threshold = DEBUG
log4j.appender.dailyfile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyfile.File = logfile.log
log4j.appender.dailyfile.layout = org.apache.log4j.PatternLayout
log4j.appender.dailyfile.layout.ConversionPattern=%5p (%F[%M]:%L) [%d] - %m%n

저기서 logfile.log 가 로그의 내용을 출력할 파일 이름이다. 적당히 다른 이름으로 바꾼다. 절대경로로 줘도되고 위와 같이 상대경로로 줘도 된다.

위 파일을 클래스패스가 걸린 디렉토리에 두면 된다. 웹 어플리케이션은 WEB-INF/classes에 두면 된다.

로그는 어떻게 남기지?
각 클래스에서 로그를 남길 때는 다음과 같이..

// 로거 임포트하기
import org.apache.log4j.Logger;

public class ClassName {
    /** Log4J 로거 얻기 */
    private Logger log = Logger.getLogger(ClassName.class);

    public void method() {

        if (log.isDebugEnabled()) {
            log.debug("디버깅용 메시지");
        }
        log.info("정보를 남기기위한 메시지");
       
        try {
            //어쩌구 저쩌구 실행...
        } catch (Exception ex) {
            //로그에 예외 메시지도 함께 남기기
            log.error("예외가 발생했어요~~", ex);
        }
    }
}

ClassName.class는 로거가 출력할 클래스의 이름이다. 그냥 항상 클래스이름.class로 하면 된다.

만약 static 메소드에서 로거를 사용해야 한다면 로거를 생성하는 부분을

private static Logger log = Logger.getLogger(ClassName.class);


위와 같이 static 으로 선언하면 된다.

실제로 로그 메시지 출력이 어떻게 되는지는 직접 확인해보면 알 수 있을 것이다.

마무리~
자, 이제 프로그램에서 보기 싫은 System.out.println()을 몽땅 없애버리자!!
Log4J하나만으로도 디버깅하기 쉽고 뽀대나고 어딘가 비싸보이는 프로그램이 된다. ^^;
by 권남
 
출처 :  http://kwon37xi.egloos.com/2176487
Posted by [czar]
,
AJAX의 사용성에 대해 실제 프로젝트에서 쉽고 유용하게 사용할 수 있는 Naver의 키워드 검색 기능을 구현해 봄으로써 AJAX가 어떻게 사용되어지는지에 대해 간단하게 살펴보자.



xmlhttp.js
function paramEscape(paramValue)
{
   return encodeURIComponent(paramValue);
}

function formData2QueryString(docForm)
{  
   var submitString = '';
   var formElement = '';
   var lastElementName = '';
  
   for(i = 0 ; i < docForm.elements.length ; i++)
   {
     formElement = docForm.elements[i];
     switch(formElement.type)
     {
        case 'text' :
        case 'select-one' :
        case 'hidden' :
        case 'password' :
        case 'textarea' :
           submitString += formElement.name + '=' + paramEscape(formElement.value) + '&';
           break;
        case 'radio' :  
           if(formElement.checked)
           {
             submitString += formElement.name + '=' + paramEscape(formElement.value) + '&';
           }
           break;
        case 'checkbox' :  
           if(formElement.checked)
           {
             if(formElement.name = lastElementName)
             {
                if(submitString.lastIndexOf('&') == submitString.length - 1)
                {
                   submitString = submitString.substring(0, submitString.length - 1);
                }
                submitString += ',' + paramEscape(formElement.value);
             }
             else
             {
                submitString += formElement.name + '=' + paramEscape(formElement.value);
             }
             submitString += '&';
             lastElementName = formElement.name;
           }
           break;
     }                                                                            
   }
   submitString = submitString.substring(0, submitString.length - 1);
   //document.all("result").value = submitString;
   return submitString;                              
}

function xmlHttpPost(actionUrl, submitParameter, resultFunction)
{
   var xmlHttpRequest = false;
  
   //IE인경우
   if(window.ActiveXObject)
   {
     xmlHttpRequest = new ActiveXObject('Microsoft.XMLHTTP');
   }
   else
   {
     xmlHttpReq = new XMLHttpRequest();
     xmlHttpReq.overrideMimeType('text/xml');
   }  
       
   xmlHttpRequest.open('POST', actionUrl, true);
   xmlHttpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
   xmlHttpRequest.onreadystatechange = function() {
     if(xmlHttpRequest.readyState == 4)
     {
        switch (xmlHttpRequest.status)
        {
           case 404:
             alert('오류: ' + actionUrl + '이 존재하지 않음');
             break;
          case 500:
             alert('오류: ' + xmlHttpRequest.responseText);
             break;
          default:
             eval(resultFunction + '(xmlHttpRequest.responseText);');
             break;    
        }       
     }
   }
  
   xmlHttpRequest.send(submitParameter);            
}                        


ajax_search.html
<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html;" charset="euc-kr">
<SCRIPT type="text/javascript" src="http://jaso.co.kr/xmlhttp.js"></SCRIPT>

<SCRIPT Language="javascript">
<!--
     
function keywordKeyDown()
{
    var keyCode = window.event.keyCode;
   
    if(keyCode ==  9)   return;     //Tab 키
    if(keyCode == 13)   return;     //Enter 키
    if(keyCode == 16)   return;     //Shift 키
    if(keyCode == 16)   return;     //Ctrl 키
    if(keyCode == 18)   return;     //Alt 키
    if(keyCode == 45)   return;     //Ins 키
    if(keyCode == 46)   return;     //Del 키
    if(keyCode == 33)   return;     //PgUp 키
    if(keyCode == 34)   return;     //PgDn 키
    if(keyCode == 35)   return;     //End 키
    if(keyCode == 36)   return;     //Home 키
   
    if(keyCode >= 37 && keyCode <= 40)   return;     //방향키
   
    //Keydown 이벤트 발생 시점에는 아직 TextField에 사용자가 입력한 키 값이 설정되지 않았기 때문에
    //브라우저가 이벤트에 반응하여 값을 설정할때 까지 잠시 기다린다.
    setTimeout('submitSearchKeyword()', 250);    

}

function submitSearchKeyword()
{
    var url = 'http://jaso.co.kr/searchKeyword.jsp';
    var queryString = formData2QueryString(document.MAIN_FORM);
    var resultProcessMethod = 'viewSearchKeywordResult';
   
    xmlHttpPost(url, queryString, resultProcessMethod);
}
               
function viewSearchKeywordResult(result)
{
    if(result == "")
    {
        var searchKeywordDiv = document.all("searchKeyword");
        searchKeywordDiv.innerHTML = "";
        searchKeywordDiv.style.visibility = "hidden";
    }
    else
    {
        var resultList = result.split('|');
        var viewResult = '';
        for(i = 0 ; i < resultList.length; i++)
        {
            if(i == 0)  viewResult += '<B>' + resultList[i] + '</B> <A href="javascript:hiddenSearchKeywordResult();">[닫기]</A><BR>'
            else        viewResult += '<A href="javascript:setKeyword(\'' + resultList[i] + '\');">' + resultList[i] + '</A><BR>'
        }       
        var searchKeywordDiv = document.all("searchKeyword");
        searchKeywordDiv.innerHTML = viewResult;
        searchKeywordDiv.style.visibility = "visible";
    }
}
   
function hiddenSearchKeywordResult()
{
    var searchKeywordDiv = document.all("searchKeyword");
    searchKeywordDiv.innerHTML = "";
    searchKeywordDiv.style.visibility = "hidden";
}
   
function setKeyword(selectedKeyword)
{
    document.MAIN_FORM.keyword.value = selectedKeyword;    
}
               
//-->
</SCRIPT>

<STYLE type="text/css">
<!--
  .scroll_div { scrollbar-face-color:#FFFFFF;
                scrollbar-highlight-color: #aaaaaa;
                scrollbar-3dlight-color: #FFFFFF;    
                scrollbar-shadow-color: #aaaaaa;
                scrollbar-darkshadow-color: #FFFFFF;
                scrollbar-track-color: #FFFFFF;    
                scrollbar-arrow-color: #aaaaaa;}
-->
</STYLE>
</HEAD>
<BODY onLoad="MAIN_FORM.keyword.focus()">
<FORM name="MAIN_FORM">
"가", "강"을 입력 해보세요.</BR>
<INPUT type="text" name="keyword" onkeydown="keywordKeyDown()" style:width=150px" autocomplete="off"><A href="javascript:alert('검색처리');">검색</A>
<DIV id="searchKeyword" style="width:250px;height:100px;visibility:hidden;background-color:#D1EED2;overflow=auto;font-size:12px" class="scroll_div">
</DIV>
</FORM>
</BODY>
</HTML>


소스에는 복잡한 내용은 거의 없다. 검색어 입력 Text의 Keydown 이벤트에 대한 처리 부분과 결과를 받아 화면에 나타내는 부분이 대부분이다. AJAX로 서버에 대한 요청은 다음과 같은 순서로 처리한다.

1.XMLHttpRequest 객체 생성
IE의 경우 new ActiveXObject('Microsoft.XMLHTTP');와 같이 생성하고 IE가 아닌 경우 new XMLHttpRequest(); 로 생성한다.

2. XMLHttpRequest open
open() 메소드에는 3개의 파라미터가 있는데 첫번째는 호출방법인 GET, POST 중에 하나가 온다.
필자의 경우 GET 방식보다는 POST 방식을 선호하기 때문에 대부분의 Request는 POST로 전송하는데 AJAX에서도 당연히 POST를 선호한다.
두번째 파라미터는 처리하는 서버의 URL 정보이다.
세번째 파라미터는 비동기/동기 방식에 대한 선택인데 true인 경우 비동기 방식으로 처리한다.
비동기 방식의 경우 Request를 전송한 다음 서버로부터 응답이 없더라도 브라우저는 계속해서 다른 처리를 할 수 있다.
사용자로부터 입력을 받거나 다른 스크립트를 수행할 수도 있다.
반면 동기방식은 요청후 서버로부터 결과를 받을때까지 다른 처리는 할 수 없도록 하는 방식이다.
검색 입력 필드의 예제에서와 같은 경우는 비동기 방식으로 처리하는 것이 보통이지만 데이터의 수정, 삭제, 입력에 대한 처리의 경우에는 처리가 완료되었다는 서버로부터의 응답을 받은 후 다른 액션을 할 수 있도록 하는 것이 좋다.

3.request의 content type 설정
GET 방식인 경우 설정할 필요가 없지만 POST 방식인 경우에는 content type을 다음과 같이 설정한다.
 
xmlHttpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

4.서버로부터 처리결과 전송 후 수행해야 하는 기능에 대한 정의
XMLHttpRequest의 onreadystatechange 속성은 서버로부터의 처리 결과에 대한 상태코드가 변경되었을 때 수행해야 하는 스크립트 function을 지정한다.
여기서는 anonymous function을 사용하여 직접 정의 햐였다.
  
   xmlHttpRequest.onreadystatechange = function() {
     if(xmlHttpRequest.readyState == 4)
     {
        //서버로부터 받은 상태코드 및 데이터를 이용하여 처리로직 구현
     }
   }
  
서버로부터 받은 결과는 XMLHttpRequest의 responseText 속성에 저장되어 있으며 이것은 HttpServletResponse에 의해 전송된 문자열일수도 있고 웹서비스로 Request를 전송한 경우라면 SOAP 프로토콜로 전송된 XML 형식의 데이터일 것이다.
문자열인 경우 여기서의 예제와 같이 처리할 수 있지만 SOAP 프로토콜로 전송된 XML 데이터인 경우 각각의 브라우저에서 제공하는
XML 또는 SOAP을 지원한 객체를 이용하여 쉽게 핸들링할 수 있을 것이다.

5. 4번까지의 작업으로 Request가 전송되지 않는다. 전송을 위한 준비 작업과 처리결과 수신시 처리방법에 대한 정의만 하였을 뿐이다.
  실제 Request를 전송하기 위해서는 send()를 호출하여 전송한다.
  send()의 파라미터는 전송되는 Request의 파라미터 값이다. 물론 여기서도 일반적인 Request와 같이 '&', '=' 으로 구성된 문자열(예: keyword=test&page=2 )을 만들어서 전송하지만, XML 형태로 만들어서 전송하는 것도 가능하다
 
  xmlHttpRequest.send(submitParameter);            

searchKeyword.jsp
<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="java.util.*" %>
<%
    HashMap keywordData = new HashMap();
    keywordData.put("가", "강타|강일|가을소나타|강주희|강은비|강력3반|강동원|가격비교|가방|강수지");
    keywordData.put("강", "강타|강일|강주희|강은비|강력3반|강동원|가방|강수지");
   
    request.setCharacterEncoding("UTF-8");

    String keyword = request.getParameter("keyword");
    //여기에서 데이터베이스로부터 해당 keyword로 시작하는 단어 검색
    //예제에서는 간단하게 하기 위해 Hash에서 가져오는 것으로 처리
    String result = (String)keywordData.get(keyword);
    if(result == null)      result = "키워드 없음";
   
    out.print(keyword + " 키워드 목록|" + result);
%>
  

AJAX의 Request에 대해 서버에서의 처리는 위의 소스에서 보는 것과 같이 비즈니스 기능에 대한 처리(여기서는 데이터조회)에 대해서는 기존과 동일하지만 처리결과를 브라우저로 전송할때 HTML 형태가 아닌 순수한 데이터형태만 제공하여 클라이언트에서 처리하도록 한다.
여기서는 데이터의 구분자를 '|' 문자로 구분하도록 처리하였다.
  
AJAX의 경우 JavaScript로 처리되기 때문에 인코딩에 대한 처리를 모두 UTF-8로 처리한다.
따라서 서버에서 Request를 받아 처리할 때에는 처리할 때에서 반드시 UTF-8로 디코딩하여 처리하여야 한다.
예제의 경우 searchKeyword.jsp에서 다음과 같이 request에 대해 처리하고 있다.

request.setCharacterEncoding("UTF-8");

지금까지 AJAX를 이용하여 간단한 기능을 구현함으로써 AJAX에 대해서 살펴보았다.
현재 AJAX의 위치는 위의 예제와 같이 애플리케이션의 특정 부분에 대해서만 주로 사용되어지고 있다.
앤터프라이즈 애플리케이션에서 전체를 AJAX 기반으로 구현하기에는 아직까지 경험과 사례가 많이 부족하고 AJAX가 Rich Client의 주류로 자리 잡을 것인지에 대해서는 아직까지는 미지수이다.

단점 : 복잡한 HTML에 대한 생성을 자바 스크립트와 같은 스크립트 언어로 처리 (View에 대한 처리가 기존의 Servlet에서 처럼 복잡하게 구현됨. 현재는 JSP 또는 Struts의 taglib를 이용하여 쉽게 처리하고 있지만 이것이 어렵다.)


연구해야할 사항 : 이런 단점을 극복할 수 있는 스크립트 처리에 대한 표준 마련 및 솔루션 echo2와 같이 이미 나와 있지만 좀 더 많은 연구 및 레퍼런스의 확보가 필요하다고 할 수 있다.
그리고 지금까지의 아키텍처는 프리젠테이션 - 컨트롤 - 비즈니스 - 데이터와 같은 형태의 레이어 구조만 있었지만 이제는 프리젠테이션 계층을 좀 더 세분화하여 프리젠테이션 내부에서의 View(Dynamic 화면 구성), 컨트롤(요청 및 응답에 대한 제어), 데이터(서버로부터 받은 또는 서버로 전송할)와 같은 세부적인 아키텍쳐에 대한 연구도 필요할 것 같다.



테스트 페이지 : ajax_search.html

소스다운로드 : source.zip

레퍼런스
http://www.onlamp.com/pub/a/onlamp/2005/05/19/xmlhttprequest.html
http://developer.apple.com/internet/webcontent/xmlhttpreq.html
http://www.onlamp.com/pub/a/onlamp/2005/05/19/xmlhttprequest.html
http://www.state26.com/download/formdata2querystring.txt
http://jania.pe.kr/wiki/jwiki/moin.cgi/JavaScriptTips


출처 : http://tong.nate.com/heart2heart/13019477 

Posted by [czar]
,

/**
 * 또다시 업무로 인해 찾아봐야 했던 FTP 클라이언트 프로그램.

 * 결국엔 하나하나 들어내서 조립을 해야 했지만.....

 * 머.. 이런걸 하다보면 내공이란 게 점점 쌓여가는 거겠지.

 * 자바 자체의 라이브러리만이 아닌 첨부한 라이브러리를 사용했습니다.

 * WEB-INF/lib 폴더에 복사 후 클래스패스를 잡아서 사용할 것.
 */
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import com.oroinc.net.ftp.FTPClient;
import com.oroinc.net.ftp.FTPFile;
import com.oroinc.net.ftp.FTPReply;

 

 

public class MyFtpClient {
 
 private static final String sServer = "XXX.XXX.XXX.XXX"; //서버 아이피
 private static final int iPort = 21;
 private static final String sId = "XXXXX"; //사용자 아이디
 private static final String sPassword = "XXXXX"; //비밀번호

 private static final String sUpDir = "D:/laredoute_dev/FTP/upload";
 private static final String sDownDir = "D:/laredoute_dev/FTP/download";
 private static final String sLogDir = "D:/laredoute_dev/FTP/log";
 
 
 public Log log = LogFactory.getLog(getClass());

 FTPClient ftpClient;

 public MyFtpClient() {
  ftpClient = new FTPClient();
  log.debug(sLogDir);
 }
  
  
 // 서버로 연결
 private void connect() {

  try {
    ftpClient.connect(sServer, iPort);
    int reply;
    // 연결 시도후, 성공했는지 응답 코드 확인
    reply = ftpClient.getReplyCode();
   
    if(!FTPReply.isPositiveCompletion(reply)) {
     ftpClient.disconnect();
     log.debug("서버로부터 연결을 거부당했습니다");
    }
   
  }catch (IOException ioe) {
    if(ftpClient.isConnected()) {
     try {
       ftpClient.disconnect();
     } catch(IOException f) {
      //
     }
    }
    log.debug("서버에 연결할 수 없습니다");
  }
 }
  
 // 계정과 패스워드로 로그인
 private boolean login() {
 
  try {
    this.connect();
    return ftpClient.login(sId, sPassword);
  }catch (IOException ioe) {
    log.debug("서버에 로그인 하지 못했습니다");
  }
  return false;
 }
  
 // 서버로부터 로그아웃
 private boolean logout() {

  try {
    return ftpClient.logout();
  }catch (IOException ioe) {
    log.debug("로그아웃이 하지 못했습니다");
  }
  return false;
 }
  
 // FTP의 ls 명령, 모든 파일 리스트를 가져온다
 private FTPFile[] list() {

  FTPFile[] files = null;
  try {
    files = this.ftpClient.listFiles();
    return files;
  }catch (IOException ioe) {
    log.debug("서버로부터 파일 리스트를 가져오지 못했습니다");
  }
  return null;
 }

 // 파일을 전송 받는다
 private boolean get(String source, String target, String name) {
 
  boolean flag = false;
 
  OutputStream output = null;
  try {
   // 받는 파일 생성 이 위치에 이 이름으로 파일 생성된다
    File local = new File(sDownDir, name);
    output = new FileOutputStream(local);
  }catch (FileNotFoundException fnfe) {
    log.debug("다운로드할 디렉토리가 없습니다");
    return flag;
  }
 
  File file = new File(source);
  try {
    if (ftpClient.retrieveFile(source, output)) {
     flag = true;
    }
  }catch (IOException ioe) {
    log.debug("파일을 다운로드 하지 못했습니다");
  }
  return flag;
 }

 // 파일을 전송 받는다 위의 method 와 return 값이 달라서 하나 더 만들었다
 private File getFile(String source, String name) {
 
  OutputStream output = null;
  File local = null;
  try {
   // 받는 파일 생성
    local = new File(sDownDir, name);
    output = new FileOutputStream(local);
  }catch (FileNotFoundException fnfe) {
    log.debug("다운로드할 디렉토리가 없습니다");
  }
 
  File file = new File(source);
  try {
    if (ftpClient.retrieveFile(source, output)) {
     //
    }
  }catch (IOException ioe) {
    log.debug("파일을 다운로드 하지 못했습니다");
  }
  return local;
 }

 // 파일을 전송 한다
 private boolean put(String fileName, String targetName) {

  boolean flag = false;
  InputStream input = null;
  File local = null;

  try {
    local = new File(sUpDir, fileName);
    input = new FileInputStream(local);
  }catch(FileNotFoundException e) {
    return flag;
  }

  try {

   // targetName 으로 파일이 올라간다

   if(ftpClient.storeFile(targetName, input)) {
    flag = true;
   }
  }catch(IOException e) {
    log.debug("파일을 전송하지 못했습니다");
    return flag;
  }
  return flag;
  
 }

 // 서버 디렉토리 이동
 private void cd(String path) {
   
  try {
    ftpClient.changeWorkingDirectory(path);
  }catch (IOException ioe) {
    log.debug("폴더를 이동하지 못했습니다");
  }
 }

 // 서버로부터 연결을 닫는다
 private void disconnect() {
   
  try {
    ftpClient.disconnect();
  }catch (IOException ioe) {
    ioe.printStackTrace();
  }
 }
  
 private void setFileType(int iFileType) {
  try {
   ftpClient.setFileType(iFileType);
  }catch(Exception e) {
   log.debug("파일 타입을 설정하지 못했습니다");
  }     
 }

}

Posted by [czar]
,

익스플로러7로 업데이트 한 후에 블로그에 글을 올릴때마다


'이 웹 페이지에서 클립보드에 엑세스 할 수 있도록 허용하시겠습니까?'


이런 종류의 메시지가 자동으로 뜨더군요. 메시지 창에서 허용을 선택해도 뜨고,

허용을 선택하지 않아도 또 뜨게 됩니다.


이 해결방법은, 익스플로러7 설치후 기본설정이 되어있다는 가정하에,

익스플로러 상단 우측을 보시면 도구 라는 메뉴가 있습니다.


이 도구 메뉴를 클릭하신 후 맨 아래쪽의 인터넷 옵션 을 선택하시면

인터넷 옵션 창이 별도록 활성화 되게 됩니다.

그 창에서 두번째 탭인 보안을 클릭하신뒤 창 아래쪽의 사용자 지정 수준을 다시

클릭하시면 보안설정-인터넷영역 이라는 창이 또 뜨게 됩니다.


여기서 우측의 스크롤바를 중간이하로 내려 스크립팅 명령을 찾으시면

스크립팅 명령의 하위 세번째 명령줄에 프로그램 클립보드 액세스 허용 이라는

명령이 있고, 이 명령에 대해서 확인에 체크가 되어있을 겁니다.

이걸 사용으로 체크를 하시면 완료가 됩니다.


풀어서 쓰다보니 길어졌는데, 간략하게 정리하면 아래와 같은 순서입니다.



도구 → 인터넷 옵션 → 보안 → 사용자 지정 수준 → 스크립팅

→ 프로그램 클립보드 액세스 허용 → 사용


::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


클립보드 복사 기능 스크립트 - 플래시 이용

미리보기 : http://oxtag.com/html/ex/clipboard/

출처 : http://www.alik.info


function copyContent(str)
{
    if (document.selection)
    {
        bResult = window.clipboardData.setData("Text",str);
        if (bResult) alert('클립보드에 저장되었습니다.');
    } else {
        str = encodeforFlash(str);
        var flashcopier = 'flashcopier';
        if(!document.getElementById(flashcopier)) {
            var divholder = document.createElement('div');
            divholder.id = flashcopier;
            document.body.appendChild(divholder);
        }
        document.getElementById(flashcopier).innerHTML = '';
        var divinfo = '<embed src="_clipboard.swf" FlashVars="clipboard='+str+'" width="1" height="1" type="application/x-shockwave-flash"></embed>';
        document.getElementById(flashcopier).innerHTML = divinfo;
        alert('클립보드에 저장되었습니다.');
    }
};


function encodeforFlash(str)
{
    var SAFECHARS = "0123456789" +
                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
                  "abcdefghijklmnopqrstuvwxyz" +
                  "-_.!~*'()";

    var HEX = "0123456789ABCDEF";

    var plaintext = str;
    var encoded = "";
    for (var i = 0; i < plaintext.length; i++ ) {
        var ch = plaintext.charAt(i);
        if (ch == " ") {
            encoded += "+";
        } else if (SAFECHARS.indexOf(ch) != -1) {
            encoded += ch;
        } else {
            var charCode = ch.charCodeAt(0);
            if (charCode > 255) {
                encoded += ch;
            } else {
                encoded += "%";
                encoded += HEX.charAt((charCode >> 4) & 0xF);
                encoded += HEX.charAt(charCode & 0xF);
            }
        }
    }
    return encoded;
};


사용법은

    copyContent('복사할내용');

이런식으로 복사될 내용을 넘겨주면서 호출해주면 되는겁니다.
(onclick 이나... 링크나...함수내 호출이나...아무렇게나!)



::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

첫번째 링크는 위 "...클립보드에 엑세스 할 수 있도록 허용..." 메시지가 나오구요.
두번째,세번째 링크는 위 메시지가 나오지 않습니다.

   http://oxtag.com/html/ex/clipboard

   http://oxtag.com/html/ex/clipboard/clipboard2/

   http://oxtag.com/html/ex/clipboard/clipboard3/

Posted by [czar]
,
사용자 삽입 이미지

아이핀은 처음듣는 분들이 많을 것이다. 아이핀(iPIN)이란 Internet Personal Identification Number로서 정부에서 추진하는 주민등록번호 대체 인증방식이다.

아이핀 발급기관

우리가 흔히 웹사이트에 가입하거나 결제를 할때 대부분의 사이트는 본인 확인을 위해 주민번호를 요구한다. 하지만 주민번호 도용이 있을 경우 내 명의의 회원가입이나 범죄가 저질러질 우려가 있다. 그래서 번호 자체로는 누군지 알 수는 없지만 인증의 수단이 될 수 있는 대체수단이 아이핀이다. 이 사업은 정보통신부와 한국정보보호진흥원(http://www.kisa.or.kr)에서 주관이 되어 개발을 했고, 5군데의 기관에서 아이핀을 발행한다.

이러한 아이핀에 여러 문제점이 발견됬다. 바로 아이핀을 사용할경우, 본인 확인을 넘어 개인의 금융기관 정보까지 제공하게 되는 문제가 생기고, 결국엔 타인 명의를 이용해 아이핀을 생성할 경우 본인조차 그 아이핀을 취소하고 다시 생성하기가 까다롭다는 문제가 발견됬다. 또한 지난해 6월부터 시행된 본 제도가 아직까지 대형 사이트 중 정부 사이트를 제외하고는 운영되는 데가 거의 없다는 점이다. 주민등록번호가 공개되지 않아서 안전하게 사용될 것 같았던 아이핀이 오히려 또다른 개인 정보 침해의 우려를 낳고 있는 것이다
Posted by [czar]
,