OSDN Git Service

BugTrack/84 Limit page name length: 115 bytes(soft); 125 bytes(hard)
[pukiwiki/pukiwiki.git] / lib / link.php
index 711be8d..8ca3088 100644 (file)
@@ -1,20 +1,35 @@
 <?php
 // PukiWiki - Yet another WikiWikiWeb clone
-// $Id: link.php,v 1.4 2005/01/29 13:51:44 henoheno Exp $
+// link.php
+// Copyright 2003-2022 PukiWiki Development Team
+// License: GPL v2 or (at your option) any later version
 //
 // Backlinks / AutoLinks related functions
 
-/*
- * CACHE_DIR/encode(¥Ú¡¼¥¸Ì¾).ref
- * »²¾È¸µ¥Ú¡¼¥¸Ì¾<tab>AutoLink¤Ë¤è¤ë¥ê¥ó¥¯¤Î¤ß¤Î¤È¤­1\n
- * »²¾È¸µ¥Ú¡¼¥¸Ì¾<tab>AutoLink¤Ë¤è¤ë¥ê¥ó¥¯¤Î¤ß¤Î¤È¤­1\n
- * ...
- *
- * CACHE_DIR/encode(¥Ú¡¼¥¸Ì¾).rel
- * »²¾ÈÀè¥Ú¡¼¥¸Ì¾<tab>»²¾ÈÀè¥Ú¡¼¥¸Ì¾<tab>...
- */
+// ------------------------------------------------------------
+// DATA STRUCTURE of *.ref and *.rel files
+
+// CACHE_DIR/encode('foobar').ref
+// ---------------------------------
+// Page-name1<tab>0<\n>
+// Page-name2<tab>1<\n>
+// ...
+// Page-nameN<tab>0<\n>
+//
+//     0 = Added when link(s) to 'foobar' added clearly at this page
+//     1 = Added when the sentence 'foobar' found from the page
+//         by AutoLink feature
+
+// CACHE_DIR/encode('foobar').rel
+// ---------------------------------
+// Page-name1<tab>Page-name2<tab> ... <tab>Page-nameN
+//
+//     List of page-names linked from 'foobar'
+
+// ------------------------------------------------------------
+
 
-// ¥Ç¡¼¥¿¥Ù¡¼¥¹¤«¤é´ØÏ¢¥Ú¡¼¥¸¤òÆÀ¤ë
+// データベースから関連ページを得る
 function links_get_related_db($page)
 {
        $ref_name = CACHE_DIR . encode($page) . '.ref';
@@ -29,7 +44,7 @@ function links_get_related_db($page)
        return $times;
 }
 
-//¥Ú¡¼¥¸¤Î´ØÏ¢¤ò¹¹¿·¤¹¤ë
+//ページの関連を更新する
 function links_update($page)
 {
        if (PKWK_READONLY) return; // Do nothing
@@ -47,65 +62,69 @@ function links_update($page)
                if (isset($lines[0]))
                        $rel_old = explode("\t", rtrim($lines[0]));
        }
-       $rel_new  = array(); // »²¾ÈÀè
-       $rel_auto = array(); // ¥ª¡¼¥È¥ê¥ó¥¯¤·¤Æ¤¤¤ë»²¾ÈÀè
+       $rel_new  = array(); // 参照先
+       $rel_auto = array(); // オートリンクしている参照先
        $links    = links_get_objects($page, TRUE);
        foreach ($links as $_obj) {
                if (! isset($_obj->type) || $_obj->type != 'pagename' ||
-                   $_obj->name == $page || $_obj->name == '')
+                   $_obj->name === $page || $_obj->name == '')
                        continue;
 
-               if (is_a($_obj, 'Link_autolink')) { // ¹Ôµ·¤¬°­¤¤
+               if (is_a($_obj, 'Link_autolink')) { // 行儀が悪い
                        $rel_auto[] = $_obj->name;
+               } else if (is_a($_obj, 'Link_autoalias')) {
+                       $_alias = get_autoalias_right_link($_obj->name);
+                       if (is_pagename($_alias)) {
+                               $rel_auto[] = $_alias;
+                       }
                } else {
                        $rel_new[]  = $_obj->name;
                }
        }
        $rel_new = array_unique($rel_new);
        
-       // autolink¤·¤«¸þ¤¤¤Æ¤¤¤Ê¤¤¥Ú¡¼¥¸
+       // autolinkã\81\97ã\81\8bå\90\91ã\81\84ã\81¦ã\81\84ã\81ªã\81\84ã\83\9aã\83¼ã\82¸
        $rel_auto = array_diff(array_unique($rel_auto), $rel_new);
 
