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

마지막으로 [b]

24 번째 수정본
(24 번째 수정본부터 24 번째 수정본까지의 변경사항) (소소한 수정, 다른 사용자에 의한 수정)
(두 수정본의 내용이 동일하거나, 수정본을 비교할 수 없음.)
사용하고 말고는 자기 맘입니다만, 동작의 정확성을 보장하지 않습니다. 이 패치를 사용하고 싶다면 아래의 테스트 요청에 협조해 주세요~ :-)

페이지 숨김 기능 추가

사용법

$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
이름:  
Homepage:
내용:
 

위키위키분류

이 수정본 편집일: 2012-8-6 4:20 pm (변경사항 [d])
2155 hits | Permalink | 변경내역 보기 [h] | 현재 수정본 보기 | 24 번째 수정본 소스 보기