From 9ddf1874865c5f42ceb3eb24f2cb7646687d385c Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sat, 16 Jan 2016 18:31:45 +0000 Subject: [PATCH] changed markdown/showdown to support codepot-aware anchors --- codepot/etc/codepot.ini.in | 6 ++ codepot/src/codepot/controllers/file.php | 10 +-- codepot/src/codepot/controllers/issue.php | 10 +-- codepot/src/codepot/controllers/wiki.php | 28 +++---- .../src/codepot/helpers/codepot_helper.php | 4 +- .../codepot/language/english/wiki_lang.php | 2 +- .../src/codepot/language/korean/wiki_lang.php | 2 +- codepot/src/codepot/libraries/wikihelper.php | 81 +++++++++++-------- codepot/src/config.php.in | 6 +- codepot/src/js/showdown.js | 31 ++++++- 10 files changed, 111 insertions(+), 69 deletions(-) diff --git a/codepot/etc/codepot.ini.in b/codepot/etc/codepot.ini.in index 225ffbd8..0e6210d2 100644 --- a/codepot/etc/codepot.ini.in +++ b/codepot/etc/codepot.ini.in @@ -212,6 +212,12 @@ usericon_dir = "@DEPOTDIR@/usericons" ;------------------------------------------------------------------------------ log_threshold = 0 +;------------------------------------------------------------------------------ +; When yes, open a wiki creation page if a non-existent wiki pages is +; requested +;------------------------------------------------------------------------------ +create_missing_wiki = "no" + ;------------------------------------------------------------------------------ ; When yes, a project member can delete a non-empty project containing ; wiki pages, file uploads, etc. An empty project can be deleted any time diff --git a/codepot/src/codepot/controllers/file.php b/codepot/src/codepot/controllers/file.php index 9fc998b5..aaf1cad0 100644 --- a/codepot/src/codepot/controllers/file.php +++ b/codepot/src/codepot/controllers/file.php @@ -302,11 +302,10 @@ class File extends Controller break; } - if (strpos($_FILES[$fid]['name'], ':') !== FALSE || - strpos($_FILES[$fid]['name'], '/') !== FALSE) + if (strpbrk($_FILES[$fid]['name'], CODEPOT_DISALLOWED_LETTERS_IN_FILENAME) !== FALSE) { // prevents these letters for wiki creole - $status = "error - colon or slash not allowed - {$_FILES[$fid]['name']}"; + $status = "error - disallowed character contained - {$_FILES[$fid]['name']}"; break; } @@ -386,11 +385,10 @@ class File extends Controller break; } - if (strpos($_FILES[$fid]['name'], ':') !== FALSE || - strpos($_FILES[$fid]['name'], '/') !== FALSE) + if (strpbrk($_FILES[$fid]['name'], CODEPOT_DISALLOWED_LETTERS_IN_FILENAME) !== FALSE) { // prevents these letters for wiki creole - $status = "error - colon or slash not allowed - {$_FILES[$fid]['name']}"; + $status = "error - disallowed character contained - {$_FILES[$fid]['name']}"; break; } diff --git a/codepot/src/codepot/controllers/issue.php b/codepot/src/codepot/controllers/issue.php index 1788901d..1f09a8a0 100644 --- a/codepot/src/codepot/controllers/issue.php +++ b/codepot/src/codepot/controllers/issue.php @@ -335,11 +335,10 @@ class Issue extends Controller $d = $this->input->post("issue_new_file_desc_{$i}"); if ($d === FALSE || ($d = trim($d)) == '') $d = ''; // description optional - if (strpos($_FILES[$fid]['name'], ':') !== FALSE || - strpos($_FILES[$fid]['name'], '/') !== FALSE) + if (strpbrk($_FILES[$fid]['name'], CODEPOT_DISALLOWED_LETTERS_IN_FILENAME) !== FALSE) { // prevents these letters for wiki creole - $status = "error - colon or slash not allowed - {$_FILES[$fid]['name']}"; + $status = "error - disallowed character contained - {$_FILES[$fid]['name']}"; break; } @@ -545,11 +544,10 @@ class Issue extends Controller $d = $this->input->post("issue_add_file_desc_{$i}"); if ($d === FALSE || ($d = trim($d)) == '') $d = ''; - if (strpos($_FILES[$fid]['name'], ':') !== FALSE || - strpos($_FILES[$fid]['name'], '/') !== FALSE) + if (strpbrk($_FILES[$fid]['name'], CODEPOT_DISALLOWED_LETTERS_IN_FILENAME) !== FALSE) { // prevents these letters for wiki creole - $status = "error - colon or slash not allowed - {$_FILES[$fid]['name']}"; + $status = "error - disallowed character contained - {$_FILES[$fid]['name']}"; break; } diff --git a/codepot/src/codepot/controllers/wiki.php b/codepot/src/codepot/controllers/wiki.php index 783554ad..8a63b291 100644 --- a/codepot/src/codepot/controllers/wiki.php +++ b/codepot/src/codepot/controllers/wiki.php @@ -121,7 +121,7 @@ class Wiki extends Controller } else if ($link !== NULL) { - // redirect to a special link like __WIKI__:projectid:wikiname + // redirect to a special link like __WIKI__:projectid:wikiname, #R1234, #I999 redirect ($link); } else @@ -151,8 +151,7 @@ class Wiki extends Controller else { $data['project'] = $project; - $data['message'] = sprintf ( - $this->lang->line('WIKI_MSG_NO_SUCH_PAGE'), $name); + $data['message'] = $this->lang->line('WIKI_MSG_NO_SUCH_PAGE') . " - {$name}"; $this->load->view ($this->VIEW_ERROR, $data); } } @@ -168,7 +167,7 @@ class Wiki extends Controller function show ($projectid = '' , $name = '') { - $this->_show_wiki ($projectid, $name, TRUE); + $this->_show_wiki ($projectid, $name, CODEPOT_CREATE_MISSING_WIKI); } function show_r ($projectid = '' , $name = '') @@ -290,9 +289,8 @@ class Wiki extends Controller } $wiki->attachments = $atts; - // disallow : # [ ] | - if (strpbrk ($wiki->name, ':#[]|') !== FALSE || - (!is_null($new_wiki_name) && strpbrk ($new_wiki_name, ':#[]|') !== FALSE)) + if (strpbrk ($wiki->name, CODEPOT_DISALLOWED_LETTERS_IN_WIKINAME) !== FALSE || + (!is_null($new_wiki_name) && strpbrk ($new_wiki_name, CODEPOT_DISALLOWED_LETTERS_IN_WIKINAME) !== FALSE)) { $data['message'] = $this->lang->line('WIKI_MSG_NAME_DISALLOWED_CHARS'); $data['wiki'] = $wiki; @@ -390,9 +388,7 @@ class Wiki extends Controller } else if ($wiki == NULL) { - $data['message'] = - $this->lang->line('WIKI_MSG_NO_SUCH_PAGE') . - " - {$name}"; + $data['message'] = $this->lang->line('WIKI_MSG_NO_SUCH_PAGE') . " - {$name}"; $this->load->view ($this->VIEW_ERROR, $data); } else @@ -540,8 +536,7 @@ class Wiki extends Controller } else if ($wiki === NULL) { - $data['message'] = sprintf ( - $this->lang->line('WIKI_MSG_NO_SUCH_PAGE'), $name); + $data['message'] = $this->lang->line('WIKI_MSG_NO_SUCH_PAGE') . " - {$name}"; $this->load->view ($this->VIEW_ERROR, $data); } else @@ -570,7 +565,7 @@ class Wiki extends Controller $_FILES[$field_name]['name'] != '') { $fname = $_FILES[$field_name]['name']; - if (strpos ($fname, ':') !== FALSE) + if (strpbrk($fname, CODEPOT_DISALLOWED_LETTERS_IN_FILENAME) !== FALSE) { while ($attno > 0) @unlink ($attachments[$attno--]['fullencpath']); @@ -918,7 +913,7 @@ class Wiki extends Controller { $status = 'error - empty name'; } - else if (strpbrk ($wiki->name, ':#[]|') !== FALSE) + else if (strpbrk ($wiki->name, CODEPOT_DISALLOWED_LETTERS_IN_WIKINAME) !== FALSE) { $status = 'error - disallowed characters in name'; } @@ -941,11 +936,10 @@ class Wiki extends Controller $fid = "wiki_file_{$i}"; if (array_key_exists($fid, $_FILES) && $_FILES[$fid]['name'] != '') { - if (strpos($_FILES[$fid]['name'], ':') !== FALSE || - strpos($_FILES[$fid]['name'], '/') !== FALSE) + if (strpbrk($_FILES[$fid]['name'], CODEPOT_DISALLOWED_LETTERS_IN_FILENAME) !== FALSE) { // prevents these letters for wiki creole - $status = "error - colon or slash not allowed - {$_FILES[$fid]['name']}"; + $status = "error - disallowed character contained - {$_FILES[$fid]['name']}"; break; } diff --git a/codepot/src/codepot/helpers/codepot_helper.php b/codepot/src/codepot/helpers/codepot_helper.php index 8fd946e5..5943cb56 100644 --- a/codepot/src/codepot/helpers/codepot_helper.php +++ b/codepot/src/codepot/helpers/codepot_helper.php @@ -164,10 +164,10 @@ if ( !function_exists ('codepot_delete_files')) { // Trim the trailing slash $path = rtrim($path, DIRECTORY_SEPARATOR); - + if ( ! $current_dir = @opendir($path)) return; - + while(FALSE !== ($filename = @readdir($current_dir))) { if ($filename != "." && $filename != "..") diff --git a/codepot/src/codepot/language/english/wiki_lang.php b/codepot/src/codepot/language/english/wiki_lang.php index a7007382..3f120b7f 100644 --- a/codepot/src/codepot/language/english/wiki_lang.php +++ b/codepot/src/codepot/language/english/wiki_lang.php @@ -6,6 +6,6 @@ $lang['WIKI_MORE_NEW_ATTACHMENTS'] = 'Add more'; $lang['WIKI_MSG_ATTACHMENT_NAME_NO_COLON'] = 'Attachment name containing a colon'; $lang['WIKI_MSG_NAME_DISALLOWED_CHARS'] = 'Wiki name contains disallowed characters'; $lang['WIKI_MSG_NO_PAGES_AVAILABLE'] = 'No wiki pages available'; -$lang['WIKI_MSG_NO_SUCH_PAGE'] = 'No such wiki page - %s'; +$lang['WIKI_MSG_NO_SUCH_PAGE'] = 'No such wiki page'; $lang['WIKI_MSG_RESERVED_WIKI_NAME'] = 'Wiki name containing a reserved word - %s'; ?> diff --git a/codepot/src/codepot/language/korean/wiki_lang.php b/codepot/src/codepot/language/korean/wiki_lang.php index 036ec246..9c35dd68 100644 --- a/codepot/src/codepot/language/korean/wiki_lang.php +++ b/codepot/src/codepot/language/korean/wiki_lang.php @@ -6,6 +6,6 @@ $lang['WIKI_MORE_NEW_ATTACHMENTS'] = '첨부파일 추가'; $lang['WIKI_MSG_ATTACHMENT_NAME_NO_COLON'] = '첨부파일이름에 콜론기호를 포함할 수 없습니다'; $lang['WIKI_MSG_NAME_DISALLOWED_CHARS'] = '위키이름에 허용되지 않는 문자가 포함되어 있습니다'; $lang['WIKI_MSG_NO_PAGES_AVAILABLE'] = '사용할 수 있는 위키 페이지가 없습니다'; -$lang['WIKI_MSG_NO_SUCH_PAGE'] = '위키 페이지를 찾을수 없습니다 - %s'; +$lang['WIKI_MSG_NO_SUCH_PAGE'] = '위키 페이지를 찾을수 없습니다'; $lang['WIKI_MSG_RESERVED_WIKI_NAME'] = '%s은(는) 사용할 수 없는 위키이름입니다'; ?> diff --git a/codepot/src/codepot/libraries/wikihelper.php b/codepot/src/codepot/libraries/wikihelper.php index 81a8e545..a4fc9116 100644 --- a/codepot/src/codepot/libraries/wikihelper.php +++ b/codepot/src/codepot/libraries/wikihelper.php @@ -2,6 +2,14 @@ class WikiHelper { + private static $double_hash_table = array ( + '##P' => '__PROJECT__', + '##W' => '__WIKI__', + '##I' => '__ISSUE__', + '##C' => '__CODE__', + '##F' => '__FILE__' + ); + function WikiHelper () { } @@ -35,8 +43,33 @@ class WikiHelper $link = "file/show/{$projectid}/{$file_name}"; return $link; } + else if (preg_match ('/^#P(.+)$/', $name, $matches) == 1) + { + // #Pprojectid -> translate it to a project home + $project_name = $matches[1]; // no AsciiToHex + $link = "project/home/{$project_name}"; + return $link; + } + else if (preg_match ('/^#W(.+)$/', $name, $matches) == 1) + { + // #Pprojectid -> translate it to a wiki name + $wiki_name = $converter->AsciiToHex ($matches[1]); + $link = "wiki/show/{$projectid}/{$wiki_name}"; + return $link; + } - if ($this->_is_reserved ($name, TRUE)) + $r = $this->double_hash_to_reserved($name); + if ($r !== FALSE) + { + $name = $r; + $reserved = TRUE; + } + else + { + $reserved = $this->_is_reserved ($name, TRUE); + } + + if ($reserved) { $ex0 = $this->_trans_reserved ($name); @@ -56,6 +89,8 @@ class WikiHelper { $ex = explode (':', $name); $cnt = count($ex); + if ($cnt >= 1 && ($r = $this->double_hash_to_reserved($ex[0])) !== FALSE) $ex[0] = $r; + if ($cnt == 2) { if ($ex[0] == '__LOCALURL__') @@ -67,14 +102,6 @@ class WikiHelper $ex0 = $this->_trans_reserved ($ex[0]); $ex1 = ($ex[1] == '')? $projectid: $ex[1]; - //redirect ("{$ex0}/home/{$ex1}"); - - //$link->type = $ex0; - //$link->target = 'home'; - //$link->projectid = $ex1; - //if ($link->projectid == NULL) return FALSE; - //$link->extra = NULL; - if ($ex1 == NULL) return FALSE; $link = "{$ex0}/home/{$ex1}"; return $link; @@ -88,13 +115,6 @@ class WikiHelper $ex0 = $this->_trans_reserved ($ex[0]); $ex1 = ($ex[1] == '')? $projectid: $ex[1]; $ex2 = $converter->AsciiToHex ($ex[2]); - //redirect ("{$ex0}/show/{$ex1}/{$ex2}"); - - //$link->type = $ex0; - //$link->target = 'show'; - //$link->projectid = $ex1; - //if ($link->projectid == NULL) return FALSE; - //$link->extra = $ex2; if ($ex1 == NULL) return FALSE; $link = "{$ex0}/show/{$ex1}/{$ex2}"; @@ -110,13 +130,9 @@ class WikiHelper if ($ex[2] == 'file' || $ex[2] == 'history' || $ex[2] == 'blame' || $ex[2] == 'diff') { + // __CODE__|project001|file|file001.txt + $ex3 = $converter->AsciiToHex ($ex[3]); - //redirect ("{$ex0}/{$ex[2]}/{$ex1}/{$ex3}"); - //$link->type = $ex0; - //$link->target = $ex[2]; - //$link->projectid = $ex1; - //if ($link->projectid == NULL) return FALSE; - //$link->extra = $ex3; if ($ex1 == NULL) return FALSE; $link = "{$ex0}/{$ex[2]}/{$ex1}/{$ex3}"; @@ -137,11 +153,6 @@ class WikiHelper { // __WIKI__:projectid:wikiname:attachment - //$link->type = $this->_trans_reserved ($ex[0]); - //$link->target = 'attachment0'; - //$link->projectid = ($ex[1] == '')? $projectid: $ex[1]; - //$link->extra = $converter->AsciiToHex ("{$link->projectid}:{$ex[2]}:{$ex[3]}"); - $ex0 = $this->_trans_reserved ($ex[0]); $ex1 = ($ex[1] == '')? $projectid: $ex[1]; $extra = $converter->AsciiToHex ("{$link->projectid}:{$ex[2]}:{$ex[3]}"); @@ -175,12 +186,18 @@ class WikiHelper } else { - return substr ($name, 0, 11) == '__PROJECT__' || - substr ($name, 0, 8) == '__WIKI__' || - substr ($name, 0, 8) == '__FILE__' || - substr ($name, 0, 8) == '__CODE__' || - substr ($name, 0, 9) == '__ISSUE__'; + return substr($name, 0, 11) == '__PROJECT__' || + substr($name, 0, 8) == '__WIKI__' || + substr($name, 0, 8) == '__FILE__' || + substr($name, 0, 8) == '__CODE__' || + substr($name, 0, 9) == '__ISSUE__'; } } + + private function double_hash_to_reserved ($name) + { + if (array_key_exists ($name, self::$double_hash_table)) return self::$double_hash_table[$name]; + return FALSE; + } } ?> diff --git a/codepot/src/config.php.in b/codepot/src/config.php.in index 474a8617..c284cd76 100644 --- a/codepot/src/config.php.in +++ b/codepot/src/config.php.in @@ -21,6 +21,9 @@ function load_ini ($file) if (!is_array($cfg)) $cfg = array (); $xcfgs = array ( + array ('disallowed_letters_in_filename', 'string', ':#|[]$*/'), + array ('disallowed_letters_in_wikiname', 'string', ':#|[]$*'), + array ('default_site_language', 'string', 'english'), array ('default_site_name', 'string', '@PACKAGE@'), @@ -79,6 +82,7 @@ function load_ini ($file) array ('log_threshold', 'integer', 0), + array ('create_missing_wiki', 'boolean', FALSE), array ('force_project_delete', 'boolean', FALSE), array ('allow_set_time_limit', 'boolean', FALSE), array ('signin_for_code_search', 'boolean', TRUE), @@ -102,7 +106,7 @@ function load_ini ($file) array ('svn_restriction_allowed_subdir_depth_max', 'integer', 0), // this item is used by the codepot-user command. - array ('codepot_user_executor', 'string', 'root') + array ('codepot_user_executor', 'string', 'root'), ); foreach ($xcfgs as $x) diff --git a/codepot/src/js/showdown.js b/codepot/src/js/showdown.js index 4ef154dc..357fae75 100644 --- a/codepot/src/js/showdown.js +++ b/codepot/src/js/showdown.js @@ -72,7 +72,12 @@ function getDefaultOpts(simple) { default: false, describe: 'Prevents weird effects in live previews due to incomplete input', type: 'boolean' - } + }, + + // codepot + codepotImageBase: '', + codepotLinkBase: '' + // end codepot }; if (simple === false) { return JSON.parse(JSON.stringify(defaultOptions)); @@ -1121,6 +1126,20 @@ showdown.subParser('anchors', function (text, options, globals) { } url = showdown.helper.escapeCharacters(url, '*_', false); + + // codepot + var front2 = url.substr(0, 2); + var front3 = url.substr(0, 3); + + if (front2 == '#P' || front2 == '#I' || front2 == '#C' || front2 == '#R' || front2 == '#F' || front2 == '#W') + { + url = options.codepotLinkBase + codepot_string_to_hex(url); + } + else if (front3 == '##P' || front3 == '##W' || front3 == '##I' || front3 == '##C' || front3 == '##F') + { + url = options.codepotLinkBase + codepot_string_to_hex(url); + } + // end codepot var result = '' + codeblock + end + ''; return showdown.subParser('hashBlock')(codeblock, options, globals); @@ -2510,11 +2530,12 @@ if (typeof module !== 'undefined' && module.exports) { //# sourceMappingURL=showdown.js.map +// codepot function showdown_render_wiki_with_input_text (input_text, outputid, linkbase, imgbase, raw) { var sd = new showdown.Converter ({ omitExtraWLInCodeBlocks: false, - noHeaderId: true, + noHeaderId: false, prefixHeaderId: false, parseImgDimensions: true, headerLevelStart: 1, @@ -2524,7 +2545,10 @@ function showdown_render_wiki_with_input_text (input_text, outputid, linkbase, i tables: true, tablesHeaderId: false, ghCodeBlocks: true, - tasklists: true + tasklists: true, + + codepotLinkBase: linkbase, + codepotImgBase: imgbase }); function decodeEntities(str) @@ -2547,3 +2571,4 @@ function showdown_render_wiki (inputid, outputid, linkbase, imgbase, raw) var input = document.getElementById(inputid); return showdown_render_wiki_with_input_text (input.innerHTML, outputid, linkbase, imgbase, raw); } +// end codepot