웹마스터 팁

이 소스코드는 두 개의 사이트에서 테스트되었으며 0.2.6버전을 기반으로 작성되었습니다. (DB구조가 크게 변하지 않는한 계속 사용가능) PHP 5와 PHP 4.2에서 테스트하여 문제없었으며 리눅스 + MySQL에 설치하신 유저분들에게만 해당되는 팁입니다.(좀 고치시면 다른 DB도 지원됩니다)

본 문서는 제 블로그에 올린 글을 Copy & Paste한 관계로 경어체로 작성되었음을 양해바랍니다. 올린 글의 댓글이나 쪽지를 항상 확인할 수 없으므로 귀찮으시더라도 질문은 원문에 댓글로 남기시거나 게시판을 이용해주셨으면 합니다.

(죄송합니다만 '위키가 무엇인가요?'라던지 '도쿠위키는 어떻게 쓰나요?'라는 질문은 사양합니다. ^_^ 일단 본인의 홈페이지에 도쿠위키를 설치까지는 하시고나서 질문해주세요.)



원본 링크

우선 큰 유감은 없지만 회사 인트라넷을 '모니위키'로부터 도쿠위키로 이전시켰다. 미디어위키도 검토를 해보았었지만 좀 복잡하고 컨버전에 많은 시간을 쏟을 수 없어서 가장 짧은 시간안에 이전시킬 만한 툴을 선택하였다. 도쿠위키는 속도가 크게 느리지 않으면서도 체계적인 구조를 가졌고 위키로 유저들이 구축해놓은 팁이나 노하우도 꽤 있는 편이라서 개인적으로도 사용중이다.

그런 관계로 본의 아니게 제로보드 XE와 모니위키를 연동시키는 것에 이어 도쿠위키와 제로보드를 연동시키는 프로그램을 짜게 되었다. (개인적으로 모니위키를 회사용으로 사용하는 것에 대해서는 여러모로 말리고 싶다)

제로보드 XE와 도쿠위키를 연동시키는 것은 모니위키와 연동시키는 것보다 더 깔끔하다. 모니위키도 ACL을 지원하고 있지만 기본적인 수준인데다가 좀 더 복잡한 것을 하기 위해서는 배포본의 코드를 뜯어고치는 문제-그보다 더 심한건 너무나도 무심한 매뉴얼. DO IT YOURSELF라면 할말 없지만...-들이 있는 반면 도쿠위키는 기본 ACL의 설계가 외부 인증모듈과 결합하도록 무리가 없게 만들어져 있고 외부의 인증모듈이 namespace의 퍼미션들과 잘 연동되도록 고려되어 있는데다가 이미 많은 외국 솔루션들과의 통합을 유저들이 경험해본터라 참조해볼만한 문서들이 많았다.

zbxe.class.php의 구현은 외국 유저가 공개한 drupal.class.php을 기반으로 작성하였다.

zbxe.class.php의 구현은 아래와 같다.

<?php
/**
 * ZBXE authentication backend
 * DokuWiki용 제로보드 XE 인증 모듈
 *
 * @license    Creative Commons 3.0 (원저작자 표시 조건 의무)
 * @author     Venister (Joongpil Cho) <venister@empal.com>
 */

class auth_zbxe extends auth_basic {
    var $url = array();
 
    function auth_zbxe() {
        global $conf;
 
        define('__ZBXE__', true);
 
        $config_file =  $conf['auth']['zbxe']['path']."files/config/db.config.php";
        require_once ($config_file);
 
        $this->url['path'] = $conf['auth']['zbxe']['path'];
        $this->url['db_prefix'] = $db_info->db_table_prefix;
        $this->url['host'] = $db_info->db_hostname;
        $this->url['user'] = $db_info->db_userid;
        $this->url['pass'] = $db_info->db_password;
        $this->url['database'] = $db_info->db_database;
 
        // 데이터베이스 연결
        $this->url['link'] = mysql_connect($this->url['host'], $this->url['user'], $this->url['pass']);
        if (!$this->url['link']) {
            msg('데이터베이스 서버에 연결할 수 없습니다: ' . mysql_error());
            $this->success = false;
            return;
        }
 
        if (!mysql_select_db($this->url['database'], $this->url['link'])) {
            msg('데이터베이스에 연결할 수 없습니다: ' . mysql_error());
            $this->success = false;
            return;
        }
        mysql_query("set names utf8");
 
        // PHP 4때문에 destructor를 명시적 선언
        register_shutdown_function("auth_zbxe_disconnect", $this);
    }
 
    // 패스워드 체크하는 함수
    function checkPass($user, $pass) {
        $query = "select count(*) from ".$this->url['db_prefix']."_member where user_id='$user' and password=MD5('$pass')";
        $result = mysql_query($query);
        if(!$result){
            msg('잘못된 쿼리: ' . mysql_error());
            return false;
        }
        $count = mysql_result($result, 0, 0);
        return ($count == 1 ? true: false);
    }
 
