[첫화면으로]UseModWiki소스수정/페이지숨김

마지막으로 [b]

사용하고 말고는 자기 맘입니다만, 동작의 정확성을 보장하지 않습니다. 이 패치를 사용하고 싶다면 아래의 테스트 요청에 협조해 주세요~ :-)

페이지 숨김 기능 추가

사용법

$HiddenPageFile = "$DataDir/hidden";

config.pl 에 추가

### hide page
$HiddenPageFile = "$DataDir/hidden";  # hidden pages list file

wiki.pl 수정

필요한 환경 변수와 전역 변수 추가
...
###############
### added by gypark
### 패치를 위해 추가된 환경설정 변수
use vars qw(
    $UserGotoBar $UserGotoBar2 $UserGotoBar3 $UserGotoBar4
    $ConfigFile $SOURCEHIGHLIGHT @SRCHIGHLANG $LinkFirstChar
    $EditGuideInExtern $SizeTopFrame $SizeBottomFrame
    $LogoPage $CheckTime $LinkDir $IconDir $CountDir $UploadDir $UploadUrl
    $HiddenPageFile                   # $HiddenPageFile 추가
    );
###
###############
...
###############
### added by gypark
### 패치를 위해 추가된 내부 전역 변수
use vars qw(%RevisionTs $FS_lt $FS_gt $StartTime $Sec_Revision $Sec_Ts
    $ViewCount $AnchoredFreeLinkPattern %UserInterest %HiddenPage);    # %HiddenPage 추가
###
###############
...

wiki.pl 이 구동될 때 숨겨진 페이지들의 목록을 읽어 온다.

sub InitRequest {
    ...
    &InitCookie();         # Reads in user data
###############
### added by gypark
### hide page
    my ($status, $data) = &ReadFile($HiddenPageFile);
    if ($status) {
        %HiddenPage = split(/$FS1/, $data, -1);
    }
###
###############
    return 1;
}

숨겨진 페이지는 브라우징을 금지

sub BrowsePage {
    my ($fullHtml, $oldId, $allDiff, $showDiff, $openKept);
    my ($revision, $goodRevision, $diffRevision, $newText);

###############
### added by gypark
### hide page
    if (&PageIsHidden($id)) {
        print &GetHeader($id, &QuoteHtml($id), $oldId);
        print Ts('%s is a hidden page', $id);
        print &GetCommonFooter();
        return;
    }
###
###############

    &OpenPage($id);
    &OpenDefaultText();
    ...
}

최근 변경 내역에서도 감춤