-       // Á´¤Æ¤Î»²¾ÈÀè¥Ú¡¼¥¸
+       // å\85¨ã\81¦ã\81®å\8f\82ç\85§å\85\88ã\83\9aã\83¼ã\82¸
        $rel_new = array_merge($rel_new, $rel_auto);
 
-       // .rel:$page¤¬»²¾È¤·¤Æ¤¤¤ë¥Ú¡¼¥¸¤Î°ìÍ÷
+       // .rel:$pageが参照しているページの一覧
        if ($time) {
-               // ¥Ú¡¼¥¸¤¬Â¸ºß¤·¤Æ¤¤¤ë
+               // ページが存在している
                if (! empty($rel_new)) {
                        $fp = fopen($rel_file, 'w')
-                               or die_message('cannot write ' . htmlspecialchars($rel_file));
+                               or die_message('cannot write ' . htmlsc($rel_file));
                        fputs($fp, join("\t", $rel_new));
                        fclose($fp);
                }
        }
 
-       // .ref:$_page¤ò»²¾È¤·¤Æ¤¤¤ë¥Ú¡¼¥¸¤Î°ìÍ÷
+       // .ref:$_pageを参照しているページの一覧
        links_add($page, array_diff($rel_new, $rel_old), $rel_auto);
        links_delete($page, array_diff($rel_old, $rel_new));
 
-       global $WikiName, $autolink, $nowikiname, $search_non_list;
+       global $WikiName, $autolink, $nowikiname;
 
-       // $page¤¬¿·µ¬ºîÀ®¤µ¤ì¤¿¥Ú¡¼¥¸¤Ç¡¢AutoLink¤ÎÂоݤȤʤêÆÀ¤ë¾ì¹ç
+       // $pageが新規作成されたページで、AutoLinkの対象となり得る場合
        if ($time && ! $rel_file_exist && $autolink
                && (preg_match("/^$WikiName$/", $page) ? $nowikiname : strlen($page) >= $autolink))
        {
-               // $page¤ò»²¾È¤·¤Æ¤¤¤½¤¦¤Ê¥Ú¡¼¥¸¤ò°ìÀƹ¹¿·¤¹¤ë(¤ª¤¤)
-               $search_non_list = 1;
-               $pages           = do_search($page, 'AND', TRUE);
+               // $pageを参照していそうなページを一斉更新する(おい)
+               $pages = links_do_search_page($page);
                foreach ($pages as $_page) {
-                       if ($_page != $page)
+                       if ($_page !== $page)
                                links_update($_page);
                }
        }
        $ref_file = CACHE_DIR . encode($page) . '.ref';
 
-       // $page¤¬ºï½ü¤µ¤ì¤¿¤È¤­¤Ë¡¢
+       // $pageが削除されたときに、
        if (! $time && file_exists($ref_file)) {
                foreach (file($ref_file) as $line) {
                        list($ref_page, $ref_auto) = explode("\t", rtrim($line));
 
-                       // $page¤òAutoLink¤Ç¤·¤«»²¾È¤·¤Æ¤¤¤Ê¤¤¥Ú¡¼¥¸¤ò°ìÀƹ¹¿·¤¹¤ë(¤ª¤¤¤ª¤¤)
+                       // $pageをAutoLinkでしか参照していないページを一斉更新する(おいおい)
                        if ($ref_auto)
                                links_delete($ref_page, array($page));
                }
@@ -127,45 +146,47 @@ function links_init()
        foreach (get_existfiles(CACHE_DIR, '.rel') as $cache)
                unlink($cache);
 
-       $pages = get_existpages();
-       $ref   = array(); // »²¾È¸µ
-       $ref_notauto = array();
-       foreach ($pages as $page) {
+       $ref   = array(); // 参照元
+       foreach (get_existpages() as $page) {
                if ($page == $whatsnew) continue;
 
-               $rel   = array(); // »²¾ÈÀè
+               $rel   = array(); // 参照先
                $links = links_get_objects($page);
                foreach ($links as $_obj) {
                        if (! isset($_obj->type) || $_obj->type != 'pagename' ||
-                           $_obj->name == $page || $_obj->name == '')
+                           $_obj->name == $page || $_obj->name == '') {
                                continue;
-
-                       $rel[] = $_obj->name;
+                       }
+                       $_name = $_obj->name;
+                       if (is_a($_obj, 'Link_autoalias')) {
+                               $_alias = get_autoalias_right_link($_name);
+                               if (! is_pagename($_alias)) {
+                                       continue;       // not PageName
+                               }
+                               $_name = $_alias;
+                       }
+                       $rel[] = $_name;
+                       if (! isset($ref[$_name][$page])) {
+                               $ref[$_name][$page] = 1;
+                       }
                        if (! is_a($_obj, 'Link_autolink')) {
-                               $ref_notauto[$_obj->name][$page] = TRUE;
+                               $ref[$_name][$page] = 0;
                        }
-                       $ref[$_obj->name][] = $page;
                }
                $rel = array_unique($rel);
                if (! empty($rel)) {
                        $fp = fopen(CACHE_DIR . encode($page) . '.rel', 'w')
-                               or die_message('cannot write ' . htmlspecialchars(CACHE_DIR . encode($page) . '.rel'));
+                               or die_message('cannot write ' . htmlsc(CACHE_DIR . encode($page) . '.rel'));
                        fputs($fp, join("\t", $rel));
                        fclose($fp);
                }
        }
 
        foreach ($ref as $page=>$arr) {
-               if (empty($arr)) continue;
-
-               $arr = array_unique($arr);
                $fp  = fopen(CACHE_DIR . encode($page) . '.ref', 'w')
-                       or die_message('cannot write ' . htmlspecialchars(CACHE_DIR . encode($page) . '.ref'));
-               foreach ($arr as $ref_page) {
-                       $ref_auto = (isset($ref_notauto[$page])
-                               && isset($ref_notauto[$page][$ref_page])) ? 0 : 1;
-                       fputs($fp, "$ref_page\t$ref_auto\n");
-               }
+                       or die_message('cannot write ' . htmlsc(CACHE_DIR . encode($page) . '.ref'));
+               foreach ($arr as $ref_page=>$ref_auto)
+                       fputs($fp, $ref_page . "\t" . $ref_auto . "\n");
                fclose($fp);
        }
 }