   // 유저 정보를 리턴
   //
   // name : 문자열, 유저이름
   // mail : 문자열, 메일주소
   // grps : 배열, 유저의 그룹 목록
    function getUserData($user) {
        global $conf;
 
        $query = "select user_name, email_address, member_srl from ".$this->url['db_prefix']."_member where user_id='$user'";
        $result = mysql_query($query);
        if(!$result) return null;
 
        if($data = mysql_fetch_array($result)){
            $info['name'] = $data[user_name];
            $info['mail'] = $data[email_address];
            $member_srl = $data[member_srl];
        }
 
        $group_table = $this->url['db_prefix']."_member_group";
        $group_member_table = $this->url['db_prefix']."_member_group_member";
 
        $query = "select g.title as title from ".$group_table." g, ".$group_member_table." gm where g.group_srl = gm.group_srl and gm.member_srl = '$member_srl'";
        $result = mysql_query($query);
 
        if (!$result){
            msg('쿼리 실패: ' . mysql_error());
            return false;
        }
 
        while($data = mysql_fetch_array($result)){
            if(strpos($conf['auth']['zbxe']['user'], $data[title]) !== FALSE){
                $info['grps'][] = 'user';
            }
            if(strpos($conf['auth']['zbxe']['admin'], $data[title]) !== FALSE){
                $info['grps'][] = 'admin';
            }
        }
 
        return $info;
    }
}
 
function auth_zbxe_disconnect($obj) {
    mysql_close($obj->url['link']);
}
 
?>

위 소스를 반드시 파일 zbxe.class.php로 저장하여 도쿠위키가 설치된 디렉토리 아래 inc/auth 밑에 복사해 넣는다.

그리고 위의 인증 백-엔드를 사용하기 위해 도쿠위키가 설치된 디렉토리 아래의 conf/local.php에 아래의 내용을 하단에 추가한다.

$conf['useacl'] = 1;
$conf['superuser'] = '@admin';  
$conf['authtype'] = 'zbxe';
$conf['auth']['zbxe']['path'] = "제로보드 설치 전체경로(반드시 /로 끝나야한다)";
$conf['auth']['zbxe']['user'] = "user그룹에 포함될 ZBXE의 그룹명. 여러개는 ;로 구분한다.";
$conf['auth']['zbxe']['admin'] = "admin그룹에 포함될 ZBXE의 그룹명. 여러개는 ;로 구분한다.";
$conf['openregister']= 0;
$conf['autopasswd'] = 1;
$conf['resendpasswd']= 0;

위에서 노란 바탕의 줄은 반드시 추가해야 한다. (나머지는 없으면 추가한다.)

여 기서 몇가지 유의사항이 있는데 이 구현은 도쿠위키 ACL의 기본그룹만을 취급하고 있다는 것이다. (소스코드를 좀 더 고치면 커스텀한 그룹을 취급하는 것도 어려운 일은 아니다. 원래 구현은 그런식으로 처리하도록 하려 했는데 한글로 된 그룹명을 도쿠위키 ACL에서 지원하려면 urlencode를 해야하므로 귀차니즘 때문에 간단하게 구현했다)

때문에 'user'로 구분될 유저의 제로보드 그룹을 $conf['auth']['zbxe']['user'] 줄에 넣는데 각 그룹은 ;로 구분한다. 마찬가지로 admin 그룹은 $conf['auth']['zbxe']['admin']에 명시한다.

두번째 주의사항은 명시할 그룹명의 제한사항인데, 그룹명들이 서로 완전히 달라야 한다는 것이다. 위에서 그룹명을 ;로 구분한다고 했는데 귀차니즘 때문에 explode를 해서 각각을 비교하지 않고 그냥 strpos로 검사했기 때문에 문제가 발생될 소지가 있다.

예를 들면, 제로보드 그룹상에서 '비회원'은 user에 포함되면 안됨에도 불구하고 '예비회원'이라는 그룹이 $conf['auth']['zbxe']['user']안에 포함되어 있으면 '예비회원'이라는 문자열 속에 '비회원'이 포함되어 있으므로 비회원을 user로 처리해버린다.

마지막 주의사항은 local.php는 ANSI로 인코딩되어 있다. (영어로 되어 있으니... 인코딩 신경쓸 필요가 없었겠지...) 그러나 ANSI 인코딩에 그냥 한글로 된 그룹명을 쓰게 되면 절대 정상작동되지 않으므로 인코딩을 UTF-8(BOM코드가 없어야 한다)로 저장해야만 한다.

위의 소스코드를 사용할 분은 위의 주의사항을 숙지하고 쓰시던지 소스코드를 고치시던지 해야할 듯... (귀찮아서 업그레이드는 없다) 소스코드를 고치더라도 local.php를 UTF-8로 인코딩해야 함은 물론이다.
태그 연관 글
  1. [2014/08/29] 묻고답하기 게시판 페이지에 위젯 달기??? by 꼰대 *2
  2. [2012/05/16] 묻고답하기 제로보드xe에서 레이아웃 편집창에 들어가면 이런 메시지가 뜹니다. by 제이투자
  3. [2011/04/18] 웹마스터 팁 XE 홈피에 예쁜 음악BGM 넣는 방법(프레임 분리형 플래시BGM) by 푸른커튼2
  4. [2011/03/04] 묻고답하기 에디터 Auto Resize 기능 by 코아 코스튬 *1
  5. [2011/01/24] 웹마스터 팁 '대표도메인'연결후 '로그인'이 안될때,,(먹통) by moonlight994