2010년 12월 10일 금요일

ASP Cint Int 반올림 문제

ASP Cint Int 반올림 문제
- Cint형의 경우 반올림시 가장 가까운 짝수를 반환한다..
0.5 -> 2, 1.5->2, 2.5->4, 3.5->4

참조: ♬ OK! Programming >> ASP - 변환 관련 함수 (Google 사이드위키에서 보기)

2010년 12월 9일 목요일

Table design

이쁘장한 테이블을 만들기 위한 CSS 를 모아 놓은 갤러리 입니다.

참조: Data Tables and Cascading Style Sheets Gallery (Google 사이드위키에서 보기)

MS-SQL 2005 Pivot Table

지랄금지 - ☆ 까만콩 :: MS-SQL 2005 Pivot Table:




mssql 2005 부터 지원 되는 pivot table 기능

동적 pivot도 설명이 되어 있네요..



DECLARE @Prod varchar(2000)
SET @Prod = ''
SELECT @Prod = @Prod + '[' + Product + '],'
FROM (SELECT Distinct Product FROM Orders) A


SET @Prod = LEFT(@Prod, LEN(@Prod) - 1)
EXEC ('SELECT * FROM Orders
PIVOT ( SUM(Quantity) FOR Product IN (' + @Prod + ')
) AS PVT')
GO

2010년 11월 30일 화요일

SQL Query - 전일과 금일 판매량의 합을 구하는 쿼리

SQL Query 중에 집합쿼리를 사용해서 해결하지 못하고

Cursor를 이용해서 구할수 밖에 없는 문제중 하나 ..

전체 영업 데이터중에서 하루 전판매량과 당일 판매량의 합을 구하는 Query 이다..



SqlServerMVP 53( SqlServerDeepDives) 책의 예제 chat4.4



USE AdventureWorks;
SET NOCOUNT ON;

DECLARE @Results TABLE
       (CustomerID int NOT NULL,
        OrderDate datetime NOT NULL,
        SalesOrderID int NOT NULL,
        TotalDue money NOT NULL,
        RunningTotal money NULL,
        Rnk int NOT NULL,
        PRIMARY KEY (Rnk, CustomerID));

INSERT INTO @Results(CustomerID, OrderDate, SalesOrderID, TotalDue,
                     RunningTotal, Rnk)
SELECT CustomerID, OrderDate, SalesOrderID, TotalDue, TotalDue,
       RANK() OVER (PARTITION BY CustomerID
                    ORDER BY     OrderDate,
                                 SalesOrderID)
FROM   Sales.SalesOrderHeader;

DECLARE @Rank int,
        @RowCount int;
SET     @Rank = 1;
SET     @RowCount = 1;

WHILE @RowCount > 0
BEGIN;
  SET @Rank = @Rank + 1;

  UPDATE     nxt
  SET        RunningTotal    = prv.RunningTotal + nxt.TotalDue
  FROM       @Results       AS nxt
  INNER JOIN @Results       AS prv
        ON   prv.CustomerID  = nxt.CustomerID
        AND  prv.Rnk         = @Rank- 1
  WHERE      nxt.Rnk         = @Rank;

  SET @RowCount = @@ROWCOUNT;
END;

SELECT   CustomerID, OrderDate, SalesOrderID, TotalDue, RunningTotal
FROM     @Results
ORDER BY CustomerID, OrderDate, SalesOrderID;

2010년 9월 6일 월요일

페이스북 페이지 팁(1) - 페이지가 효과적인 이유

페이스북 페이지 팁(1) - 페이지가 효과적인 이유: "

올해 초에 제 블로그를 통해 소개드렸던 주요 트렌드 중의 하나가 실시간 소셜웹(Real-time Social Web) 서비스인데, 국내에서 최근 들어 트위터에 이어 페이스북도 큰 사랑을 받고 있습니다.


특히 기업들이 고객과의 소통에 트위터와 페이스북 등 소셜미디어를 적극 활용할 움직임을 보이고 있는데, 기업의 브랜드나 상품 등을 효과적으로 운영할 수 있는 페이스북 페이지(Facebook Pages)에 대한 관심이 높아가고 있습니다.


기업들이 페이스북을 잘 활용할 수 있도록 오늘부터 제 블로그를 통해 페이스북 및 페이스북 페이지에 대한 내용을 중점적으로 소개할 예정인데.. 오늘은 첫 시간으로 페이스북 페이지를 만드는 방법에 대해서 살펴보도록 하겠습니다.



프로필 VS 페이지 VS 그룹


페이스북에 페이지를 만들기 위해서는 일단 페이스북에 회원가입을 해야 합니다.


회원가입이 완료되면 자신의 페이스북 프로필을 꾸밀 수가 있고, 페이스북 페이지도 만들 수 있습니다. 아래에서는 페이스북에서 제공하는 프로필, 그룹, 페이지에 대한 차이를 간단히 살펴보도록 하겠습니다.



  • 프로필(Profile) : 페이스북에 회원 가입하고 나면 자동으로 생기는 개인 프로필입니다.

  • 그룹(Group) : 관심사를 정해서 페이스북에 있는 회원들과 그룹을 만들 수 있습니다. 우리가 포털에서 자주 볼 수 있는 '카페' 기능과 비슷하다고 생각하시면 됩니다. 그룹은 공개/비공개/비밀그룹으로 나뉠 수가 있습니다.


  • 페이지(Page) : 특정 상품이나 브랜드, 유명인들이 자신만의 페이지를 만들 수가 있습니다. 기본적으로 공개하는걸 원칙으로 하며, 사람이나 제품, 관심사를 홍보하고 페이스북 친구들과 공유하는데 강점이 있습니다. 페이스북 페이지는 아래와 같이 두 가지로 구분됩니다.



    • 공식페이지(Official Page) : 이전에는 팬페이지(Fan Page)라고 했던 것으로, 회사나 브랜드/상품/단체 또는 예술가,밴드 등 유명한 사람이 자신의 페이지를 만들 수가 있습니다. 이전에는 팬되기(become a fan)을 통해 해당 페이지의 팬이 될 수 있었는데.. 페이스북이 그라프 API와 소셜 플러그인(Social Plugin)을 발표하면서 '좋아요(Like)' 기능으로 통합되었습니다.

    • 커뮤니티페이지(Community Page) : 회사나 브랜드, 사람 외에 특정 주제나 관심사에 대해서도 자신의 페이지를 만들어 홍보하거나 다른 사람들과 쉽게 공유할 수 있도록 만든 것이 바로 커뮤니티 페이지입니다. 예를 들어 제가 관심을 가지고 지켜보고 있는 실시간 소셜웹(Real-time Social Web)에 대해서는 커뮤니티 페이지 기능을 이용해서 만드는 것이 효과적입니다.





기업에게 페이지(Page)가 효과적인 이유


요즘 페이스북에 대한 관심이 높아지면서.. 트위터뿐만 아니라 페이스북을 이용해서 이용자들과 소통하려고 하는 회사나 서비스가 늘어나고 있습니다. 이 분들에게 페이스북 내에서 어떤 서비스를 이용해서 이용자들과 소통할 것인가가 중요한데.. 아래와 같은 이유로 페이스북 페이지를 적극 활용해야 합니다.




  • 페이스북 페이지는 공개 형태로 운영됩니다.

  • 페이스북 페이지는 프로필의 친구 맺기와 달리 좋아요(Like)를 통해 손쉬운 관계 맺기가 가능합니다. 페이스북 친구의 경우 친구신청-승인이라는 절차가 필요하지만.. 페이지의 경우 방문하신 분이 '좋아요(Like)'버튼을 누르면 페이지에 올린 글이 그 친구의 뉴스피드(News Feed)에 보이게 됩니다.

  • 페이스북 친구의 경우 현재 5,000명까지만 친구를 할 수가 있는데.. 페이지의 경우 '좋아요'를 눌러 해당 페이지의 팬이 되는 분에 대한 제한이 없습니다.

  • 프로필은 나 혼자 운영해야 하는데.. 페이지의 경우 내 말고도 여러 명의 운영자(Admin)을 지정해서 같이 운영할 수가 있습니다.

  • 페이지에서는 팬(좋아요한 친구)에게 쪽지를 보낼 수가 있습니다. 페이지에 글을 올리는 것은 공개할 수 있는 내용만 올리는데.. 팬에게 공개적으로 할 수 없는 비밀스런 이야기도 보낼 수가 있다는 것입니다. 또한 쪽지를 보낼 때 팬의 나이나 국가 등을 필터링해서 보낼 수 있는 기능도 제공합니다.

  • 페이지에서는 방문자나 좋아요(Like) 등에 대한 통계 기능을 제공하므로, 현재 페이지에 대한 상황을 정확하게 파악할 수가 있습니다.

  • 페이지에서는 다른 웹사이트에 자신의 페이지를 홍보할 수 있는 라이크 박스(Like Box)를 제공합니다.

  • 자신의 페이지를 광고로 제작해서 페이스북 내에서 홍보를 진행할 수가 있습니다.

  • 페이스북에서 제공하는 FBML을 이용하면 기본적으로 제공되는 기능 외에 자신만의 랜딩 탭(페이지에 왔을 때 제일 먼저 접속하는 탭)을 구현할 수가 있습니다. API로 공개되어 있기 때문에.. 이런 서비스를 전문적으로 제공하는 곳도 많아 골라 이용하시면 됩니다.



회사에서 제공하는 상품이나 서비스, 브랜드 등을 페이스북 친구들에게 효과적으로 홍보하고 의사소통을 하기 위해서는 페이스북 페이지가 효과적입니다. 다음 시간부터는 페이스북 페이지를 만들어 효과적으로 사용하는 방법에 대해서 차례대로 살펴보도록 하겠습니다.


이 글은 스프링노트에서 작성되었습니다.

"

2010년 8월 18일 수요일

Bitly Api 에서 사용하는 JSonP를 이용한 동적 웹서비스 구현

Bitly 에서 사용하는 JSonP를 이용한 동적 웹서비스 구현


BitlyApi.call = function(method, params, callback_method_name) {

var s = "http://api.bit.ly/" + method;

var url_args = [];

if (callback_method_name) url_args.push("callback=" + callback_method_name);

for (var name in params) {

url_args.push(name + "=" + encodeURIComponent(params[name]));

};

s += "?" + url_args.join("&");

BitlyApi.loadScript(s);

};

2010년 8월 10일 화요일

트위터에 글 올리기기 연동

트위터에 글 올리기 연동 ..


html

- a href="javascript:alert('넷마블, 넷마블이 재미있는 이유')"


Javascript

function goTwitter(msg,url) {


var href = "http://twitter.com/home?status=" + encodeURIComponent(msg) + " " + encodeURIComponent(url);

var a = window.open(href, 'twitter', '');

if ( a ) {

a.focus();

}

}


트위트 버튼 :  http://twitter.com/goodies/tweetbutton
 

2010년 8월 9일 월요일

SQL 2005 에서 페이징 처리법

SQL 2005 에서 페이징 처리법

간단하게 잘 되었네요..

-- @CurrentPageIndex : 현재페이지번호 (1번부터시작)


-- @PagingSize : 한페이지에 표시할 게시글수

SELECT TOP (@PagingSize) *

FROM

(

SELECT ROW_NUMBER() OVER(ORDER BY AccountNo DESC) AS RowNo, *

FROM members

) A

WHERE A.RowNo > (@CurrentPageIndex - 1) * @PagingSize;
 
 
의문사항 ::
 
SELECT ROW_NUMBER() OVER(ORDER BY AccountNo DESC) AS RowNo, * FROM members 을
 
SELECT TOP( @CurrentPageIndex * (@PagingSize) ROW_NUMBER() OVER(ORDER BY AccountNo DESC) AS RowNo, *  FROM members  로
 
바꾸면 어떻까 하는 생각이 든다...
 
 

2010년 7월 30일 금요일

Apache cassandra

Apache cassandra

Key-value DB의 하나인데... 

Digg, Facebook, Twitter 등의 서비스에서 대규모 처리를 지원하는데 사용한다고 하네요..

http://cassandra.apache.org/

2010년 7월 20일 화요일

간단하게 정리해본 페이스북 앱 개발 튜토리얼

간단하게 정리해본 페이스북 앱 개발 튜토리얼: "

페이스북과 연동한 웹 개발 방식은 크게 두 종류로 나눌 수 있다. 하나는 기존 웹사이트와 페이스북을 연동하는 페이스북 커넥트 방식의 웹 개발이고, 다른 하나는 페이스북 페이지 안에 사이트를 내장시키는 페이스북 캔버스 애플리케이션(앱) 방식이다. 페이스북 캔버스 앱은 다시 내장 방식으로 아이프레임을 사용하냐 혹은 페이스북에서 제공하는 FBML을 사용하냐에 따라 아이프레임 캔버스와 FBML 캔버스로 나눌 수도 있다.


페이스북은 잘 정리된 개발문서와 개발자 지원 페이지를 제공하고 있고, 또한 위에서 소개한 각각의 개발 방식에 맞춰 여러 종류의 개발 언어로 작성된 SDK를 제공하기 때문에 어떤 개발환경을 사용하든 손쉽게 페이북과 연동되는 웹 애플리케이션/서비스를 개발할 수 있다.



오픈 그래피 API와 OAuth


최근 페이스북은 기존의 REST 방식의 API를 버리고 오픈 그래프라는 오픈 프로토콜에 기반한 API로 서비스 접근 방식을 변경하였다. 또한 서비스 인증(authentication & authorization)도 오픈 표준인 OAuth2를 채용함으로써 이전보다 훨씬 표준적인 개발 방식으로 접근할 수 있는 길을 열어 놓고 있다.


특히 페이스북 자바스크립트 SDK와 FBML의 클라이언트 확장인 XFBML을 이용하게 되면 기존 페이스북 커넥트나 아이프레임 캔버스 방식의 페이스북 앱 성능도 향상시킬 수 있게 되었다.


페이스북 앱 개발 절차


페이스북 앱 개발 절차를 간략히 정리하면 아래 단계와 같다. 자세한 내용은 페이스북 개발 문서를 참조하면 된다.



  1. 페이스북 개발자 페이지에서 새 App을 추가한다.

  2. 페이스북 자바스크립트 SDK를 페이지에 추가한다.

  3. OAuth 액세스 토큰으로 그래프 API를 액세스한다.

  4. FBML/XFBML, FQL을 적절히 이용한다.


루비/레일스와 페이스북 앱


아쉽게도 아직 페이스북에서 루비/레일스 개발자들을 위한 공식 SDK는 제공하지 않는다. 그렇지만 이미 루비 커뮤니티에서는 페이스북 개발을 지원하는 많은 라이브러리와 도구들이 나와 있다. 대표적인 것은 다음과 같다.



  • Facebooker: 레일즈 플러그인. 가장 오래되고 사용자 기반이 넓지만 Old REST 방식이며 다소 무겁다는 단점이 있다.

  • Facebooker2: 기존 Facebooker를 새 API에 맞게 리모델링한 것으로, 그래프 API 라이브러리인 mogli를 기반으로 한다.

  • sinbook: Sinatra 확장 라이브러리. 300줄 정도의 적은 코드로 되어 있으며, Old REST API 방식.

  • Koala: 새 API 기반이며 커넥트와 앱 개발 모드 모두를 지원한다. 주목할 만 한 신예 라이브러리.


"

2010년 7월 7일 수요일

2010년 6월 17일 목요일

OAuth1.0a + OAuth Access Tokens using credentials draft

OAuth1.0a + OAuth Access Tokens using credentials draft


Twitter.com에서 2-legged 방식으로 access token을 제공하는 방식의 OAuth Access Tokens using credentials draft 스펙을 적용해서 운영을 하고 있군요. 이에 대해 분석을 좀 해 봤습니다.



1. 배경

- 기존에는 웹 방식으로 3-legged 방식으로 진행되어 웹이 지원되지 않는 클라이언트 어플에서 한계점이 있었음.

- OAuth WRAP/2.0이 아직 안나와서 OAuth Access Tokens using credentials draft + OAuth 1.0a를 트위터에서 구현한 것임.

- 이 스펙의 draft로 인해 클라이언트 및 모바일 어플에서도 확장되어 사용할 가능성이 많아 보임.



2. 개요

- OAuth1.0a + OAuth Access Tokens using credentials draft(xAuth) 개념 도입함.

- xAuth : x_auth_mode, x_auth_username, x_auth_password 요청 파라미터에 추가되었음.

- 기존은 3-legged 방식이었는데 이 방식은 2-legged 방식으로 변환되어 바로 access token을 제공하여 이 토큰을 가지고 보호 개인 콘텐츠들을 공유할 수 있는 기반을 마련해 줌.

- Third Party(Consumer)에서는 아이디/패스워드는 관리하지 않고 access token만 관리를 하게 됨.

- OAuth WRAP/2.0는 FriendFeed, Facebook에서 적용하고 있음.



3. OAuth Access Tokens using credentials draft 상세 정보

*. 요청시 파라미터

- x_auth_mode=client_auth

- x_auth_username=트위터 아이디

- x_auth_password=트위터 패스워드

- oauth_consumer_key : 트위터에서 발급한 consumer 인증용 키

- oauth_signature_method : 시그너처 암호화 방법

- oauth_signature : 시그너처

- oauth_timestamp : 요청 시간

- oauth_nonce : phishing용 방어 Nonce

- oauth_version : OAUTH 스펙 버전(1.0)



*. 요청 응답 파라미터(아래 파라미터만 Consumer 사이트에서 관리함)

- oauth_token : TwitterPic에서 이미지 공유가능하도록 접근 허용 키 발급(access token)

- oauth_token_secret : 키에 대한 credentials 값

- x_auth_expires : 인증 세션 만료 기간(0:무기한, 만료되었을 경우 Consumer 사이트는 재 인증 절차를 밟아야 함)



4. 이슈

- username, password 정보를 Third-Party에서 저장해서 관리할 가능성 존재.

- Phishing Attacks, Session Fixation Attacks의 OAuth 자체가 안고 있는 보안 이슈에 대해서도 보완도 필요해 보임.



[참조사이트]



•OAuth Access Tokens using credentials draft

•OAuth WRAP/2.0
 
출처: http://www.mimul.com/pebble/default/2010/02/17/1266404940000.html

2010년 6월 7일 월요일

PHP cURL library

1. cURL이란?




- cURL = Client URL

- cURL은 아래와 같은 프로토콜 등에 의해 전송되는 파일들을 위한 command line tool이다.

FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS, FILE

- SSL, HTTP POST, HTTP PUT, FTP uploading, HTTP form기반의 upload, proxies, cookies, user+password인증도 제공한다.

- cURL은 무료이며, 많은 운영체제에서 컴파일되고 동작하는 open software이다.

- command line tool을 이용하거나

- libCURL을 이용할 수 있다.


http://webtech.tistory.com/search/curl

2010년 6월 3일 목요일

bash shell script 가이드

Bash Shell Script 가이드

http://wiki.kldp.org/HOWTO/html/Adv-Bash-Scr-HOWTO/

Announcing Snowflake

http://engineering.twitter.com/2010/06/announcing-snowflake.html

트위터의 트윗 아이디 생성하는 소스를 오픈했습니다.

K-V 디비에서 Key 값을 생성할때 유용하게 사용할 수 있을 듯 합니다.

2010년 6월 1일 화요일

Comet with PHP

comet  with PHP

http://www.zeitoun.net/articles/comet_and_php/start

2010년 5월 17일 월요일

아이폰앱 개발 무료 강좌

http://www.ittoday.co.kr/news/articleView.html?idxno=13499


아이폰 앱 개발 무료 동영상 강좌.


http://www.appsnext.com/

앱 개발자들 참고.

2010년 5월 11일 화요일

rsyncd.conf 관련 메뉴얼

rsyncd.conf 관련 메뉴얼

http://samba.anu.edu.au/ftp/rsync/rsyncd.conf.html

Linux 자료

http://yyman.tistory.com/category/강좌/자료/리눅스

Bash Shell 프로그래밍

Shell


사용자와 운영체제 사이에 존재하여 사용자의 명령을 운영체제가 이해하도록 하고, 사용자 명령의 실행 결과를 사용자에게 보여주는 사용자 인터페이스

Steven Bourne이 개발한 Bourne Shell(sh)가 최초의 Shell 이다.



Bash Shell

1988년 1월 10일 Brian Fox가 개발

GNU 시스템의 표준 Shell로 자리 잡았고 그 후 거의 모든 유닉스에서 사용됨

1989년 Chet Ramey가 합류하여 곧 공식적으로 bash의 유지보수를 맡게 되었다.

Sh Shell의 기본기능에 csh와 ksh의 장점을 합하여 bash가 탄생하였다.



Bash 기본 설정 파일

.profile : sh의 설정파일

대부분의 환경 설정이 이루어 지며 사용자가 시스템에 로그인할 때마다 실행된다.

.bash_profile : bash의 .profile

.bashrc : 서브Shell이 실행될 때 읽는다.

서브 Shell이란 로그인Shell에서 다시 bash가 실행되는 경우이다.



Shell script

Script : Shell 명령어들을 담고 있는 파일로 Shell Program이라고도 부른다.

.bash_profile, .bashrc 등은 모두 script이다.



문법



변수

처음 사용될 때 만들어진다. 즉, 미리 선언할 필요가 없다.

유닉스 명령과 마찬가지로 대소문자 구별이 있다.

기본적으로 데이터를 문자열로 저장한다. 수치를 입력해도 문자열로 저장한다.

계산이 필요한 경우에는 자동으로 수치로 변환하여 계산 후 다시 문자열로 저장된다.

변수의 값을 사용할 때는 변수 명 앞에 “$”를 붙여서 사용한다.



foo=”동영상은 tv팟” - 입력

echo $foo - 입력

동영상은 tv팟 - 출력결과 주의! 변수에 값 입력시 ! 가 들어갈시에는 작은따옴표(‘test’)로 입력한다.



환경변수

Shell을 기동하고 나면 기복적으로 셋팅 되어 있는 변수. 필요한 경우 일반변수처럼 값을 얻어오거나 셋팅 할 수 있다.

$0 – 실행된 쉘 스크립트 이름 b. $# - 스크립트에 넘겨진 인자의 개수 c. $$ - 쉘 스크립트의 프로세스 ID



인자변수

쉘 스크립트에 인자를 넘겨줄 때 그 인자들에 대한 정보를 가지고 있는 변수이다.

$1 ~ $nnn – 넘겨진 인자들 b. $* - 스크립트에 전달된 인자들을 모아놓은 문자열 하나의 변수에 저장되며 IFS 환경변수의 첫번째 문자로 구분된다. c. $@ - $*와 같은 기능이지만 구분자가 IFS변수의 영향을 받지 않는다.



예제

-> ./vi test2.sh

echo "This Script Executable File : $0"

echo "Argument Count : $#"

echo "Process ID : $$"

echo "Argument List \$* : $*"

echo "Argument List \$@ : $@"

echo "Argument 1 : $1"

echo "Argument 2 : $2"



-> ./sh test.sh a b

This Script Executable File : ./test2.sh

Argument Count : 2

Process ID : 9308

Argument List $* : a b

Argument List $@ : a b

Argument 1 : a

Argument 2 : b

함수

함수는 스크립트 안의 스크립트이다 (a script-within-a-script)

함수는 쉘의 메모리에 저장되고, 실행 속도가 빠르다

declare –F 명령어로 현재 자신의 로그인 세션에 정의되어 있는 함수들을 알 수 있다.

명령어 우선순위

Alias (alias ls=’ls –l’) b. 예약어 (function, if , for, ….) c. 함수 d. bunlt-ins like cd and type e. 스크립트, 프로그램



함수 정의 방법



bash

function testfunc {

echo "test"

}



sh

testfunc() {

echo "test"

}

예제)

val1=$1

val2=$2

function testfunc {

echo "동영상은 tv팟"

echo $val1

echo $val2

}

testfunc

}