sub GetRcHtml {
    ...
    foreach $rcline (@outrc) {
        ($ts, $pagename, $summary, $isEdit, $host, $kind, $extraTemp)
            = split(/$FS3/, $rcline);
        # Later: need to change $all for new-RC?
        next  if ((!$all) && ($ts < $changetime{$pagename}));
        next  if (($idOnly ne "") && ($idOnly ne $pagename));
###############
### added by gypark
### hide page
        next if (&PageIsHidden($pagename));
###
###############
###############
### commented by gypark
### RcOldFile 버그 수정
#       next  if ($ts >= $oldts);
    ...
}

변경내역 열람도 금지

sub DoHistory {
    my ($id) = @_;
    my ($html, $canEdit, $row, $newText);

###############
### added by gypark
### hide page
    if (&PageIsHidden($id)) {
        print &GetHeader("",&QuoteHtml(Ts('History of %s', $id)), "");
        print Ts('%s is a hidden page', $id);
        print &GetCommonFooter();
        return;
    }
###
###############

    print &GetHeader("",&QuoteHtml(Ts('History of %s', $id)), "") . "<br>";
    ...
}

편집 가이드에 페이지의 숨겨짐 여부와, 숨김/드러냄 메뉴를 표시

sub GetEditGuide {
    my ($id, $rev) = @_;
    my $result = "\n<HR class='footer'>\n<DIV class='editguide'>";
#       print "<HR class='footer'>\n"  if (!&GetParam('embed', $EmbedWiki));

###############
### added by gypark
### 관리자가 페이지를 볼 때는 하단에 수정 금지 여부를 알려주고 금지 설정/해제를 할 수 있게 함
    if (&UserIsAdmin()) {
    ...
        $result .= " | " . &ScriptLink("action=pagelock&set=0&id=" . $id, T('unlock'));
### hide page by gypark
        $result .= " | ";
        if (defined($HiddenPage{$id})) {
            $result .= T('(hidden)') . " | ";
        }
        $result .= &ScriptLink("action=pagehide&set=1&id=" . $id, T('hide'));
        $result .= " | " . &ScriptLink("action=pagehide&set=0&id=". $id, T('unhide'));
    }
###
###############
    ...
}

include, includenotoc, includeday 매크로로 내용을 가져오지 못하게 함

sub MacroInclude {
    ...
    my $fname = &GetPageFile($name);    # 존재하지 않는 파일이면 그냥 리턴
    if (!(-f $fname)) {
        return "";
    }

###############
### added by gypark
### hide page
    if (&PageIsHidden($name)) {
        return "";
    }
###
###############
    my $data = &ReadFileOrDie($fname);
    my %SubPage = split(/$FS1/, $data, -1);  # -1 keeps trailing null fields
    ...
}

숨겨진 페이지는 당연히 편집도 불가능하다

sub UserCanEdit {
    my ($id, $deepCheck) = @_;

###############
### added by gypark
### hide page
    if (($id ne "") && (&PageIsHidden($id))) {
        return 0;
    }
###
###############

    # Optimized for the "everyone can edit" case (don't check passwords)
    if (($id ne "") && (-f &GetLockedPageFile($id))) {
    ...
}

전체 페이지 목록을 가져오는 AllPagesList 함수에서 숨겨진 페이지는 반환하지 않게 한다. (따라서 다른 매크로나, 그 외에 전체 페이지 목록을 가져와서 작업을 하는 모든 동작에 영향을 미친다)

sub AllPagesList {
    my ($rawIndex, $refresh, $status);

    if (!$UseIndex) {
### hide page by gypark
#       return &GenerateAllPagesList();
        return &GetNotHiddenPages(&GenerateAllPagesList());
###
    }
    $refresh = &GetParam("refresh", 0);
    if ($IndexInit && !$refresh) {
        # Note for mod_perl: $IndexInit is reset for each query
        # Eventually consider some timestamp-solution to keep cache?
### hide page by gypark
#       return @IndexList;
        return &GetNotHiddenPages(@IndexList);
###
    }
    if ((!$refresh) && (-f $IndexFile)) {
        ($status, $rawIndex) = &ReadFile($IndexFile);
        if ($status) {
            %IndexHash = split(/\s+/, $rawIndex);
            @IndexList = sort(keys %IndexHash);
            $IndexInit = 1;
### hide page by gypark
#           return @IndexList;
            return &GetNotHiddenPages(@IndexList);
###
        }
        # If open fails just refresh the index
        }
        # If open fails just refresh the index
    }
    @IndexList = ();
    %IndexHash = ();
    @IndexList = &GenerateAllPagesList();
    foreach (@IndexList) {
        $IndexHash{$_} = 1;
    }
    $IndexInit = 1;  # Initialized for this run of the script
    # Try to write out the list for future runs
    &RequestIndexLock() or return @IndexList;
    &WriteStringToFile($IndexFile, join(" ", %IndexHash));
    &ReleaseIndexLock();
### hide page by gypark
#   return @IndexList;
    return &GetNotHiddenPages(@IndexList);
###
}

action=pagehide 액션 처리

sub DoOtherRequest {
    ...
### UploadedFiles 매크로
        } elsif ($action eq "deleteuploadedfiles") {
            &DoDeleteUploadedFiles();
### hide page by gypark
        } elsif ($action eq "pagehide") {
            &DoPageHide();
###
###############
        } else {
            # Later improve error reporting
            &ReportError(Ts('Invalid action parameter %s', $action));
        }
        return;
    }
    ...
}

페이지 편집을 금함

