2010년 5월 11일 화요일

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 리더를 사용하면 다음과 같은 일들이 가능해집니다.