String 연산자

${varname:-word} : varname이 존재하고 null이 아니면 그 값을 리턴, 아니면 word리턴

${varname:=word} : varname이 존재하고 null이 아니면 그 값을 리턴, 아니면 varname에 word를 대입

${varname:?message} : varname이 존재하고 null이 아니면 그 값을 리턴, 아니면 varname을 출력하고 message를 출력

${varname:+word} : varname이 존재하고 null이 아니면 word를 리턴 아니면 null을 리턴

${varname:offset:leng(없으면 varname의 length)} : varname=daum tvpot이면 ${varname:4}의 값은 tvpot, ${varname:5:2}의 값은 tv



pattern and pattern matching

${#valiable} : valiable의 길이를 가져온다

${variable#pattern} : pattern이 variable의 앞부분이 일치하면 가장 짧은 부분을 제거하고 나머지를 리턴

${variable##pattern} : pattern이 variable의 앞부분과 일치하면 가장 긴 부분을 제거하고나머지를 리턴

${variable%pattern} : pattern이 variable의 뒷부분과 일치하면 가장 짧은 부분을 제거하고나머지를 리턴

${variable%%pattern} : pattern이 variable의 뒷부분과 일치하면 가장 긴 부분을 제거하고나머지를 리턴

${variable/pattern/string} : 일치하는 가장 긴 부분을 string으로 대체. 한번만 일어남

${variable//pattern/string} : 일치하는 가장 긴 부분을 string으로 대체. 모두 일어남



조건문



if / else



문법

if condition

then

statements

elif condition

then

statements

else

statements

fi

값 비교절

[ string ] - string이 빈 문자열이 아니라면 참

[ string1 = string2 ] - 두 문자열이 같다면 참 or string1 matches string2

[ string1 != string2 ] - 두 문자열이 다르면 참 or string1 does not match string2

[ -n string ] - 문자열이 null(빈 문자열) 이 아니라면 참

[ -z string ] - 문자열이 null(빈 문자열) 이라면 참

[ expr1 -lt expr2 ] – exp2가 exp1보다 크면 참 (‘Less than')

[ expr1 -le expr2 ] – exp2가 exp1보다 크거나 같다면 참 (‘Less than or equal')

[ expr1 -eq expr2 ] - 두 표현식 값이 같다면 참 (‘EQual')

[ expr1 -ne expr2 ] - 두 표현식 갑이 같지 않다면 참 ('Not Equal')

[ expr1 -gt expr2 ] - expr1 > expr2 이면 참 ('Greater Then')



[ expr1 -ge expr2 ] - expr1 >= expr2 이면 참 ('Greater Equal')



[ expr1 -ne expr2 ] - expr1 != expr2 이면 참 ('Not Equal')

[ ! expr ] - expr 이 참이면 거짓, 거짓이면 참

[ expr1 -a expr2 ] - expr1 AND expr2 의 결과 (둘다 참이면 참, 'And')

[ expr1 -o expr2 ] - expr1 OR expr2 의 결과 (둘중 하나만 참이면 참, 'Or')



파일관련 비교절

[ -d FILE ] - FILE 이 디렉토리이면 참

[ -e FILE ] - FILE 이 존재하면 참

[ -f FILE ] - FILE 이 존재하고 정규파일이면 참

[ -r FILE ] – 파일 읽을 권한이 있다면 참

[ -s FILE ] – 파일이 있고 빈파일 아니라면 참

[ -w FILE ] – 파일 쓰기 권한이 있다면 참

[ -x FILE ] – 실행권한이 있다면 참

[ -O FILE ] – 파일의 주인(?)이라면 참

[ -G FILE ] – 파일의 group ID와 사용자의 group ID가 같다면 참

[ FILE1 -nt F - : FILE1이 FILE2 보다 새로운 파일이면 ( 최근파일이면 ) 참

[ FILE1 -ot F - : FILE1이 FILE2 보다 오래된 파일이면 참



case



문법

case 변수 in

pattern 1 )

statements ;;

pattern 2 )

statements ;;

* )

statements ;;

esac

select



문법

select name [in list]

do

statements that can use $name …

done

Building a 5 Star Rating System with jQuery, AJAX and PHP

Building a 5 Star Rating System with jQuery, AJAX and PHP: "

In this tutorial, you’ll learn how to build a rating system with AJAX, PHP, and jQuery. Votes will be recorded and updated in real-time with the magic of AJAX, and we’ll also leverage the power of PHP so that you don’t even need a database!





Step 1. Building the HTML


We’re going to create a simple page that lists two movies, and allows you to rate them. This means we need the stars to show the current rating, and to allow voting. We also want an area to show the total votes cast, and the current rating down to one decimal place.





Let’s take a look at the HTML/CSS



<div class='movie_choice'>
Rate: Raiders of the Lost Ark
<div id="r1" class="rate_widget">
<div class="star_1 ratings_stars"></div>
<div class="star_2 ratings_stars"></div>
<div class="star_3 ratings_stars"></div>
<div class="star_4 ratings_stars"></div>
<div class="star_5 ratings_stars"></div>
<div class="total_votes">vote data</div>
</div>
</div>

<div class='movie_choice'>
Rate: The Hunt for Red October
<div id="r2" class="rate_widget">
<div class="star_1 ratings_stars"></div>
<div class="star_2 ratings_stars"></div>
<div class="star_3 ratings_stars"></div>
<div class="star_4 ratings_stars"></div>
<div class="star_5 ratings_stars"></div>
<div class="total_votes">vote data</div>
</div>
</div>

Notice how there are no graphics in this HTML? They’ll be added with CSS. We’re just using the HTML to create the framework that the widget works from. Now it’s time to start adding CSS.



.rate_widget {
border: 1px solid #CCC;
overflow: visible;
padding: 10px;
position: relative;
width: 180px;
height: 32px;
}
.ratings_stars {
background: url('star_empty.png') no-repeat;
float: left;
height: 28px;
padding: 2px;
width: 32px;
}
.ratings_vote {
background: url('star_full.png') no-repeat;
}
.ratings_over {
background: url('star_highlight.png') no-repeat;
}

This first part of the CSS accomplishes a few things:



  • Gives the default ‘empty’ start to each star location

  • Sets up classes for filled in stars, and highlighted stars

  • Defines and styles the stars’ container.


You can either use the graphics provided in the download, or make your own. There needs to be a graphic for each of the three states: empty, full, and highlighted.


Next we add a little more CSS to position the total votes box, and center the widgets so the page matches the graphic at the start of this section.



.total_votes {
background: #eaeaea;
top: 58px;
left: 0;
padding: 5px;
position: absolute;
}
.movie_choice {
font: 10px verdana, sans-serif;
margin: 0 auto 40px auto;
width: 180px;
}



Step 2. Adding the UI Interactivity


At this point, we have a very plain looking bunch of empty stars, but they don’t do a whole lot at this point. This is where jQuery comes to the rescue.





Our first step is to add mouseover and mouseout handlers for the stars. We need to highlight the star the mouse is over, and all the preceding stars.



$('.ratings_stars').hover(
// Handles the mouseover
function() {
$(this).prevAll().andSelf().addClass('ratings_over');
$(this).nextAll().removeClass('ratings_vote');
},
// Handles the mouseout
function() {
$(this).prevAll().andSelf().removeClass('ratings_over');
set_votes($(this).parent());
}
);

We’re taking advantage of jQuery’s powerful .prevAll() and .nextAll() methods to get the stars preceding and following the currently moused over star.


The code above then adds and removes the classes to make the stars under the mouse and before ‘highlighted’, and the stars after ‘not highlighted’.


What about set_votes() ?


This is a function that checks which stars should be in the ‘full’ state, and ties in closely with the next step, where we grab remote data from the server.




Step 3. Retrieving Data from the Server


Our stars highlight when you move the mouse over them, and that’s a great start. But what about the red stars showing the current vote? To reach this step, we need to both get the information from the server, and write some JavaScript to handle that data.



$('.rate_widget').each(function(i) {
var widget = this;
var out_data = {
widget_id : $(widget).attr('id'),
fetch: 1
};
$.post(
'ratings.php',
out_data,
function(INFO) {
$(widget).data( 'fsr', INFO );
set_votes(widget);
},
'json'
);
});

This code block – actually all the JavaScript – goes in a document.ready block. This particular code executes right away. It queries the server and gets some information on every vote widget on the page.


First we set up an object, out_data, to contain the information we’re sending to the server. Our PHP script expects to see ‘fetch’ when just grabbing data, so we include it here. We also include the ID of the widget, which lets the server-side script know what data we’re after. When the call back function fires, it contains a JavaScript object that looks like this:



{
'widget_id' : 'r1',
'number_votes' : 129,
'total_points' : 344,
'dec_avg' : 2.7,
'whole_avg' : 3
}

The .data() method is a bit of jQuery magic that allows you to associate arbitrary data with a DOM

object.



If you look closely at the code, you’ll see we’re taking that object (stored in the variable INFO) and

doing something with it via the .data() method.


The .data() method is a bit of jQuery magic that allows you to associate arbitrary data with a DOM

object. In this case, we’re storing the data in the widget div. It can be accessed later like this:



$('#one_of_your_widgets).data('fsr').widget_id;

set_votes(), Finally.


After the data has been returned from the server, its handed off indirectly to set_votes().



function set_votes(widget) {

var avg = $(widget).data('fsr').whole_avg;
var votes = $(widget).data('fsr').number_votes;
var exact = $(widget).data('fsr').dec_avg;

$(widget).find('.star_' + avg).prevAll().andSelf().addClass('ratings_vote');
$(widget).find('.star_' + avg).nextAll().removeClass('ratings_vote');
$(widget).find('.total_votes').text( votes + ' votes recorded (' + exact + ' rating)' );
}

The first three lines are for readability, as those variable names are pretty long. So let’s take a look at what’s happening here.


Line 7: ‘avg’ is a whole number, representing the rounded vote average of this widget. Because it’s

a number 1-5, we can use it to find the proper star in the widget, and turn it, and the

preceding ones to our ‘filled’ graphic. Notice the use of .andSelf() to include the star that

we’ve selected.


Line 8: This is quite similar to line seven, but we’re removing the filled graphic from later stars. This

is necessary in case the average for this widget has gone down since the last vote.


Line 9: Here we’re updating the grey box underneath the widget, which shows a more precise rating,

and lets a visitor know how many votes have been cast.




Step 4. Let the Voting Begin


The final step for the UI is to enable voting. We’re going to add a click handler to each of the stars. This click handler will be responsible for sending the vote data to the server.





Here’s the click handler:



$('.ratings_stars').bind('click', function() {
var star = this;
var widget = $(this).parent();

var clicked_data = {
clicked_on : $(star).attr('class'),
widget_id : widget.attr('id')
};
$.post(
'ratings.php',
clicked_data,
function(INFO) {
widget.data( 'fsr', INFO );
set_votes(widget);
},
'json'
);
});

In this code block, we start out by creating some variables not only for clarity, but, in this case, so they can be used within the .post callback. Remember the click handler is assigned to the stars, so we also need that second variable, widget, to have the object containing the data.


First, we set up our outgoing data, which we place in the object clicked_data. We grab the class which includes a class name in the format of star_# telling us what vote is being given, and prepare to send that to the server, along with the widget’s ID.


The widget ID is the corner stone that this voting system relies on. It allows us to look up our stored data, and to easily show that data to the visitor.


Finally, on line line, we send this information to the server. The server will add the vote to the current totals, and send information back to the browser containing the updated data. The values displayed by the widget are then updated with set_votes().




Step 5. PHP: Creating the Class


Now that the UI is finished, we need to create a server side script to store and retrieve voting data.





We’re going to create a very simple class in PHP, called ‘Ratings,’ and use it to handle server requests for our rating system. There are only going to be two methods, plus the invocation. The use of our class will look like so:



# New Object
$rating = new ratings($_POST['widget_id']);

# either return ratings, or process a vote
isset($_POST['fetch']) ? $rating->get_ratings() : $rating->vote();

If you go back to section four, you’ll see we load the data with the variable ‘fetch’ set – that’s what we’re looking for here on line five. If its not set, then we’re processing a vote.


The first thing we’re going to look at is the begining of the class, and, more specifically, the constructor.



class ratings {

private $data_file = './ratings.data.txt';
private $widget_id;
private $data = array();

function __construct($wid) {

$this->widget_id = $wid;

$all = file_get_contents($this->data_file);

if($all) {
$this->data = unserialize($all);
}
}

serialize() and unserialize are a great way to easily store

PHP data structures on disk.


There’s a lot going on here in very few lines, so I’m going to cover the important bits.


Line 3: This needs to be set to a text file you’d like to use to store your data. We’re not using a database for this project, although you easily could. A simple file will suffice for our needs.


Line 7: The constructor. This is called when we create our object, and immediately stores the ID of the widget.


Line 11: We try to load the text file. If the file doesn’t exist, fine, but on some systems you’ll need to create it ahead of time and give it the proper permissions for PHP to be able to read and write to it.


Line 14: This line is important. It takes the data from the text file – if there is one – and unserializes() it. The file contains a complex PHP array that’s been converted to a plain text representation, via serialize(), allowing us to store it and read it back in as an array later.




Step 6. The get_ratings() Method.


This method is called either on its own, or from the vote() method. It finds the data for a particular widget ID and returns it to the requesting page, in JSON format.



public function get_ratings() {
if($this->data[$this->widget_id]) {
echo json_encode($this->data[$this->widget_id]);
}
else {
$data['widget_id'] = $this->widget_id;
$data['number_votes'] = 0;
$data['total_points'] = 0;
$data['dec_avg'] = 0;
$data['whole_avg'] = 0;
echo json_encode($data);
}
}

This only looks complicated – it’s actually pretty simple. The first thing we do is check if the array stored in $this->data has a key matching our widget ID. If it does, we just return that information, because that’s the widget data the page was requesting.


We don’t have to do anything to that data because its already in array form. $this->data is just an array of arrays. We encode the array we want with json_encode() and send it back to the browser.


If there’s no data for the widget ID we’ve requested, we create a record with all zero values, and send it back to the browser.


Step 7. The vote() Method


Next, we need to create a method to handle incoming votes. When the method finishes, it has to call get_ratings() to send the updated information back to the web browser.


The Method Start



public function vote() {
# Get the value of the vote
preg_match('/star_([1-5]{1})/', $_POST['clicked_on'], $match);
$vote = $match[1];

The first thing we do is get the value of the vote. Remember that somewhere in ‘clicked_on’ is a class name in the format of star_#. "star_4", for example. To get that value, we’re using a regular expression and capturing the value of the number to $match[1].


The method Middle



$ID = $this->widget_id;
# Update the record if it exists
if($this->data[$ID]) {
$this->data[$ID]['number_votes'] += 1;
$this->data[$ID]['total_points'] += $vote;
}
# Create a new one if it does not
else {
$this->data[$ID]['number_votes'] = 1;
$this->data[$ID]['total_points'] = $vote;
}

Here we store $this->widget_id into $ID for clarity – the following code gets a bit rough on the eyes without it.


We check if information for this ID exists, and, if so, we add a vote to the total vote count, and add the points from the vote received. This is a running total of all votes; so if one person gives five stars, and another, three, that’s eight points total.


If the record doesn’t exist, we create one, with one vote, and just the points from the incoming vote.


Finishing Up



$this->data[$ID]['dec_avg'] = round( $this->data[$ID]['total_points'] / $this->data[$ID]['number_votes'], 1 );
$this->data[$ID]['whole_avg'] = round( $this->data[$ID]['dec_avg'] );

file_put_contents($this->data_file, serialize($this->data));
$this->get_ratings();
}

Once we’ve updated the vote and point totals, we have to calculate both the average expressed as a whole number, and to one decimal point. To avoid having to do the math twice, we first calculate the average to one decimal on line one, and then round that off to a whole number, on line two.


On line four, we’re storing the changed information back on disk after processing it with serialize(). Once the data is safely stored away, we call $this->get_ratings() to send the new, updated information to the browser.




Conclusion


For the sake of simplicity, this isn’t a 100% complete solution. To extend this project, we should store a cookie to make sure people only vote once, or even record the IP address. It’s also possible that two first-votes couple happen simultaneously, and only one may be recorded. It is, however, a great start, and is more then suitable for keeping track of votes on a few handfuls of items on your website. Thoughts? Thanks for reading!




"

2010년 5월 3일 월요일

windows2003 + iis log + awstats-6.8 로그분석기 및 3일이상된 로그 자동지우기

출처: http://blog.naver.com/kikisu11/10038366446


리눅스 로그분석기 webalizer만 쓰다가 리눅스서버를 윈도우 2003으로 옮기면서 그에 해당하는 로그분석기를 찾았으나

생각보다 해당자료를 쉽게 찾아볼수 없었다

우연히 awstats 란 놈을 알게됬으나 대부분 설치가 리눅스 용이었다 그러다 마침 좋은 글을 찾게되어 설치하기로 결정!

참조 사이트 :

http://www.1000dedi.net/hosting/gnuboard4/bbs/board.php?bo_table=serverLecture&wr_id=237

http://blog.naver.com/mijugari?Redirect=Log&logNo=120051328913

http://hbesthee.tistory.com/319

100dedi 는 사장님이 곰아저씨라 불리던 사람이였던거 같은데 잘 되는지 모르겠다

그분들 아직도 열심히 하시는가보다.. 사무실에 한번 찾아간적 있었던거 같은데..쩝







-- 설치과정

1. http://awstats.sourceforge.net에서 윈도우용 awstats(awstats-6.8.exe)를 다운을 받는다

2. http://www.activestate.com 에서 window용 perl을 다운(ActivePerl-5.10.0.1004-MSWin32-x86-287188.msi)을 받는다

3. 다운받은걸(perl) 인스톨한다. ( perl.exe 를 패스로 잡아주던지 system32 폴더안에 넣든지 둘중하나)



--- 여기까진 참조 사이트와 같다.. 이후는 조금 다르다 버전차이인거 같음



4. awstats 인스톨한다 설치과정중에 아무것도 안물어본다.. (급당황-_-)

5. 설치된 디렉토리에서 C:\AWStats\cgi-bin 폴더를 통째로 웹폴더 e:\www 상에 옮긴다.

6. 옮긴 cgi-bin 폴더에서 awstats.model.conf 하나 복사해서 awstats.사이트명.conf 로 변경후 수정



---------------- 수정 내용 -------------------------

LogFile="E:/LogFiles/W3SVC895811793/ex%YY-24%MM-24%DD-24.log"

LogFormat=2

SiteDomain="www.사이트명.co.kr"

DirData="E:/www/weblog/data"

LoadPlugin="timezone +9"



7. IIS 셋팅

- 웹서비스 확장에 Perl 추가

이름:Activeperl 링크: C:\Perl\bin\Perl.exe "%s" %s 속성 : 허용





- 웹단에서 펄 cgi 읽게 해줘야함

IIS셋팅 - 해당웹사이트 - 사이트속성 - 홈디렉토리(탭) - 구성 - 삽입 - 실행파일 C:\Perl\bin\Perl.exe "%s" %s 확장명 .pl





- 로깅형식 맞추기

IIS셋팅 - 해당웹사이트 - 사이트속성 - 웹사이트(탭) - 로깅사용체크 (W3C 확장로그파일형식) -속성버튼 클릭

일정 : 매일 , 파일 명명 및 롤오버 현지 시간 사용

로그디렉토리 해당 디렉토리 설정

-- 고급속성에 들어가 체크해준것들



date,time,c-ip,cs-username,cs-method, cs-uri-stem, sc-status, sc-bytes, cs-version, cs(User-Agent) , csReferer



8. 도스로 들어가서

C:\Perl\bin\perl.exe E:\www\weblog\cgi-bin\awstats.pl -config=사이트명 -update

실행.... 안됨 ㅠ,ㅠ 오류내용(W3C 확장로그파일에 맞추란다)

기존로그를 모두 지우고 iis 에 새로맞춘 로깅형식 데이터를 조금 복사해서 어제날짜로 파일명을 맞춘후 다시 실행!!!

된다~ ㅎㅎㅎ



9. 작업일정 등록

배치파일 생성 (AUTO_LOG_ANALYZER.bat) 명령어 내용

C:\Perl\bin\perl.exe E:\www\weblog\cgi-bin\awstats.pl -config=사이트명 -update



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

10. 매일 쌓이는 iis 로그가 2기가정도 된다 타업체에서 우리사이트 로봇으로 돌려서 데이터를 수집해가는것 같은데

이것저것 작업할게 많아서 수집못하게 설정할 시간이 없다..

우선 로그 관리부터 해야겠다 싶어서 "자동 삭제"로 검색해보니 C#소스만 보였따..

그냥 그 소스 가져다 하나 만들려다 검색명령어를 이리저리 바꿔봤더니 좋은 프로그램이 있다

해당 참조사이트에서 날짜로 자동 삭제하는 프로그램(forfile.exe)을 가져다 썼다..

참고로 forfile.exe 은 윈도우2003에서 기본제공이라는데 명령어가 안먹혀서 인터넷 가서 다운 받아서 system32 폴더에 저장했음



11. 배치파일 생성 (AUTO_LOG_DELETE.bat) 명령어 내용



C:\WINDOWS\system32\forfile /p "E:\LogFiles\W3SVC895811793" /M *.* /D -3 /C "cmd /C del @path"



-- 이상 --



다음날 확인해봤더니 로그가 안쌓였다.. 이런..

오류내용 역시 W3C 확장로그파일에 맞추란다 - 하지만 원인은 이게 아니엿음....

테스트로 로그를 열어서 2000여줄로 줄여서 날렸다.. 잘된다.. 헉!! 무료가 아닌가???

기존 생성된데이터를 모두 지우고 테스트했더니 2기가도 잘 된다...

원인은 어제 테스트한 로그의 날짜가 12월 2일이였고 오늘 새벽에 쌓을려고 하는 로그도 12월 2일이였다.. 모두 지우고

다시 시작했더니 3일간 잘 쌓이고 있다...











[출처] windows2003 + iis log + awstats-6.8 로그분석기 및 3일이상된 로그 자동지우기
작성자 장돌뱅이

2010년 4월 30일 금요일

linux samba 설치하기



리눅스 페도라를 사용하여 삼바 서버를 설치한다.

1. 설치 확인하기
    - rpm -qa samba
      아무런 결과도 없으면 설치되지 않은 것임

2. 설치하기
    - yum -y install samba samba-swat samba_config_samba samba-client samba-common
    자동적으로 설치해 준다.
    당연히 리눅스에서 인터넷이 연결되어야 한다.
    삼바에 필요한 모듈을 모두 설치 한다.
    시간이 좀 걸리므로 술한잔 하시고 오시면 설치가 완료되어 있을 겁니다.^^
    Complete!가 맨 끝줄에 나오면 성공

3. 환경파일
   - etc/bashrc   : 전체적으로 적용되는 파일
   - etc/profile
   - 설정파일 : /etc/samba/smb.conf
[설명]  workgroup = MYGROUP
           server starting =  Samba Server
           security = share <---------- user, server가 있음.
                                                    share : 개나 소 모두 접근 가능 =>일단 이걸로 합시다.
                                                    user : 삼바에서 제공하는 user,password를 이용

[공유] smb.conf파일을 맨 아래에 다음과 같은 내용을 추가한다.
         [homes]    <----공유이름임
              comment = "test"    <--- windows에서 보여질 폴더이름
              path = /homepage  <--- 실제 공유할 디렉토리

4. 삼바의 실행
   - /etc/init.d/smb -restart

5. 보안의 설정
   - samba 서버의 보안을 해제한다.
     (system-config-securitylevel을 이용)
  
6. 테스트(공유를 걸지 않은 상태임)
    1) windows에서 시작->실행 -> //Linux IP로 공유파일을 확인한다.
        [힌트] windows에서 하다 연결이 안되면 안되는 이유가 많으므로
                  먼저 localhost에서 sambaclient로 리스트를 확인해 본다.
                  smbclient -L //192.168.0.4 -N
6.1 삼바 사용자 비밀번호 추가
     smbpasswd -a fedora    <---- fedora는 이미 linux에 등록되어 있는 user name 이여야 합니다.

7. Linux에서 Windows 공유 접근하기
   1) 리스트 확인하기
        smbclient -L //XP_IP -N
   2) 접근하기
        smbclient //XP_IP/공유폴더명 -U administrator
   3) mount하기
        mount.cifs //XP_IP/공유명  /mnt/xp user=administrator, pass=####
        => 당근으로 /mnt/xp를 만들어야 한다는 것...   뭔말인지 알져?
8. 사용자 제한
   /etc/samba/smb.conf

2010년 4월 29일 목요일

ubuntu 9.10 에서 APM + viewvc + cvsgraph 돌리기

 
 

끄자님이 Google 리더 이메일을 보내셨습니다!

 
 

10. 4. 28 작성자: 구차니의 구차니의 잡동사니 모음

APM (Apache - PHP - Mysql)
apache2
php5
mysql-server
패키지를 설치하면 자동으로 서버로 구동하게 된다.

viewvc / cvsgraph / enscript
viewvc
cvsgraph
enscript

기본적으로 설치되는 경로는
/var/www [htdocs]
/usr/lib/cgi-bin [cgi-bin]

/etc/viewvc/viewvc.conf
/etc/viewvc/cvsgraph.conf
[링크 : http://ubuntuforums.org/showthread.php?t=272022]

cvsgraph.conf는 별다르게 수정할건 없으며
viewvc.conf는 상당부분 수정이 가해진다.

viewvc.conf

#---------------------------------------------------------------------------
#
# Configuration file for ViewVC
#
# Information on ViewVC is located at the following web site:
#     http://viewvc.org/
#
#---------------------------------------------------------------------------

#
# BASIC CONFIGURATION
#
# For correct operation, you will probably need to change the following
# configuration variables:
#
#    cvs_roots (for CVS)
#    svn_roots (for Subversion)
#    root_parents (for CVS or Subversion)
#    default_root
#    rcs_path or cvsnt_exe_path
#    mime_types_file
#
# It is usually desirable to change the following variables:
#
#    address
#    forbidden
#
#    use_enscript
#    use_cvsgraph
#
# For Python source colorization:
#
#    py2html_path
#
# To optimize delivery of ViewVC static files:
#
#    docroot
#
# To customize the display of ViewVC for your site:
#
#    template_dir
#    the [templates] override section
#

#
# FORMAT INFORMATION
#
# This file is delineated by sections, specified in [brackets]. Within each
# section, are a number of configuration settings. These settings take the
# form of: name = value. Values may be continued on the following line by
# indenting the continued line.
#
# WARNING: indentation *always* means continuation. name=value lines should
#          always start in column zero.
#
# Comments should always start in column zero, and are identified with "#".
#
# Certain configuration settings may have multiple values. These should be
# separated by a comma. The settings where this is allowed are noted below.
#
# Any other setting that requires special syntax is noted at that setting.
#

#---------------------------------------------------------------------------
[general]

#
# This setting specifies each of the CVS roots on your system and assigns
# names to them. Each root should be given by a "name: path" value. Multiple
# roots should be separated by commas and can be placed on separate lines.
#
cvs_roots = cvs: /home/cvs

#
# This setting specifies each of the Subversion roots (repositories)
# on your system and assigns names to them. Each root should be given
# by a "name: path" value. Multiple roots should be separated by
# commas and can be placed on separate lines.
#
svn_roots = svn: /home/svn/repository

# The 'root_parents' setting specifies a list of directories in which
# any number of repositories may reside.  Rather than force you to add
# a new entry to 'cvs_roots' or 'svn_roots' each time you create a new
# repository, ViewVC rewards you for organising all your repositories
# under a few parent directories by allowing you to simply specifiy
# just those parent directories.  ViewVC will then notice each
# repository in that directory as a new root whose name is the
# subdirectory of the parent path in which that repository lives.
#
# You can specify multiple parent paths separated by commas or new lines.
#
# Caution: these names can, of course, clash with names you have
# defined in your cvs_roots or svn_roots configuration items.  If this
# occurs, you can either rename the offending repository on disk, or
# grant new names to the clashing item in cvs_roots or svn_roots.
# Each parent path is processed sequentially, so repositories under
# later parent paths may override earlier ones.
#
#root_parents = /home/svn-repositories : svn,
#               /home/cvs-repositories : cvs

# this is the name of the default root
# (ignored when root_as_url_component is turned on)
default_root =

# uncomment if the RCS binaries are not on the standard path
#rcs_path = /usr/bin/

# ViewVC can use CVSNT (www.cvsnt.org) instead of the RCS
# utilities to retrieve information from CVS repositories.
# To enable use of CVSNT, set the "cvsnt_exe_path" value
# to the path of the CVSNT executable. (If CVSNT is on the
# standard path, you can also set it to the name of the
# CVSNT executable). By default "cvsnt_exe_path" is set to
# "cvs" on Windows and is not set on other platforms.
#
#cvsnt_exe_path =
#cvsnt_exe_path = cvs
#cvsnt_exe_path = K:\Program Files\cvsnt\cvs.exe
#cvsnt_exe_path = /usr/bin/cvs

# use rcsparse python module to retrieve cvs repository information instead
# of invoking rcs utilities. this feature is experimental
use_rcsparse = 0

# uncomment if the svn command-line utilities are not on the standard path
#svn_path = /usr/bin/

#
# This is a pathname to a MIME types file to help viewvc to guess the
# correct MIME type on checkout.
#
# If you are having problems with the default guess on the MIME type, then
# uncomment this option and point it at a MIME type file.
#
# For example, you can use the mime.types from apache here:
#mime_types_file = /usr/local/apache/conf/mime.types

# This address is shown in the footer of the generated pages.
# It must be replaced with the address of the local repository maintainer.
address = <a href="mailto:cvs-admin@insert.your.domain.here">No admin address has been configured</a>

#
# This should contain a list of modules (that is, top-level directories within
# repositories) that should not be displayed (by default or by explicit path
# specification).
#
# This configuration can be a simple list of modules, or it can get quite
# complex:
#
#   *) The "!" can be used before a module to explicitly state that it
#      is NOT forbidden. Whenever this form is seen, then all modules will
#      be forbidden unless one of the "!" modules match.
#
#   *) Shell-style "glob" expressions may be used. "*" will match any
#      sequence of zero or more characters, "?" will match any single
#      character, "[seq]" will match any character in seq, and "[!seq]"
#      will match any character not in seq.
#
#   *) Tests are performed in sequence. The first match will terminate the
#      testing. This allows for more complex allow/deny patterns.
#
# Tests are case-sensitive.
#
# NOTE: This is for the hiding of modules within repositories, *not*
# for the hiding of repositories (roots) themselves.
#
# Some examples:
#
# Disallow "example" but allow all others:
#   forbidden = example
#
# Disallow "example1" and "example2" but allow all others:
#   forbidden = example1, example2
#
# Allow *only* "example1" and "example2":
#   forbidden = !example1, !example2
#
# Forbid modules starting with "x":
#   forbidden = x*
#
# Allow modules starting with "x" but no others:
#   forbidden = !x*
#
# Allow "xml", forbid other modules starting with "x", and allow the rest:
#   forbidden = !xml, x*, !*
#
forbidden =

#
# This is similar to 'forbidden', but differs in some key ways:
#
#   *) Rather than shell-style "glob" expressions, the values in this
#      list are regular expressions.  You can still prepend a ! character
#      to each regular expression to invert its meaning, though.
#
#   *) It compares not against modules only, but against paths consisting
#      of the repository (or root) name plus the path of the versioned file
#      or directory to be tested.  For example, to see if the user is
#      authorized to see the path "/trunk/www/index.html" in the repository
#      whose root name is "svnrepos", this authorizer will test the path
#      "svnrepos/trunk/www/index.html" against the list of forbidden regular
#      expressions.  Directory paths will be terminated by a forward slash.
#
# NOTE: Use of this configuration option will *disable* any configuration of
# the 'forbidden' option -- they cannot be used simultaneously.
#
# Some examples:
#
#    Disallow files named "PRIVATE", but allow all others:
#       forbiddenre = /PRIVATE$
#
#    Allow only the "example1" and "example2" roots and the paths inside them,
#    disallowing all others (which can be done in multiple ways):
#       forbiddenre = !^example1(/|$), !^example2(/|$)/
#       forbiddenre = !^example[12](/|$)
#
#    Only allow visibility of HTML files and the directories that hold them:
#       forbiddenre = !^.*(/|\.html)$
#
forbiddenre =

#
# This option provides a mechanism for custom key/value pairs to be
# available to templates. These are stored in key/value files (KV files).
#
# Pathnames to the KV files are listed here, specified as absolute paths
# or relative to this configuration file. The kV files follow the same
# format as this configuration file. It may have multiple, user-defined
# sections, and user-defined options in those sections. These are all
# placed into a structure available to the templates as:
#
#    kv.SECTION.OPTION
#
# Note that an option name can be dotted. For example:
#
#    [my_images]
#    logos.small = /images/small-logo.png
#    logos.big = /images/big-logo.png
#
# Templates can use these with a directive like: [kv.my_images.logos.small]
#
# Note that sections across multiple files will be merged. If two files
# have a [my_images] section, then the options will be merged together.
# If two files have the same option name in a section, then one will
# overwrite the other (it is unspecified regarding which "wins").
#
# To further categorize the KV files, and how the values are provided to
# the templates, a KV file name may be annotated with an additional level
# of dotted naming. For example:
#
#    kv_files = [asf]kv/images.conf
#
# Assuming the same section as above, the template would refer to an image
# using [kv.asf.my_images.logos.small]
#
# Lastly, it is possible to use %lang% in the filenames to specify a
# substitution of the selected language-tag.
#
kv_files =

# example:
# kv_files = kv/file1.conf, kv/file2.conf, [i18n]kv/%lang%_data.conf
#

#
# The languages available to ViewVC. There are several i18n mechanisms
# available:
#
#   1) using key/value extension system and reading KV files based on
#      the selected language
#   2) GNU gettext to substitute text in the templates
#   3) using different templates, based on the selected language
#
# ### NOTE: at the moment, the GNU gettext style is not implemented
#
# This option is a comma-separated list of language-tag values. The first
# language-tag listed is the default language, and will be used if an
# Accept-Language header is not present in the request, or none of the
# user's requested languages are available. If there are ties on the
# selection of a language, then the first to appear in the list is chosen.
#
languages = en-us

# other examples:
#
# languages = en-us, de
# languages = en-us, en-gb, de
# languages = de, fr, en-us
#

#---------------------------------------------------------------------------
[options]

# root_as_url_component: Interpret the first path component in the URL
# after the script location as the root to use.  This is an
# alternative to using the "root=" query key. If ViewVC is configured
# with multiple repositories, this results in more natural looking
# ViewVC URLs.
# Note: Enabling this option will break backwards compatibility with
# any old ViewCVS URL which doesn't have an explicit "root" parameter.
root_as_url_component = 0

# default_file_view: "log" or "co"
# Controls whether the default view for file URLs is a checkout view or
# a log view. "log" is the default for backwards compatibility with old
# ViewCVS URLs, but "co" has the advantage that it allows ViewVC to serve
# static HTML pages directly from a repository with working links
# to other repository files
# Note: Changing this option may cause old ViewCVS URLs that referred
# to log pages to load checkout pages instead.
default_file_view = log

# checkout_magic: Use checkout links with magic /*checkout*/ prefixes so
# checked out HTML pages can have working links to other repository files
# Note: This option is DEPRECATED and should not be used in new ViewVC
# installations. Setting "default_file_view = co" achieves the same effect
checkout_magic = 0

# http_expiration_time: Expiration time (in seconds) for cacheable
# pages served by ViewVC.  Note that in most cases, a cache aware
# client will only revalidate the page after it expires (using the
# If-Modified-Since and/or If-None-Match headers) and that browsers
# will also revalidate the page when the reload button is pressed.
# Set to 0 to disable the transmission of these caching headers.
http_expiration_time = 600

# generate_etags: Generate Etag headers for relevant pages to assist
# in browser caching.
#   1      Generate Etags
#   0      Don't generate Etags
generate_etags = 1

# sort_by: File sort order
#   file   Sort by filename
#   rev    Sort by revision number
#   date   Sort by commit date
#   author Sort by author
#   log    Sort by log message
sort_by = file

# sort_group_dirs: Group directories when sorting
#   1      Group directories together
#   0      No grouping -- sort directories as any other item would be sorted
sort_group_dirs = 1

# hide_attic: Hide or show the contents of the Attic subdirectory
#   1      Hide dead files inside Attic subdir
#   0      Show the files which are inside the Attic subdir
hide_attic = 1

# log_sort: Sort order for log messages
#   date   Sort revisions by date
#   rev    Sort revision by revision number
#   cvs    Don't sort them. Same order as CVS/RCS shows them.
log_sort = date

# diff_format: Default diff format
#   h      Human readable
#   u      Unified diff
#   c      Context diff
#   s      Side by side
#   l      Long human readable (more context)
diff_format = h

# hide_cvsroot: Don't show the CVSROOT directory
#   1      Hide CVSROOT directory
#   0      Show CVSROOT directory
hide_cvsroot = 1

# set to 1 to make lines break at spaces,
# set to 0 to make no-break lines,
# set to a positive integer to make the lines cut at that length
hr_breakable = 1

# give out function names in human readable diffs
# this just makes sense if we have C-files, otherwise
# diff's heuristic doesn't work well ..
# ( '-p' option to diff)
hr_funout = 0

# ignore whitespaces for human readable diffs
# (indendation and stuff ..)
# ( '-w' option to diff)
hr_ignore_white = 1

# ignore diffs which are caused by
# keyword-substitution like $Id - Stuff
# ( '-kk' option to rcsdiff)
hr_ignore_keyword_subst = 1

# Enable highlighting of intraline changes in human readable diffs
# this feature is experimental and currently requires python 2.4
#
hr_intraline = 0

# allow on-the-fly generation of repository tarballs
allow_tar = 0

# allow annotation of files.
allow_annotate = 1

# allow pretty-printed version of files
allow_markup = 1

# allow compression with gzip of output if the Browser accepts it
# (HTTP_ACCEPT_ENCODING=gzip)
# [make sure to have gzip in the path]
allow_compress = 1

# The directory which contains the EZT templates used by ViewVC to
# customize the display of the various output views.  ViewVC looks in
# this directory for files with names that match the name of the view
# ("log", "directory", etc.) plus the ".ezt" extension.  If specified
# as a relative path, it is relative to the ViewVC installation
# directory; absolute paths may be used as well.
#
# If %lang% occurs in the pathname, then the selected language will be
# substituted.
#
template_dir = /etc/viewvc/templates

# Web path to a directory that contains ViewVC static files
# (stylesheets, images, etc.)  If set, static files will get
# downloaded directory from this location.  If unset, static files
# will be served by the ViewVC script (at a likely performance
# penalty, and from the "docroot" subdirectory of the directory
# specified by the "template_dir" option).
#docroot = /docroot

# Show last changelog message for sub directories
# The current implementation makes many assumptions and may show the
# incorrect file at some times. The main assumption is that the last
# modified file has the newest filedate. But some CVS operations
# touches the file without even when a new version is not checked in,
# and TAG based browsing essentially puts this out of order, unless
# the last checkin was on the same tag as you are viewing.
# Enable this if you like the feature, but don't rely on correct results.
show_subdir_lastmod = 0

# show a portion of the most recent log entry in directory listings
show_logs = 1

# Show log when viewing file contents
show_log_in_markup = 1

# Cross filesystem copies when traversing Subversion file revision histories.
cross_copies = 1

# Display dates as UTC or in local time zone
use_localtime = 0
#use_localtime = 1

# == Configuration defaults ==
# Defaults for configuration variables that shouldn't need
# to be configured..

#
# If you want to use Marc-Andrew Lemburg's py2html (and Just van Rossum's
# PyFontify) to colorize Python files, then you may need to change this
# variable to point to their directory location.
#
# This directory AND the standard Python path will be searched.
#
py2html_path = .
#py2html_path = /usr/local/lib/python1.5/site-python

# the length to which the most recent log entry should be truncated when
# shown in the directory view
short_log_len = 80

# should we use 'enscript' for syntax coloring?
use_enscript = 1

#
# if the enscript program is not on the path, set this value
#
enscript_path =
# enscript_path = /usr/bin/

# should we use 'highlight' for syntax coloring?
# NOTE: use_enscript has to be 0 or enscript will be used instead
use_highlight = 0

#
# if the highlight program is not on the path, set this value
#
# highlight_path = /usr/bin

# should we add line numbers?
highlight_line_numbers = 1

# convert tabs to ## spaces (use 0 for no conversion)
highlight_convert_tabs = 2

# use php to colorize .php and .inc files?
use_php = 0

# path to php executable
# (This should be set to the path of a PHP CLI executable, not the path
# to a CGI executable. If you use a CGI executable, you may see "no input file
# specified" or "force-cgi-redirect" errors instead of colorized source. The
# output of "php -v" tells you whether an given executable is CLI or CGI.)
php_exe_path = php
# php_exe_path = /usr/local/bin/php
# php_exe_path = C:\Program Files\php\cli\php.exe

#
# Use CvsGraph. See http://www.akhphd.au.dk/~bertho/cvsgraph/ for
# documentation and download.
#
use_cvsgraph = 0
# use_cvsgraph = 1

#
# if the cvsgraph program is not on the path, set this value
#
#cvsgraph_path =
 cvsgraph_path = /usr/bin/

#
# Location of the customized cvsgraph configuration file. 
# You will need an absolute pathname here:
#
cvsgraph_conf = /etc/viewvc/cvsgraph.conf

#
# Set to enable regular expression search of all files in a directory
#
# WARNING:
#
#   Enabling this option can consume HUGE amounts of server time. A
#   "checkout" must be performed on *each* file in a directory, and
#   the result needs to be searched for a match against the regular
#   expression.
#
#
# SECURITY WARNING:  Denial Of Service
#
#   Since a user can enter the regular expression, it is possible for
#   them to enter an expression with many alternatives and a lot of
#   backtracking. Executing that search over thousands of lines over
#   dozens of files can easily tie up a server for a long period of
#   time.
#
# This option should only be used on sites with trusted users. It is
# highly inadvisable to use this on a public site.
#
use_re_search = 0
# use_re_search = 1

#
# Split directories and logs into pages.
# Allows ViewVC to present discrete pages to the users instead of the
# entire log or directory.
# Set use_pagesize to the number of entries you want displayed on a page.
#
use_pagesize = 0
# use_pagesize = 20

# Limit number of changed paths shown per commit in the Subversion revision
# view and in query results. This is not a hard limit (the UI provides
# options to show all changed paths), but it prevents ViewVC from generating
# enormous and hard to read pages by default when they happen to contain
# import or merge commits affecting hundreds or thousands of files.
# Set to 0 to disable the limit.
limit_changes = 100

#---------------------------------------------------------------------------
[templates]

# You can override the templates used by various ViewVC views in this
# section.  By default, ViewVC will look for templates in the
# directory specified by the "template_dir" configuration option (see
# the documentation for that option for details).  But if you want to
# use a different template for a particular view, simply uncomment the
# appropriate option below and specify the currect location of the EZT
# template file you wish to use for that view.
#
# Templates are specified relative to the installation directory, but
# absolute paths may also be used as well.
#
# If %lang% occurs in the pathname, then the selected language will be
# substituted.
#
# Note: the selected language is defined by the "languages" item in the
#       [general] section, and based on the request's Accept-Language
#       header.
#
#directory = templates/directory.ezt
### an alternative directory view
#directory = templates/dir_new.ezt  
#log = templates/log.ezt
### a table-based alternative log view
#log = templates/log_table.ezt 
#query = templates/query.ezt
#diff = templates/diff.ezt
#graph = templates/graph.ezt
#annotate = templates/annotate.ezt
#markup = templates/markup.ezt
#revision = templates/revision.ezt
#query_form = templates/query_form.ezt
#query_results = templates/query_results.ezt
#error = templates/error.ezt
#roots = templates/roots.ezt

#---------------------------------------------------------------------------
[cvsdb]

enabled = 0
#host = localhost
#port = 3306
#database_name = ViewVC
#user =
#passwd =
#readonly_user =
#readonly_passwd =
#row_limit = 1000

#---------------------------------------------------------------------------
[vhosts]
### DOC

# vhost1 = glob1, glob2
# vhost2 = glob3, glob4

# [vhost1-section]
# option = value
# [vhost1-othersection]
# option = value
# [vhost2-section]
# option = value

#
# Here is an example:
#
# [vhosts]
# lyra = *lyra.org
#
# [lyra-general]
# forbidden = hideme
#
# [lyra-options]
# show_logs = 0
#
# Note that "lyra" is the "canonical" name for all hosts in the lyra.org
# domain. This canonical name is then used within the additional, vhost-
# specific sections to override specific values in the common sections.
#

#---------------------------------------------------------------------------


위와 같이 설정하고, 설치하면 아래와 같은 화면을 볼수 있다.
repository 전부를 보는 화면.
cvs 하위의 모든 프로젝트를 보여준다.

cvs는 파일별로 revision이 붙으므로 상관없지만
svn은 프로젝트별로 repository를 구성하면
viewvc 구성이 꽤나 까다로워질것으로 예상된다.

위에서
버튼을 누르면 아래와 같은 revision tree가 그래프로 나타난다.

그리고 개별 소스를 클릭하면 아래와 같이 syntax highlight 되어 나타난다.

아직 euc-kr로 설정하는법을 찾지 못해, 한글이 ??? 로 깨어져 나온다.
해결방법은 아래 링크를 참조!

나의 경우에는 viewvc 1.0.5 버전이고
/usr/lib/viewvc/sapi.py 파일에서
UTF-8을 검색하여 EUC-KR로 고쳐주었다. (3곳)

[링크 : http://www.pyrasis.com/main/SubversionWithViewVCForWindows]
[링크 : http://kldp.org/node/50455]

2010/04/28 - [프로그램 사용] - [작업중] cvsweb + cvsgraph + xampp


 
 

Google 리더를 사용하면 다음과 같은 일들이 가능해집니다.