sub DoEdit {
    ...
    $editCols = &GetParam("editcols", 65);
    print &GetHeader('', &QuoteHtml($header), '');
###############
### added by gypark
### hide page
    if (&PageIsHidden($id)) {
        print Ts('%s is a hidden page', $id);
        print &GetCommonFooter();
        return;
    }
###
###############
###############
### added by gypark
### view action 추가
    if (!$canEdit) {
        if (&UserIsBanned()) {
    ...
}

숨겨진 페이지의 역링크를 찾는 액션도 금함

sub DoReverse {
    ...
        &DoIndex();
        return;
    }
    print &GetHeader('', &QuoteHtml(Ts('Links to %s', $string)), '');
### hide page by gypark
    if (&PageIsHidden($string)) {
        print Ts('%s is a hidden page', $string);
        print &GetCommonFooter();
        return;
    }
###
    print '<br>';

    foreach $pagelines (&GetFullLinkList("page=1&inter=1&unique=1&sort=1&exists=2&empty=0&reverse=$string")) {
    ...
}

페이지 목록을 인자로 받아서 색인을 나누어 출력하는 함수. 여기서 감춰진 페이지는 다시 한 번 걸러낸다. (보통은 이 함수로 들어오기 전에 이미 걸러져 있겠지만) 또한 잠금/해제와 마찬가지로 각 페이지 이름 오른쪽에 숨김/드러냄 메뉴를 표시한다.

sub PrintPageList {
    ...
    $count2 = 0;

    foreach $pagename(@_) {
###############
### added by gypark
### hide page
        next if (&PageIsHidden($pagename));
###
###############
        until (
            $pagename lt @indexSearch[$count]
            && ($count == 0 || $pagename gt @indexSearch[$count-1])
        ) {
    ...
        if (&UserIsAdmin()) {
###############
### added by gypark
### 관리자의 인덱스 화면에서는 잠긴 페이지를 별도로 표시
            if (-f &GetLockedPageFile($pagename)) {
                print " " . T('(locked)');
            }
###
###############
            print " | " . &ScriptLink("action=pagelock&set=1&id=" . $pagename, T('lock'));
            print " | " . &ScriptLink("action=pagelock&set=0&id=" . $pagename, T('unlock'));
###############
### added by gypark
### hide page
            if (defined($HiddenPage{$pagename})) {
                print " | " . T('(hidden)');
            }
            print " | " . &ScriptLink("action=pagehide&set=1&id=" . $pagename, T('hide'));
            print " | " . &ScriptLink("action=pagehide&set=0&id=" . $pagename, T('unhide'));
###
###############
        }
        print $q->br;
        print "\n";
    }
}

숨겨진 페이지를 삭제할 경우, hidden 화일에서도 엔트리를 제거

sub DeletePage {
### page count 화일도 같이 삭제
    $fname = &GetCountFile($page);
    unlink ($fname) if (-f $fname);
### hide page by gypark
    if (defined($HiddenPage{$page})) {
        # 숨긴 화일의 경우는 keep 화일과 rclog 를 다 제거한다.
        &EditRecentChanges(1, $page, "");
        $fname = $KeepDir . "/" . &GetPageDirectory($page) .  "/$page.kp";
        unlink($fname)  if (-f $fname);
        delete $HiddenPage{$page};
        &SaveHiddenPageFile();
    }
#########################################################3
###############
### added by gypark
### 링크 목록을 별도로 관리
    $fname = &GetLinkFile($page);
    unlink($fname) if (-f $fname);
    ...
}

숨겨진 페이지의 이름을 변경할 경우, hidden 화일의 엔트리도 같이 변경

sub RenamePage {
    ...
        &CreatePageDir($CountDir, $new);  # It might not exist yet
        rename($oldcnt, $newcnt) || die "error while renaming count file";
    }
### hide page by gypark
    if (defined($HiddenPage{$old})) {
        delete $HiddenPage{$old};
        $HiddenPage{$new} = "1";
        &SaveHiddenPageFile();
    }
###
###############

###############
### added by gypark
### 링크 목록을 별도로 관리
    my ($oldlink, $newlink);
    $oldlink = &GetLinkFile($old);
    ...
}

페이지 이름을 인자로 받아서, 그 페이지 안에 있는 링크들의 목록을 반환하는 함수. 만일 인자로 받은 페이지 자체가 숨겨진 페이지라면 NULL 을 반환한다. 그렇지 않은 경우, 반환되는 링크 목록 중에서 숨겨진 페이지는 제외하고 반환한다.

sub GetPageLinksFromFile {
    ...
    my ($name, $pagelink, $interlink, $urllink) = @_;
    my ($status, $data, %links, @result, $fname);

###############
### added by gypark
### hide page
    if (&PageIsHidden($name)) {
        return;
    }
###
###############

    @result = ();
    $fname = &GetLinkFile($name);
    ...
    %links = split($FS1, $data, -1);
### hide page by gypark
#   push (@result, split($FS2, $links{'pagelinks'}, -1)) if ($pagelink);
    push (@result, &GetNotHiddenPages(split($FS2, $links{'pagelinks'}, -1))) if ($pagelink);
###
    push (@result, split($FS2, $links{'interlinks'}, -1)) if ($interlink);
    push (@result, split($FS2, $links{'urllinks'}, -1)) if ($urllink);

    return @result;
}

action=pagehide 를 처리하는 함수. 통채로 추가

sub DoPageHide {
    my ($id);

    print &GetHeader('', T('Hide or Unhide page'), '');
    return  if (!&UserIsAdminOrError());
    $id = &GetParam("id", "");
    if ($id eq "") {
        print '<p>', T('Missing page id to hide/unhide');
        return;
    }
    return  if (!&ValidIdOrDie($id));       # Later consider nicer error?

    if (&GetParam("set", 1)) {
        $HiddenPage{$id} = "1";
    } else {
        delete $HiddenPage{$id};
    }

    if (!(&SaveHiddenPageFile())) {
        print T('Hiding/Unhiding page failed');
        print &GetCommonFooter();
        return;
    }

    if (defined ($HiddenPage{$id})) {
        print '<p>', Ts('%s is hidden.', $id), '<br>';
    } else {
        print '<p>', Ts('%s is revealed.', $id), '<br>';
    }
    print &GetCommonFooter();
}

페이지 이름을 인자로 받아서, 숨겨진 페이지인지 아닌지를 반환하는 함수. 통채로 추가

sub PageIsHidden {
    my ($id) = @_;

    if ((!(defined $HiddenPage{$id})) || (&UserIsAdmin())) {
        return 0;
    } else {
        return 1;
    }
}

페이지 이름들의 목록을 배열로 받아서, 그 중에 숨겨진 페이지를 제외하고 나머지를 반환하는 함수. 통채로 추가

sub GetNotHiddenPages {
    my (@pages) = @_;
    my @notHiddenPages = ();

    foreach (@pages) {
        push (@notHiddenPages, $_) if (!(&PageIsHidden($_)));
    }
    return @notHiddenPages;
}

페이지를 숨김 설정하거나 해제할 경우에 hidden 화일을 갱신하는 함수. 통채로 추가

sub SaveHiddenPageFile {
    my $data;

    $data = join($FS1, %HiddenPage);

    &WriteStringToFile($HiddenPageFile, $data);
    chmod(0644, $HiddenPageFile);

    return 1;
}

가장 최근에 수정된 페이지가 숨겨진 페이지이고, 로그인하지 않은 사용자가 최근변경내역을 볼 경우, "이 날 이후의 변경 리스트 보기" 링크에 숨겨진 페이지의 수정 시각이 노출되는 문제 수정:

sub DoRc {
...
# 이 단락을 아래처럼 수정
#    if (@fullrc > 0) {  # Only false if no lines in file
#        ($lastTs) = split(/$FS3/, $fullrc[$#fullrc]);
#    }

### hide page
    for (my $i = $#fullrc; $i >= 0; $i--) {
        my ($ts, $page) = split(/$FS3/, $fullrc[$i]);
        $lastTs = $ts, last if not PageIsHidden($page);
    }

translations/korean.pl 화일에 추가

(hidden)
(숨겨짐)
hide
숨김
unhide
드러냄
Hide or Unhide page
페이지 숨김 설정 또는 해제
Missing page id to hide/unhide
숨김 또는 해제할 페이지 이름이 누락되었습니다...
%s is hidden.
%s 페이지의 숨김 속성을 설정했습니다.
%s is revealed.
%s 페이지의 숨김 속성을 제거했습니다.
%s is a hidden page
%s 는 관리자가 감춘 페이지입니다.
Hiding/Unhiding page failed
페이지 감춤/드러냄 명령에 실패했습니다

추가 업데이트 내역

Notes

테스트 요청

방문객들에게 테스트를 요청합니다. 현재 이 홈페이지의 연습장 에는 HideTest 라는 페이지가 링크되어 있습니다. 왼쪽의 단어 때문에 이 페이지에도 링크가 되어 버렸으니, 두 군데서 링크하고 있고, HideTest 의 정보는 다음과 같습니다.
이 페이지는 페이지 숨김을 테스트하기 위한 페이지입니다.

동해물과 백두산이 마르고 닳도록

[[연습장]]

GyparkWiki

http://gypark.pe.kr

GyparkWiki:UseModWiki소스수정
HideTest 의 내용을 알아낼 방법이 없도록 최대한 감춘다고는 했는데, 정말 모든 경우를 다 봉쇄한 것인지 확신이 서지 않네요. 여기 오시는 분들께서 10분 정도만 시간을 내어서 이런 저런 테스트좀 해보아 주시면 감사하겠습니다.

당연히... 평범하게 링크를 따라가는 길은 다 막혀 있을 테니까... 브라우저의 URL 창에 직접 이런 저런 action 등을 넣어 보거나, 현재 있는 매크로 (매크로 목록은 UseModWiki소스수정에 다 나와 있으니..) 를 사용해 보아야 되겠죠. 텍스트 검색, 역링크, diff 등 수단과 방법을 가리지말고 저 HideTest 페이지 안의 내용을 일부라도 알아낼 수 있는 방법을 발견하시면 제보해 주시면 됩니다. (HideTest 페이지 내에는 연습장으로 가는 링크가 있다.. 내용 중에 "동해물과" 라는 텍스트가 있다.. 등등)

그 외

wantedpages 매크로에서 빈페이지로 표시되지 않고 전체링크로 표시됩니다. 이것은 그다지 상관없을듯... - Bab2
역시 Bab2님! 역시 보기 싫은 부분이 생겨나는군요. 이건 매크로 쪽을 손을 볼지 더 근본적인 곳을 손을 볼 지 고민하게 만드는군요..
-- Raymundo 2003-4-7 2:21 pm
이젠 안 나오죠? :-)
-- Raymundo 2003-4-7 4:59 pm
예. ^^
-- Bab2 2003-4-7 9:32 pm


그럭저럭 마무리 정리를 하고 일단 공개는 합니다. 처음에는 간단하다고 생각하고 손을 대었는데 신경쓸 곳이 한 두 군데가 아니더군요. 그냥 브라우징, 에디팅, 변경내역 등을 보는 것만 금지시켜 버릴까 했습니다만, (그러면 훨씬 간단하겠죠) 숨기려면 확실히 숨기는 것이 더 낫다고 생각했고, 특히나 역링크나 full link list 등을 통해서 숨겨진 페이지 내에 있는 링크나 URL 을 알 수 있다면 숨기는 의미가 너무 없다고 판단해서 일을 크게 벌렸습니다. 현재 Bab2 님께서 열심히 테스트해주시고 계신 듯 한데, 감사의 말씀을 드립니다. 다른 분들도 한번 도전 좀 해봐주세요~ 헛점을 찾아 감춰진 내용을 알아내기... 재밌지 않나요? ;-)
-- Raymundo 2003-4-7 10:10 pm

음..한달쯤 전에 이 기능이 올라왔다면..정말 쌍수를 들고 반겼을듯..하나..(개인적인 부분과 회사업무등과 관련된 위키페이지의 필요성이 있어서..) 현재는 그냥 따로 비공개 위키를 깔아서 쓰고있습니다. 아무래도..기능이 복잡해질것같아서..그래도 여기서 테스트는 열심히 해보죠.. :)
-- Nyxity 2003-4-7 11:08 pm

