2. 필요한 파일을 UPLOAD.
TISTORY 관리자 페이지에 로긴해서, [ 스킨 ] / [ HTML/CSS편집 ] / [ 파일 업로드 ] 화면에서
필요한 파일을 모두 올린다.
필요한 파일은 압축푼 파일 중에 styles, scripts 디렉토리 밑에 있는 모든 파일이다.
올려진 파일을들 보면, images 디렉토리 밑으로 올라간 것을 알 수 있다.
3. TISTORY 스킨 파일 편집.
[ 스킨 ] / [ HTML/CSS편집 ] / [ HTML/CSS 편집 ] 화면에서 skin.html 파일에 내용을 편집한다.
밑줄에 아래의 내용을 추가한다.
위 내용 처럼 압축을 풀었을때 경로가 아닌, 파일이 올라간 images로 경로를 바꾸어야 한다.
두번째 "shThemeEmacs.css" 파일은 보여줄 테마를 지정한 것이다.
테마 css 파일을 이것저것 지정해보고 마음에 드는 것으로 결정하면 된다.
(사실 맘에 쏙 드는 것이 없었는데. Emacs 테마가 가장 나은 것 같다.)
동일한 방법으로 skin.html 파일 가장 하단 </body> 위쪽에 아래와 내용을 넣어 준다.
여기서 필요한 코드는 맨 밑줄 함수 실행부 이고, 그외 설정 부분이다.
stripBrs를 true로 설정하면, TISTORY 에서 자동으로 <br> 태그를 붙이는 걸 무시 할 수 있다.
4. TISTORY에서 글쓰기.
글을 쓸때에는 소스 코드가 들어갈때는 html 모드에서 글을 써야한다.
위와 같이 html 체크박스를 체크하면, html 모드에서 글을 입력할 수 있다.
소스 코드를 넣을때 아래와 같은 문법으로 넣는다.
<pre class="brush: sql">
CREATE TABLE CVS_COMMIT
(
SEQ NUMBER(10) NOT NULL,
USERID VARCHAR2(20) NOT NULL,
REG_DATE DATE DEFAULT SYSDATE,
PROJECT VARCHAR2(50) NOT NULL,
FILENAME VARCHAR2(500) NOT NULL
);
</pre>
소스의 내용은 <pre></pre> 태그 사이에 넣어주고, class의 brush 속성에 원하는 문법을 지정한다.
지정 가능한 문법은 아래와 같다.
ActionScript3
as3, actionscript3
shBrushAS3.js
Bash/shell
bash, shell
shBrushBash.js
ColdFusion
cf, coldfusion
shBrushColdFusion.js
C#
c-sharp, csharp
shBrushCSharp.js
C++
cpp, c
shBrushCpp.js
CSS
css
shBrushCss.js
Delphi
delphi, pas, pascal
shBrushDelphi.js
Diff
diff, patch
shBrushDiff.js
Erlang
erl, erlang
shBrushErlang.js
Groovy
groovy
shBrushGroovy.js
JavaScript
js, jscript, javascript
shBrushJScript.js
Java
java
shBrushJava.js
JavaFX
jfx, javafx
shBrushJavaFX.js
Perl
perl, pl
shBrushPerl.js
PHP
php
shBrushPhp.js
Plain Text
plain, text
shBrushPlain.js
PowerShell
ps, powershell
shBrushPowerShell.js
Python
py, python
shBrushPython.js
Ruby
rails, ror, ruby
shBrushRuby.js
Scala
scala
shBrushScala.js
SQL
sql
shBrushSql.js
Visual Basic
vb, vbnet
shBrushVb.js
XML
xml, xhtml, xslt, html, xhtml
shBrushXml.js
첫번째 컬럼이 문법, 두번째 컬럼이 brush에 지정할 속성 상수,
세번째 컬럼이 필요한 Javascript 파일로써 TISTORY에 UPLOAD되어 있어야 한다.
문법 뿐 아니라 추가 속성을 지정할 수 있는데, 아래와 같이 ";" (세미콜론) 로 구분한다.
php, asp, jsp 등과 같이 소스 코드안에 html이 포함되는 경우
html도 하이라이팅하고 싶으면 사용한다
smart-tabs
true
스마트탭 기능의 활성화 여부를 지정한다
(무슨 기능인지 잘 모르겠다)
tab-size
4
TAB 크기를 지정한다.
toolbar
true
툴바를 켜거나 끌 수 있다.
이제 TISTORY에서 깔끔한 코드를 볼 수 있다.
<주의 사항>
-. SyntaxHighlighter 3.0.83 버전에 버그가 하나 있다.
일부 코드에 대해 Line Number가 어긋나 보이는 경우가 있다.
한 Line 에 긴 코드가 포함된 경우 wrapped(자동줄바꿈) 처리를 하면서 잘못 처리하는 것 같다.
소스 코드를 무조건 올리지 말고, 적당히 줄바꿈 처리를 해주고 올리는 것이 좋다.
-. html모드에서 <pre></pre> 태그를 사용할 경우 소스 코드에 포함된 "<", ">"의 파싱을 잘못하는
경우가 발생하는 것 같다.
소스 코드를 올리기 전에 "<"를 "<"로, ">"를 ">"로 변환 해서 올리는 것이 좋다.
적용 패키지 작성을 위해 수정된 파일 목록을 추출 할 방법을 찾아 보기로 했다.
업무 때문에 소스 관리를 CVS 로 하고 있다. CVS의 단점은 개별 파일이력은 확인 할 수 있는데,
수정된 파일 목록을 뽑기가 쉽지 않다는 것이다.
구글링을 해보니 CVS에서 Commit 시점에 뭔가 처리할 수 있다는 것을 알았다.
먼저, CVS 서버에 접속해서 저장소의 CVSROOT 디렉토리를 보자
-rwxrwxr-- 1 cvs cvs 544 4월 22 09:23 checkoutlist
-rwxrwxr-- 1 cvs cvs 694 3월 21 2009 checkoutlist,v
-rwxrwxr-- 1 cvs cvs 882 4월 26 16:03 commitinfo
-rwxrwxr-- 1 cvs cvs 959 3월 21 2009 commitinfo,v
-rwxrwxr-- 1 cvs cvs 993 3월 21 2009 config
-rwxrwxr-- 1 cvs cvs 1192 3월 21 2009 config,v
-rwxrwxr-- 1 cvs cvs 602 2월 8 16:32 cvswrappers
-rwxrwxr-- 1 cvs cvs 801 3월 21 2009 cvswrappers,v
-rwxrwxr-- 1 cvs cvs 1025 3월 21 2009 editinfo
-rwxrwxr-- 1 cvs cvs 1224 3월 21 2009 editinfo,v
-rwxrwxr-- 1 cvs cvs 292081967 4월 29 18:14 history
-rwxrwxr-- 1 cvs cvs 1245 4월 21 11:32 loginfo
-rwxrwxr-- 1 cvs cvs 1367 3월 21 2009 loginfo,v
-rwxrwxr-- 1 cvs cvs 1151 3월 21 2009 modules
-rwxrwxr-- 1 cvs cvs 1350 3월 21 2009 modules,v
-rwxrwxr-- 1 cvs cvs 564 3월 21 2009 notify
-rwxrwxr-- 1 cvs cvs 763 3월 21 2009 notify,v
-rwxrwxr-- 1 cvs cvs 640 4월 25 12:43 passwd
-rwxrwxr-- 1 cvs cvs 649 3월 21 2009 rcsinfo
-rwxrwxr-- 1 cvs cvs 848 3월 21 2009 rcsinfo,v
-rwxrwxr-- 1 cvs cvs 879 3월 21 2009 taginfo
-rwxrwxr-- 1 cvs cvs 1078 3월 21 2009 taginfo,v
-rwxrwxrw- 1 cvs cvs 187 11월 10 17:15 val-tags
-rwxrwxr-- 1 cvs cvs 1026 3월 21 2009 verifymsg
-rwxrwxr-- 1 cvs cvs 1225 3월 21 2009 verifymsg,v
위와 같은 파일들을 볼 수 있는데..
여기서 commitinfo 란 파일이 CVS에서 Commit 하기 바로전에 실행되는 파일이다.
방향은 정해졌다.
작업 구성은 아래와 같은 순서로 하기로 했다.
1. CVS가 Commit 되는 시점에 파일명을 DB에 저장한다.
-> CVSROOT/commitinfo에 등록할 쉘 스크립트를 작성. 2. 저장된 DB를 조회할 간단한 WEB Page 제작
-> 평소 관심을 갖고 있던, jQuery를 이용.
[ 1. CVS가 Commit 되는 시점에 파일명을 DB에 저장한다 ]
commitinfo 파일에 아래와 같이 내용을 추가 한다.
$ vi CVSROOT/commitinfo
ALL /home/cvs/myproject/CVSROOT/cvscommitlog.sh
DB에 테이블을 생성 한다.
CREATE TABLE CVS_COMMIT
(
SEQ NUMBER(10) NOT NULL,
USERID VARCHAR2(20) NOT NULL,
REG_DATE DATE DEFAULT SYSDATE,
PROJECT VARCHAR2(50) NOT NULL,
FILENAME VARCHAR2(500) NOT NULL
);
* index는 REG_DATE, TO_CHAR(reg_date, 'YYYY/MM/DDHH24:MI'), USERID, PROJECT 를 걸었다.
jQuery에 관심이 생기면서, javascript 만으로 RSS 리더기를 만들어 보기로 했다.
jQuery가 워낙에 많은 Plugin들을 지원하고 있어서, rss Parser도 금방 찾을 수 있었다. jFeed 라는 것인데, 소스도 간단하고.. 복잡한 기능이 필요없는 용도로는 적당했다.
그런데, 예상치도 못한 문제가 있었다.
Ajax에서 다른 도메인의 페이지를 읽기 위해 proxy를 구현 해야 하는데..
셈플 소스에 포함된 것이 정상적으로 동작하지 않는 것이다.
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script>
function roundTable(objID) {
var $obj = $("table#" + objID);
var s, r;
var y, x, MAX;
var w, h;
r = parseInt($obj.attr('radius'));
if (r == null || r < 1) r = 1;
else if (r > 6) r = 6;
MAX = r * 2 + 1;
$obj.before("<TABLE id='tmpRoundTbl'></TABLE>")
$("table#tmpRoundTbl")
.attr("cellSpacing", 0)
.attr("cellPadding", 0)
.append("<TBODY></TBODY>");
for (y=0; y < MAX; y++) {
$("table#tmpRoundTbl TBODY").append("<TR></TR");
s = Math.abs(y - parseInt(r));
for (x=0; x < MAX; x++) {
$("table#tmpRoundTbl TBODY TR:eq("+y+")")
.append("<TD></TD>");
w = '1px'; h = '1px';
if (x == 0 || x == MAX - 1) h = null;
else if (y == 0 || y == MAX - 1) w = null;
else if (r > 2) {
if (Math.abs(x - r) == 1) w = '2px';
if (Math.abs(y - r) == 1) h = '2px';
}
if (w != null)
$("table#tmpRoundTbl TBODY TR:eq("+y+") TD:eq("+x+")")
.css("width", w);
if (h != null)
$("table#tmpRoundTbl TBODY TR:eq("+y+") TD:eq("+x+")")
.css("height", h);
if (s == x || s == MAX - x - 1)
$("table#tmpRoundTbl TBODY TR:eq("+y+") TD:eq("+x+")")
.css("backgroundColor", $obj.attr('rborder') );
else if (x > s && s < MAX - x - 1)
$("table#tmpRoundTbl TBODY TR:eq("+y+") TD:eq("+x+")")
.css("backgroundColor", $obj.attr('rbgcolor') );
}
}
$("table#tmpRoundTbl TBODY TR:eq("+s+") TD:eq("+r+")").append( $obj );
}
</script>
<table id="ta" width="300" height="100" border="0"
radius="3" rborder="#999999" rbgcolor="#F8F8F8">
<tbody><tr>
<td valign="top">테스트입니다</td>
</tr>
</tbody></table>
<span>
<script>roundTable("ta");</script>
</span>
Proc*c를 이용해 Sub Program(Procedure or Function)을 호출 하는 방법에 대해 설명한다.
자료를 되져보면 대부분의 샘플 코드가 Procedure 로만 되어 있다.
여기서는 Function을 호출 해 보기로 한다.
사실 호출 방법은 거의 비슷 하다.
- 컴파일 방법
PL/SQL 구문을 사용하기 때문에 proc 컴파일 옵션을 주어야 한다.
그런데, 컴파일 옵션을 주면 다른 Pro*c 구문에서 컴파일이 안되는 일이 발생을 한다.
따라서, PL/SQL 구문을 사용하는 소스는 별도 .pc 파일로 때어 내어서 별도 컴파일을 해야한다.
여기서 [Enable Dynamic SOCKS Port] 설정을 꼭 해주어야 한다. 설정을 마치고, 접속 한 후 [ Hide ] 버튼을 누르면 TrayBox로 보낼 수 있다.
3. WEB 설정 Internet Explorer의 경우 [도구] / [인터넷 옵션] / [연결] / [LAN 설정] 화면을 열어 [프록시 서버] 항목을 체크하고, 활성화된 [고급] 버튼을 누르면 프록시 설정을 할 수 있다. 여기서 Socks 항목의 서버 주소를 "localhost"로, 포트를 MyEntunnel에서 지정한 "7070" 포트로 설정 한다.
4. NATEON 설정 [설정] / [연결(방화벽)] 메뉴에서 [프록시 서버 사용]을 체크하고 아래와 같이 설정한다. 종류: SOCKS 버전 4 서버: localhost 포트: 7070
이렇게만 해주면 해당 네트웍의 방화벽 설정에 상관없이 웹서핑과 메신져 활동을 누릴 수 있다.
이 방법은 장점은 또 있다. ssh 프로토콜을 이용해 암호화 되어 패킷이 전송되기 때문에 패킷 감시를 할 수 없다는 점이다.
DB Link로 Remote 테이블을 참조 하고 있는 프로세스가 작업을 수행하고 있는 상태에서,
Remote DB가 Shotdown 되는 경우 위 에러가 발생 한다.
Remote DB가 Start되고 새로운 세션을 맺어야 프로세스가 정상 동작을 한다.
세션을 유지한 상태에서 Remote DB가 Start 되어도 위 에러가 계속 발생한다.
말이 어렵다 테스트 해보자.
1. ORA TNS에 RemoteDB를 추가한다.
2. DB 링크를 생성한다.
CREATE PUBLIC DATABASE LINK test_link CONNECT TO remoteDBid IDENTIFIED BY remoteDBpwd USING 'remoteDB';
CREATE SYNONYM test_proc FOR test_proc_table@test_link
SELECT * FROM test_proc
3. 데이터를 삽입한다.
insert into test_proc values ( 1, 1 );
insert into test_proc values ( 2, 1 );
~~~~~~
insert into test_proc values ( 33, 1 );
insert into test_proc values ( 44, 1 );
4. 테스트 프로그램을 작성한다.
$ vi t.pc
#include <stdio.h>
EXEC SQL INCLUDE SQLCA;
#define MAX_ARRAY_SIZE 10
int main()
{
int n;
EXEC SQL BEGIN DECLARE SECTION;
int hSEQ;
char hOracleUser[20] = "localDBid";
char hOraclePwd[20] = "localDBpwd";
EXEC SQL END DECLARE SECTION;
EXEC SQL CONNECT :hOracleUser IDENTIFIED BY :hOraclePwd;
if(sqlca.sqlcode !=0)
{
printf( "login fail\n");
return 0;
}
for (n=0; n<10; n++)
{
printf( "start of job\n");
EXEC SQL DECLARE CUR_TEST_PROC CURSOR FOR
SELECT SEQ FROM TEST_PROC;
EXEC SQL OPEN CUR_TEST_PROC;
while(1)
{
EXEC SQL FETCH CUR_TEST_PROC INTO :hSEQ;
sleep(3);
if(sqlca.sqlcode != 0)
{
if(sqlca.sqlcode == 1403)
{
printf( "data not found\n");
break;
}
else
{
printf( "fetch Error [%20s]\n" , sqlca.sqlerrm.sqlerrmc);
break;
}
}
printf("fetch [%d]\n", hSEQ );
}
EXEC SQL CLOSE CUR_TEST_PROC;
printf( "end of job\n");
} /* for */
return 0;
}
$ proc iname=t.pc
$ cc -o t t.c -L/home/oracle/app/oracle/product/8.1.7/lib -lclntsh -R/home/oracle/app/oracle/product/8.1.7/lib
먼저, Visual Studio 2008 RTM 설치를 시도했다.
일단, iso를 zip+ v6.99 로 풀었다.
zip+ 는 데몬이나 알콜을 설치하지 않아도 간단하게 가상 CD를 잡을 수 있어서 애용 중이다.
그런데, 이상하게도 Visual Studio 2008 RTM 버전은 가상 CD로 잡히지를 않는다.
iso를 직접 풀어서 설치를 하니,
"baseline 데이터를 찾을 수 없습니다"라는 오류가 발생하면서 설치가 되지 않는다.
여러 가지 방법으로 시도를 해보았지만, 결국 포기..
하지만, 마음속에 불길은 벌써 걷잡을 수 없이 번져 버렸다.
불길을 잡기 위해서는, Visual Studio 2008 설치 뿐!
Visual Studio 2008 평가판을 다운 받았다.
젠장, 용량이 크다고 파일이 7개로 나눠 져있다.
rar로 묶어서 exe로 만들어 놓은 배포본 이다.
전부 받아 압축을 풀어보니 또 iso 파일..
왠지 불안하다..
역시, 가상 CD로는 잡히지 않고...
iso를 풀어 설치를 시도 했지만.. 역시 설치 실패..
이번엔 무슨 파일이 존재하지 않는단다.
엇, 그런데!!
iso 파일 용량은 4기가 넘는데, 풀어 놓은 전체 용량이 더 작은 것이 아닌가!!
혹시 zip+에서 iso 파일을 제대로 지원하지 않는 것일까??
이제까진 이런 경우가 없었는데... 워낙 용량이 크다보니 그럴수도 있겠다는 생각이 들었다.
하드를 뒤져보니, WinRAR 3.4 버전이 있다.
이걸로 풀어서 설치를 해보니, 역시 설치가 제대로 되질 않는다.
이번엔 무슨 파일이 손상되었단다..
웹을 뒤져보니, 영문 버전은 WinRAR 3.8까지, 한글 버전은 WinRAR 3.6까지 있는 듯 하다.
3.6 버전 평가판을 다운로드 받아 설치하고, iso 파일을 풀어서 설치하니..
설치가 잘된다!!
이렇게 Visual Studio 2008 RTM 버전을 무사히 설치했다 ㅡㅡ;
세줄 요약 1. Zip+ v6.99를 이용 Visual Studio 2008 설치 실패. 2. WinRAR 3.4를 이용한 Visual Studio 2008 설치 실패. 3. WinRAR 3.6를 이용한 Visual Studio 2008 설치 성공.
// 현재 fp 부터 검색한다. // 다음 key 값을 얻는다. void getNextKey(FILE *fp, char *retKey, int sizeKey, char *retValue, int sizeValue) { char str[MAX_LENGTH] =""; char buf[MAX_LENGTH] =""; char *p=0; int bingo;
// fp 파일에서 app 카테고리의 key 값을 읽는다. // ret는 들어갈 int형 주소 // return : -1 파라미터 에러 // -2 파일 핸들 에러 // -3 app 검색 실패 // -4 key 검색 실패 // 0 성공 int GetProfileInt(FILE *fp, char *app, char *key, int *ret) { char buf[MAX_LENGTH]=""; int n = 0;
// 파라미터 에러 if ( ret == 0 ) return -1;
n = GetProfileString( fp, app, key, buf, sizeof(buf) ); if ( n == 0 ) { (*ret) = atoi(buf); return 0; }
prototype을 이용해 비동기 방식의 요청을 여러건 해서 순서 상관없이 응답을 받아 처리하는 부분을 구현해 봤다.
원래 목적은 fund 정보를 웹에서 관리하기 위해 만들려 한것인데... 미완성 프로젝트다.. 엑셀에선 간단하던 수식들을 웹으로 옮기려니 만만치 않더라 ㅡㅡ;
소스에는 포함된 내용들은 아래와 같다. - Prototype Javascript Lib 사용 - Javascript Calendar Javascript Lib 사용(한국어 처리 부분 소스 약간 수정) - 멀티 Ajax 요청 처리 - 요청 처리중일때 모래 시계 보여주기 - Msg 출력을 동적으로 - select Object에 요청 받은 내용 동적으로 append
common.js 보기
common.js
// 결과를 보여줄 영역을 동적 생성 function getMsgElement() { var id = 'result'; var element = $(id);
// 처리중 모래시계를 element 앞에 삽입 function beginWaiting(element) { var elementImage; var next = element; var id = element.id + 'WaitingImage'; element = $(id);
if ( !element || Object.isUndefined(element) ) { element = document.createElement('IMG'); element.setAttribute('id', id); element.setAttribute('src', '../images/waiting.gif');
next.parentNode.insertBefore(element, next); } };
// 처리중 모래시계를 지운다. function endWaiting(element) { var parent = element.parentNode; var id = element.id + 'WaitingImage'; element = $(id);
if ( !element || Object.isUndefined(element) ) return;
parent.removeChild(element); };
// select에 OPTION 태그를 추가한다. function addOption(parent, value, text) { var element = document.createElement('OPTION'); element.value = value; element.text = text;
if ( !parent || Object.isUndefined(parent) ) return;
try { parent.add(element, null); // from standard } catch(ex) { parent.add(element); // from IE } }
var isTry = false; var cName = new FillOptions('./fund_list.php', 'name', 'seq'); var cScope = new FillOptions('./fund_list.php', 'scope', 'scope'); var cType = new FillOptions('./fund_list.php', 'type', 'type'); var cCompany = new FillOptions('./fund_list.php', 'company', 'company');
function beforeOption(oSel) { addOption(oSel, "All", "모두" ); }
function init() { cName.run(); cScope.run(); cType.run(); cCompany.run();