@@ -186,13 +207,18 @@ function links_add($page, $add, $rel_auto)
                        foreach (file($ref_file) as $line) {
                                list($ref_page, $ref_auto) = explode("\t", rtrim($line));
                                if (! $ref_auto) $all_auto = FALSE;
-                               if ($ref_page != $page) $ref .= $line;
+                               if ($ref_page !== $page) $ref .= $line;
                        }
                        unlink($ref_file);
                }
+               if (! $is_page) {
+                       if (! is_pagename_bytes_within_soft_limit($_page)) {
+                               continue;
+                       }
+               }
                if ($is_page || ! $all_auto) {
                        $fp = fopen($ref_file, 'w')
-                                or die_message('cannot write ' . htmlspecialchars($ref_file));
+                                or die_message('cannot write ' . htmlsc($ref_file));
                        fputs($fp, $ref);
                        fclose($fp);
                }
@@ -213,15 +239,15 @@ function links_delete($page, $del)
                $ref = '';
                foreach (file($ref_file) as $line) {
                        list($ref_page, $ref_auto) = explode("\t", rtrim($line));
-                       if ($ref_page != $page) {
+                       if ($ref_page !== $page) {
                                if (! $ref_auto) $all_auto = FALSE;
                                $ref .= $line;
                        }
                }
                unlink($ref_file);
-               if ($is_page && ! $all_auto && $ref != '') {
+               if (($is_page || ! $all_auto) && $ref != '') {
                        $fp = fopen($ref_file, 'w')
-                               or die_message('cannot write ' . htmlspecialchars($ref_file));
+                               or die_message('cannot write ' . htmlsc($ref_file));
                        fputs($fp, $ref);
                        fclose($fp);
                }
@@ -233,8 +259,39 @@ function & links_get_objects($page, $refresh = FALSE)
        static $obj;
 
        if (! isset($obj) || $refresh)
-               $obj = & new InlineConverter(NULL, array('note'));
+               $obj = new InlineConverter(NULL, array('note'));
+
+       $result = $obj->get_objects(join('', preg_grep('/^(?!\/\/|\s)./', get_source($page))), $page);
+       return $result;
+}
+
+/**
+ * Search function for AutoLink updating
+ *
+ * @param $word page name
+ * @return list of page name that contains $word
+ */
+function links_do_search_page($word)
+{
+       global $whatsnew;
 
-       return $obj->get_objects(join('', preg_grep('/^(?!\/\/|\s)./', get_source($page))), $page);
+       $keys = get_search_words(preg_split('/\s+/', $word, -1, PREG_SPLIT_NO_EMPTY));
+       foreach ($keys as $key=>$value)
+               $keys[$key] = '/' . $value . '/S';
+       $pages = get_existpages();
+       $pages = array_flip($pages);
+       unset($pages[$whatsnew]);
+       $count = count($pages);
+       foreach (array_keys($pages) as $page) {
+               $b_match = FALSE;
+               // Search for page contents
+               foreach ($keys as $key) {
+                       $body = get_source($page, TRUE, TRUE, TRUE);
+                       $b_match = preg_match($key, remove_author_header($body));
+                       if (! $b_match) break; // OR
+               }
+               if ($b_match) continue;
+               unset($pages[$page]); // Miss
+       }
+       return array_keys($pages);
 }
-?>