예, 비공개할 페이지가 많을 경우는 그냥 따로 두는 게 낫죠. 이 기능은 공개된 페이지들을 이것 저것 링크해야 되지만 내용은 감춰야 될 경우 필요한 건데... 제 경우는 제 다이어리나 잡생각을 여기에 같이 끄적일까 해서 만들었지요. 한 달만 빨리 만들 것 그랬군요. ^^
-- Raymundo 2003-4-8 12:06 am

서브페이지는 제가 테스트 할 수 없겠군요. ㅡ.ㅡa

-- Bab2 2003-4-8 1:05 am


숨겨진 페이지 목록을 저장하는 "hidden" 화일의 퍼미션을 600 에서 644 로 설정하도록 변경했습니다. 데이타 디렉토리를 백업할 때 저 화일을 읽을 수 없는 문제가 있었네요.
-- Raymundo 2003-4-22 8:44 pm


Raymundo, this feature inspired me (beside a feature from ancient cwick wiki), a granular visibility on nodes. Something like this (I choose ^ markup, for instance):

  sub CommonMarkup )
 ...
    s/\^admn(.*?)\^/&StoreRaw('<div class=visibility>') . $1 . '<\/div>'/gei if (!&UserIsAdmin());
    s/\^edit(.*?)\^/&StoreRaw('<div class=visibility>') . $1 . '<\/div>'/gei if (!&UserIsEditor()); 
and css:
  div.visibility {
  visibility:hidden;
  position: absolute; 
  top: 0px; left: 0px; 
  z-index: -1;
}

It can be completed with:

  $Text{'text'} =~ s/\^admn(.*?)\^//gei if (not &UserIsAdmin());
  $Text{'text'} =~ s/\^edit(.*?)\^//gei if (not &UserIsEditor());
in own actions as: find, diff, raw in in coherence.

Great!

In fact, there is similar macro "adminonly".

http://gypark.pe.kr/wiki/UseModWiki%EC%86%8C%EC%8A%A4%EC%88%98%EC%A0%95/%EC%82%AC%EC%9A%A9%EC%9E%90%EC%B6%94%EA%B0%80%EB%A7%A4%ED%81%AC%EB%A1%9C#H_5 (Sorry, written in Korean, as always)

Thank you for your code, anyway. :-)
-- Raymundo 2012-7-8 11:06 pm

you're right; even in korean, the "adminonly" particle was a clue ...
(Other feature could be granular edition on node ... ).
Thanks.

-- JuanmaMP 2012-7-8 11:56 pm

Hi, Raymundo et col.:
A question if the answer is not hard work for you:
In UseMod, on sub DeletePage:

  
&EditRecentChanges(1, $page, "")  if ($doRC);  # Delete page <=========
# Currently don't do anything with page text 
is at the bottom, but in UseModKr, is here:
     
if (defined($HiddenPage{$page})) {
       
  &EditRecentChanges(1, $page, ""); <===================================== 
  $fname = $KeepDir . "/" . &GetPageDirectory($page) .  "/$page.kp"; 
  unlink($fname)  if (-f $fname); 
  delete $HiddenPage{$page}; 
  &SaveHiddenPageFile(); 
} 
Why, please?.
Big thanks, and good holidays.
-- JuanmaMP 2012-8-6 4:14 pm

In UseMod, after a page has been deleted, visitors couldn't see the content of the page.

When I made "bookmark" feature, I decided to improve it, so that visitors can see the content of a deleted page. This was done by removing the line "EditRecentChanges(..)". This subroutine removes the footprint(?) of deleted page in rcfile.

After a while, I made this "page hiding" feature. Then the case became opposite. I had to use that subroutine again, because the footprint of hidden page should be removed in rcfile, so that any other visitors couldn't notice that hidden page.

This is why the line is now in the if-block. I wish my explanation could help you.

-- Raymundo 2012-8-6 5:26 pm

Sometimes, I was thinking, when deleting hidden page, don't delete $HiddenPage{$page} (and don't delete rcline (footprint) when delete any page, this last thing for hidden page or not), so doesn't show in Recent Changes because the other filter: "next if PageIsHidden{$page}" on GetRc.

If later, someone wishes edit a "new" page with the same title, then, both assume, (last editor and previous editor), "refresh" the old footprints in Recent Changes about that page, because is now when the old $HiddenPage($page) will be deleted (when the second, third, etc creation). Then, the "new" page inherits the rcline.

I have in mind a conservative information wiki (of any thing) but it's only a design point of view.

Thanks for reading.
Big thanks. Much better now with EditRecentChanges.

-- JuanmaMP 2012-8-7 2:58 am
이름:  
Homepage:
내용:
 

위키위키분류


마지막 편집일: 2012-8-7 3:01 am (변경사항 [d])
1647 hits | Permalink | 변경내역 보기 [h] | 페이지 소스 보기