# HG changeset patch # User Dan # Date 1234819045 18000 # Node ID 7152ca0a0ce9e03f437af279a1ffa06fe9c4a96c # Parent 45e887f2328217874c219c92ad93d2280ae31d5f Major redesign of rendering pipeline that separates pages saved with MCE from pages saved with the plaintext editor (full description in long commit message) - Pages are now stored with an extra metadata field called page_format which is "wikitext" or "xhtml" - New $flags parameter + RENDER_* constants added that control RenderMan::render() behavior - Several other changes: * Added a sprite API for Javascript and made editor use sprites when possible * Removed a number of config options from the default install schema, replaced with second parameter to getConfig() calls * MessageBox in editor mostly replaced with miniPrompt * A few bugfixes related to password changes (registration didn't even work) * Rewrote the bitfield compression algorithm used to serialize allowed MIME types * Fixed some typos in language files and strings * Fixed a Text_Wiki bug in Heading parser diff -r 45e887f23282 -r 7152ca0a0ce9 ajax.php --- a/ajax.php Mon Feb 16 16:04:54 2009 -0500 +++ b/ajax.php Mon Feb 16 16:17:25 2009 -0500 @@ -37,7 +37,7 @@ if ( $src = $page->fetch_source() ) { $allowed = true; - $q = $db->sql_query('SELECT author, time_id, page_text, edit_summary FROM ' . table_prefix . 'logs WHERE log_type = \'page\' AND action = \'edit\' + $q = $db->sql_query('SELECT author, time_id, page_text, edit_summary, page_format FROM ' . table_prefix . 'logs WHERE log_type = \'page\' AND action = \'edit\' AND page_id = \'' . $db->escape($paths->page_id) . '\' AND namespace = \'' . $db->escape($paths->namespace) . '\' AND is_draft = 1;'); @@ -76,6 +76,21 @@ 'have_draft' => false ); + $return['page_format'] = $paths->cpage['page_format']; + if ( $return['page_format'] == 'xhtml' ) + { + // gently process headings to make tinymce format them correctly + if ( preg_match_all('/^ *?(={1,6}) *(.+?) *\\1 *$/m', $return['src'], $matches) ) + { + foreach ( $matches[0] as $i => $match ) + { + $hi = strlen($matches[1][$i]); + $heading = "{$matches[2][$i]}"; + $return['src'] = str_replace_once($match, $heading, $return['src']); + } + } + } + if ( $have_draft ) { $row =& $draft_row; @@ -86,6 +101,7 @@ { $return['src'] = $row['page_text']; $return['edit_summary'] = $row['edit_summary']; + $return['page_format'] = $row['page_format']; } } @@ -212,26 +228,37 @@ else { $src = RenderMan::preprocess_text($request['src'], false, false); - - // Save the draft - $q = $db->sql_query('INSERT INTO ' . table_prefix . 'logs ( log_type, action, page_id, namespace, author, edit_summary, page_text, is_draft, time_id ) - VALUES ( - \'page\', - \'edit\', - \'' . $db->escape($paths->page_id) . '\', - \'' . $db->escape($paths->namespace) . '\', - \'' . $db->escape($session->username) . '\', - \'' . $db->escape($request['summary']) . '\', - \'' . $db->escape($src) . '\', - 1, - ' . time() . ' - );'); - - // Done! - $return = array( - 'mode' => 'success', - 'is_draft' => true + $draft_format = $request['format']; + if ( !in_array($draft_format, array('xhtml', 'wikitext')) ) + { + $return = array( + 'mode' => 'error', + 'error' => 'invalid_format' ); + } + else + { + // Save the draft + $q = $db->sql_query('INSERT INTO ' . table_prefix . 'logs ( log_type, action, page_id, namespace, author, edit_summary, page_text, is_draft, time_id, page_format ) + VALUES ( + \'page\', + \'edit\', + \'' . $db->escape($paths->page_id) . '\', + \'' . $db->escape($paths->namespace) . '\', + \'' . $db->escape($session->username) . '\', + \'' . $db->escape($request['summary']) . '\', + \'' . $db->escape($src) . '\', + 1, + ' . time() . ', + \'' . $draft_format . '\' + );'); + + // Done! + $return = array( + 'mode' => 'success', + 'is_draft' => true + ); + } } } } @@ -280,7 +307,7 @@ // Verification complete. Start the PageProcessor and let it do the dirty work for us. $page = new PageProcessor($paths->page_id, $paths->namespace); - if ( $page->update_page($request['src'], $request['summary'], ( $request['minor_edit'] == 1 )) ) + if ( $page->update_page($request['src'], $request['summary'], ( $request['minor_edit'] == 1 ), $request['format']) ) { $return = array( 'mode' => 'success', @@ -429,52 +456,66 @@ case "fillusername": break; case "fillpagename": - $name = (isset($_GET['name'])) ? $_GET['name'] : false; - if(!$name) die('userlist = new Array(); namelist = new Array(); errorstring=\'Invalid URI\''); - $nd = RenderMan::strToPageID($name); - $c = 0; - $u = Array(); - $n = Array(); - - $name = sanitize_page_id($name); - $name = str_replace('_', ' ', $name); - - foreach ( $paths->pages as $i => $_ ) - { - if( ( - preg_match('#'.preg_quote($name).'(.*)#i', $paths->pages[$i]['name']) || - preg_match('#'.preg_quote($name).'(.*)#i', $paths->pages[$i]['urlname']) || - preg_match('#'.preg_quote($name).'(.*)#i', $paths->pages[$i]['urlname_nons']) || - preg_match('#'.preg_quote(str_replace(' ', '_', $name)).'(.*)#i', $paths->pages[$i]['name']) || - preg_match('#'.preg_quote(str_replace(' ', '_', $name)).'(.*)#i', $paths->pages[$i]['urlname']) || - preg_match('#'.preg_quote(str_replace(' ', '_', $name)).'(.*)#i', $paths->pages[$i]['urlname_nons']) - ) && - ( ( $nd[1] != 'Article' && $paths->pages[$i]['namespace'] == $nd[1] ) || $nd[1] == 'Article' ) - && $paths->pages[$i]['visible'] - ) - { - $c++; - $u[] = $paths->pages[$i]['name']; - $n[] = $paths->pages[$i]['urlname']; - } - } - if($c > 0) - { - echo 'userlist = new Array(); namelist = new Array(); errorstring = false; '."\n"; - for($i=0;$iinit_vars(); echo PageUtils::genPreview($_POST['text']); break; + case "transform": + header('Content-type: text/javascript'); + if ( !isset($_GET['to']) ) + { + echo enano_json_encode(array( + 'mode' => 'error', + 'error' => '"to" not specified' + )); + break; + } + if ( !isset($_POST['text']) ) + { + echo enano_json_encode(array( + 'mode' => 'error', + 'error' => '"text" not specified (must be on POST)' + )); + break; + } + switch($_GET['to']) + { + case 'xhtml': + $result = RenderMan::render($_POST['text'], RENDER_WIKI_DEFAULT | RENDER_BLOCKONLY); + break; + case 'wikitext': + $result = RenderMan::reverse_render($_POST['text']); + break; + default: + $text =& $_POST['text']; + $result = false; + $code = $plugins->setHook('ajax_transform'); + foreach ( $code as $cmd ) + { + eval($cmd); + } + if ( !$result ) + { + echo enano_json_encode(array( + 'mode' => 'error', + 'error' => 'Invalid target format' + )); + break; + } + break; + } + + // mostly for debugging, but I suppose this could be useful elsewhere. + if ( isset($_POST['plaintext']) ) + die($result); + + echo enano_json_encode(array( + 'mode' => 'transformed_text', + 'text' => $result + )); + break; case "pagediff": require_once(ENANO_ROOT.'/includes/pageutils.php'); $id1 = ( isset($_GET['diff1']) ) ? (int)$_GET['diff1'] : false; diff -r 45e887f23282 -r 7152ca0a0ce9 images/editor/sprite.png Binary file images/editor/sprite.png has changed diff -r 45e887f23282 -r 7152ca0a0ce9 images/icons/abort.png Binary file images/icons/abort.png has changed diff -r 45e887f23282 -r 7152ca0a0ce9 images/icons/abortretryignore-sprite.png Binary file images/icons/abortretryignore-sprite.png has changed diff -r 45e887f23282 -r 7152ca0a0ce9 images/icons/fmt_sprite.png Binary file images/icons/fmt_sprite.png has changed diff -r 45e887f23282 -r 7152ca0a0ce9 images/icons/fmt_wikitext.png Binary file images/icons/fmt_wikitext.png has changed diff -r 45e887f23282 -r 7152ca0a0ce9 images/icons/fmt_xhtml.png Binary file images/icons/fmt_xhtml.png has changed diff -r 45e887f23282 -r 7152ca0a0ce9 images/icons/ignore.png Binary file images/icons/ignore.png has changed diff -r 45e887f23282 -r 7152ca0a0ce9 images/icons/retry.png Binary file images/icons/retry.png has changed diff -r 45e887f23282 -r 7152ca0a0ce9 includes/clientside/css/enano-shared.css --- a/includes/clientside/css/enano-shared.css Mon Feb 16 16:04:54 2009 -0500 +++ b/includes/clientside/css/enano-shared.css Mon Feb 16 16:17:25 2009 -0500 @@ -784,7 +784,7 @@ .abutton_red { color: #880000 !important; } .abutton_red:hover { background-color: #880000 !important; } -.abutton_img { +.abutton_img, .abutton.icon { background-image: url('../../../images/mini-error.png'); background-position: 4px center; background-repeat: no-repeat; diff -r 45e887f23282 -r 7152ca0a0ce9 includes/clientside/static/dynano.js --- a/includes/clientside/static/dynano.js Mon Feb 16 16:04:54 2009 -0500 +++ b/includes/clientside/static/dynano.js Mon Feb 16 16:17:25 2009 -0500 @@ -36,6 +36,7 @@ this.getContent = DN_mceFetchContent; this.setContent = DN_mceSetContent; this.makeSwitchable = DN_makeSwitchableTA; + this.isMCE = DN_isMCE; } } function __DNObjGetHeight(o) { @@ -154,6 +155,11 @@ return this; } +function DN_isMCE() +{ + return ( this.object.dnIsMCE == 'yes' ); +} + function DN_mceFetchContent() { if ( this.object.name ) @@ -274,24 +280,56 @@ } } -// A basic Wikitext to XHTML converter function DN_WikitextToXHTML(text) { - text = text.replace(/^===[\s]*(.+?)[\s]*===$/g, '

$1

'); - text = text.replace(/'''(.+?)'''/g, '$1'); - text = text.replace(/''(.+?)''/g, '$1'); - text = text.replace(/\[(http|ftp|irc|mailto):([^ \]])+ ([^\]]+?)\]/g, '$4'); - return text; + return DN_AjaxGetTransformedText(text, 'xhtml'); +} + +function DN_XHTMLToWikitext(text) +{ + return DN_AjaxGetTransformedText(text, 'wikitext'); } -// Inverse of the previous function -function DN_XHTMLToWikitext(text) +// AJAX to the server to transform text +function DN_AjaxGetTransformedText(text, to) { - text = text.replace(/

(.+?)<\/h3>/g, '=== $1 ==='); - text = text.replace(/<(b|strong)>(.+?)<\/(b|strong)>/g, "'''$2'''"); - text = text.replace(/<(i|em)>(.+?)<\/(i|em)>/g, "''$2''"); - text = text.replace(/(.+?)<\/a>/g, '[$1 $2]'); - text = text.replace(/<\/?p>/g, ''); + // get an XHR instance + var ajax = ajaxMakeXHR(); + + var uri = stdAjaxPrefix + '&_mode=transform&to=' + to; + var parms = 'text=' + ajaxEscape(text); + try + { + ajax.open('POST', uri, false); + ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + // Setting Content-length in Safari triggers a warning + if ( !is_Safari ) + { + ajax.setRequestHeader("Content-length", parms.length); + } + ajax.send(parms); + // async request, so if status != 200 at this point then we're screwed + if ( ajax.readyState == 4 && ajax.status == 200 ) + { + var response = String(ajax.responseText + ''); + if ( !check_json_response(response) ) + { + handle_invalid_json(response); + return text; + } + response = parseJSON(response); + if ( response.mode == 'error' ) + { + alert(response.error); + return text; + } + return response.text; + } + } + catch(e) + { + console.warn('DN_AjaxGetTransformedText: XHR failed'); + } return text; } diff -r 45e887f23282 -r 7152ca0a0ce9 includes/clientside/static/editor.js --- a/includes/clientside/static/editor.js Mon Feb 16 16:04:54 2009 -0500 +++ b/includes/clientside/static/editor.js Mon Feb 16 16:17:25 2009 -0500 @@ -5,6 +5,7 @@ var AutosaveTimeoutObj = null; var editor_img_path = cdnPath + '/images/editor'; var editor_save_lock = false; +var editor_wikitext_transform_enable = true; window.ajaxEditor = function(revid) { @@ -12,7 +13,7 @@ return true; if ( editor_open ) return true; - load_component(['l10n', 'template-compiler', 'messagebox']); + load_component(['l10n', 'template-compiler', 'messagebox', 'fadefilter', 'flyin']); selectButtonMinor('edit'); selectButtonMajor('article'); setAjaxLoading(); @@ -124,29 +125,34 @@ var span_mce = document.createElement('span'); span_wiki.id = 'enano_edit_btn_pt'; span_mce.id = 'enano_edit_btn_mce'; - if ( readCookie('enano_editor_mode') == 'tinymce' ) + + // to-wikitext button + var a = document.createElement('a'); + a.href = '#'; + a.className = 'abutton image abutton_green'; + a.appendChild(gen_sprite(scriptPath + '/images/editor/sprite.png', 16, 16, 0, 96)); + a.appendChild(document.createTextNode(' ' + $lang.get('editor_btn_wikitext'))); + span_wiki.appendChild(a); + toggler.appendChild(span_wiki); + + // to-HTML button + var a = document.createElement('a'); + a.href = '#'; + a.className = 'abutton image abutton_blue'; + a.appendChild(gen_sprite(scriptPath + '/images/editor/sprite.png', 16, 16, 0, 112)); + a.appendChild(document.createTextNode(' ' + $lang.get('editor_btn_graphical'))); + span_mce.appendChild(a); + toggler.appendChild(span_mce); + + if ( response.page_format == 'xhtml' ) { // Current selection is TinyMCE - make span_wiki have the link and span_mce be plaintext - var a = document.createElement('a'); - a.href = '#'; - a.appendChild(document.createTextNode($lang.get('editor_btn_wikitext'))); - span_wiki.appendChild(a); - toggler.appendChild(span_wiki); - toggler.appendChild(document.createTextNode(' | ')); - span_mce.appendChild(document.createTextNode($lang.get('editor_btn_graphical'))); - toggler.appendChild(span_mce); + span_mce.style.display = 'none'; } else { // Current selection is wikitext - set span_wiki to plaintext and span_mce to link - span_wiki.appendChild(document.createTextNode($lang.get('editor_btn_wikitext'))); - toggler.appendChild(span_wiki); - toggler.appendChild(document.createTextNode(' | ')); - var a = document.createElement('a'); - a.href = '#'; - a.appendChild(document.createTextNode($lang.get('editor_btn_graphical'))); - span_mce.appendChild(a); - toggler.appendChild(span_mce); + span_wiki.style.display = 'none'; } } @@ -223,6 +229,7 @@ button.assign_vars({ TITLE: $lang.get('editor_btn_closeviewer'), IMAGE: editor_img_path + '/discard.gif', + SPRITE: gen_sprite_html(editor_img_path + '/sprite.png', 16, 16, 0, 16), FLAGS: 'href="#" onclick="ajaxReset(true); return false;"' }); toolbar += button.run(); @@ -343,6 +350,7 @@ button.assign_vars({ TITLE: $lang.get('editor_btn_save'), IMAGE: editor_img_path + '/save.gif', + SPRITE: gen_sprite_html(editor_img_path + '/sprite.png', 16, 16, 0, 64), FLAGS: 'href="#" onclick="ajaxEditorSave(); return false;"' }); toolbar += button.run(); @@ -351,6 +359,7 @@ button.assign_vars({ TITLE: $lang.get('editor_btn_preview'), IMAGE: editor_img_path + '/preview.gif', + SPRITE: gen_sprite_html(editor_img_path + '/sprite.png', 16, 16, 0, 32), FLAGS: 'href="#" onclick="ajaxEditorGenPreview(); return false;"' }); toolbar += button.run(); @@ -359,6 +368,7 @@ button.assign_vars({ TITLE: $lang.get('editor_btn_revert'), IMAGE: editor_img_path + '/revert.gif', + SPRITE: gen_sprite_html(editor_img_path + '/sprite.png', 16, 16, 0, 48), FLAGS: 'href="#" onclick="ajaxEditorRevertToLatest(); return false;"' }); toolbar += button.run(); @@ -367,6 +377,7 @@ button.assign_vars({ TITLE: $lang.get('editor_btn_diff'), IMAGE: editor_img_path + '/diff.gif', + SPRITE: gen_sprite_html(editor_img_path + '/sprite.png', 16, 16, 0, 0), FLAGS: 'href="#" onclick="ajaxEditorShowDiffs(); return false;"' }); toolbar += button.run(); @@ -375,6 +386,7 @@ button.assign_vars({ TITLE: $lang.get('editor_btn_cancel'), IMAGE: editor_img_path + '/discard.gif', + SPRITE: gen_sprite_html(editor_img_path + '/sprite.png', 16, 16, 0, 16), FLAGS: 'href="#" onclick="ajaxEditorCancel(); return false;"' }); toolbar += button.run(); @@ -389,6 +401,7 @@ button.assign_vars({ TITLE: $lang.get('editor_btn_savedraft'), IMAGE: editor_img_path + '/savedraft.gif', + SPRITE: false, FLAGS: 'href="#" onclick="ajaxPerformAutosave(); return false;" id="ajax_edit_savedraft_btn"' }); toolbar += button.run(); @@ -467,29 +480,23 @@ $dynano('ajaxEditArea').setContent(content); // If the editor preference is tinymce, switch the editor to TinyMCE now - if ( readCookie('enano_editor_mode') == 'tinymce' && allow_wysiwyg ) + if ( response.page_format == 'xhtml' && allow_wysiwyg ) { - $dynano('ajaxEditArea').switchToMCE(); + $dynano('ajaxEditArea').switchToMCE(false); } if ( allow_wysiwyg ) { - if ( readCookie('enano_editor_mode') == 'tinymce' ) - { - var a = document.getElementById('enano_edit_btn_pt').getElementsByTagName('a')[0]; - a.onclick = function() { - ajaxSetEditorPlain(); - return false; - }; - } - else - { - var a = document.getElementById('enano_edit_btn_mce').getElementsByTagName('a')[0]; - a.onclick = function() { - ajaxSetEditorMCE(); - return false; - }; - } + var a = document.getElementById('enano_edit_btn_pt').getElementsByTagName('a')[0]; + a.onclick = function() { + ajaxSetEditorPlain(); + return false; + }; + var a = document.getElementById('enano_edit_btn_mce').getElementsByTagName('a')[0]; + a.onclick = function() { + ajaxSetEditorMCE(); + return false; + }; } // if we're using the modal window, fade it in @@ -563,6 +570,7 @@ minor_edit: is_minor, time: timestamp, draft: ( is_draft == true ), + format: ( $dynano('ajaxEditArea').isMCE() ) ? 'xhtml' : 'wikitext', used_draft: used_draft }; @@ -597,12 +605,14 @@ // This will only be used if there was a lower-level error. if ( response.mode == 'error' ) { + editor_save_lock = false; new MessageBox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_server'), response.error); return false; } // This will be used if the PageProcessor generated errors (usually security/permissions related) if ( response.mode == 'errors' ) { + editor_save_lock = false; // This will be true if the user entered a captcha code incorrectly, thus // invalidating the code and requiring a new image to be generated. if ( response.new_captcha ) @@ -625,6 +635,7 @@ // If someone else got to the page first, warn the user if ( response.mode == 'obsolete' ) { + editor_save_lock = false; // Update the local timestamp to allow override $dynano('ajaxEditArea').object._edTimestamp = response.time; new MessageBox(MB_OK | MB_ICONEXCLAMATION, $lang.get('editor_err_obsolete_title'), $lang.get('editor_err_obsolete_body', { author: response.author, timestamp: response.date_string, page_url: makeUrl(title, false, true) })); @@ -668,6 +679,7 @@ editor_open = false; editor_save_lock = false; enableUnload(); + $dynano('ajaxEditArea').destroyMCE(false); changeOpac(0, 'ajaxEditContainer'); ajaxGet(stdAjaxPrefix + '&_mode=getpage&noheaders', function(ajax) { @@ -751,11 +763,34 @@ window.ajaxEditorRevertToLatest = function() { - var mb = new MessageBox(MB_YESNO | MB_ICONQUESTION, $lang.get('editor_msg_revert_confirm_title'), $lang.get('editor_msg_revert_confirm_body')); - mb.onclick['Yes'] = function() - { - setTimeout('ajaxEditorRevertToLatestReal();', 750); - } + miniPromptMessage({ + title: $lang.get('editor_msg_revert_confirm_title'), + message: $lang.get('editor_msg_revert_confirm_body'), + buttons: [ + { + text: $lang.get('editor_btn_revert_confirm'), + color: 'red', + sprite: [ editor_img_path + '/sprite.png', 16, 16, 0, 48 ], + style: { + fontWeight: 'bold' + }, + onclick: function() + { + ajaxEditorRevertToLatestReal(); + miniPromptDestroy(this); + return false; + } + }, + { + text: $lang.get('etc_cancel'), + onclick: function() + { + miniPromptDestroy(this); + return false; + } + } + ] + }); } window.ajaxEditorRevertToLatestReal = function() @@ -789,7 +824,11 @@ return false; } - $dynano('ajaxEditArea').setContent(response.src); + setTimeout(function() + { + editor_convert_if_needed(response.page_format); + $dynano('ajaxEditArea').setContent(response.src); + }, aclDisableTransitionFX ? 10 : 750); } }, true); } @@ -818,73 +857,135 @@ window.ajaxEditorCancel = function() { - var mb = new MessageBox(MB_YESNO | MB_ICONQUESTION, $lang.get('editor_msg_cancel_confirm_title'), $lang.get('editor_msg_cancel_confirm_body')); - mb.onclick['Yes'] = function() - { - setAjaxLoading(); - ajaxEditorDestroyModalWindow(); - editor_open = false; - enableUnload(); - setTimeout('ajaxReset();', 750); - } + miniPromptMessage({ + title: $lang.get('editor_msg_cancel_confirm_title'), + message: $lang.get('editor_msg_cancel_confirm_body'), + buttons: [ + { + text: $lang.get('editor_btn_cancel_confirm'), + color: 'red', + sprite: [ editor_img_path + '/sprite.png', 16, 16, 0, 16 ], + style: { + fontWeight: 'bold' + }, + onclick: function() + { + setAjaxLoading(); + ajaxEditorDestroyModalWindow(); + editor_open = false; + enableUnload(); + $dynano('ajaxEditArea').destroyMCE(false); + ajaxReset(); + miniPromptDestroy(this); + return false; + } + }, + { + text: $lang.get('editor_btn_cancel_cancel'), + onclick: function() + { + miniPromptDestroy(this); + return false; + } + } + ] + }); } -window.ajaxSetEditorMCE = function() +window.ajaxSetEditorMCE = function(confirmed) { if ( editor_loading ) return false; + if ( !confirmed ) + { + miniPromptMessage({ + title: $lang.get('editor_msg_convert_confirm_title'), + message: $lang.get('editor_msg_convert_confirm_body'), + buttons: [ + { + color: 'blue', + text: $lang.get('editor_btn_graphical'), + style: { + fontWeight: 'bold' + }, + sprite: [ editor_img_path + '/sprite.png', 16, 16, 0, 112 ], + onclick: function() + { + ajaxSetEditorMCE(true); + miniPromptDestroy(this); + return false; + } + }, + { + text: $lang.get('etc_cancel'), + onclick: function() + { + miniPromptDestroy(this); + return false; + } + } + ] + }); + return false; + } + // Clear out existing buttons var span_wiki = $dynano('enano_edit_btn_pt').object; var span_mce = $dynano('enano_edit_btn_mce').object; - span_wiki.removeChild(span_wiki.firstChild); - span_mce.removeChild(span_mce.firstChild); - - // Rebuild control - var a = document.createElement('a'); - a.href = '#'; - a.onclick = function() { - ajaxSetEditorPlain(); - return false; - }; - a.appendChild(document.createTextNode($lang.get('editor_btn_wikitext'))); - span_wiki.appendChild(a); - span_mce.appendChild(document.createTextNode($lang.get('editor_btn_graphical'))); + span_wiki.style.display = 'inline'; + span_mce.style.display = 'none'; // Swap editor - $dynano('ajaxEditArea').switchToMCE(); - - // Remember the setting - createCookie('enano_editor_mode', 'tinymce', 365); + $dynano('ajaxEditArea').switchToMCE(true); } -window.ajaxSetEditorPlain = function() +window.ajaxSetEditorPlain = function(confirmed) { if ( editor_loading ) return false; + if ( !confirmed ) + { + miniPromptMessage({ + title: $lang.get('editor_msg_convert_confirm_title'), + message: $lang.get('editor_msg_convert_confirm_body'), + buttons: [ + { + color: 'green', + text: $lang.get('editor_btn_wikitext'), + style: { + fontWeight: 'bold' + }, + sprite: [ editor_img_path + '/sprite.png', 16, 16, 0, 96 ], + onclick: function() + { + ajaxSetEditorPlain(true); + miniPromptDestroy(this); + return false; + } + }, + { + text: $lang.get('etc_cancel'), + onclick: function() + { + miniPromptDestroy(this); + return false; + } + } + ] + }); + return false; + } + // Clear out existing buttons var span_wiki = $dynano('enano_edit_btn_pt').object; var span_mce = $dynano('enano_edit_btn_mce').object; - span_wiki.removeChild(span_wiki.firstChild); - span_mce.removeChild(span_mce.firstChild); - - // Rebuild control - span_wiki.appendChild(document.createTextNode($lang.get('editor_btn_wikitext'))); - var a = document.createElement('a'); - a.href = '#'; - a.onclick = function() { - ajaxSetEditorMCE(); - return false; - }; - a.appendChild(document.createTextNode($lang.get('editor_btn_graphical'))); - span_mce.appendChild(a); + span_wiki.style.display = 'none'; + span_mce.style.display = 'inline'; // Swap editor - $dynano('ajaxEditArea').destroyMCE(); - - // Remember the setting - createCookie('enano_editor_mode', 'text', 365); + $dynano('ajaxEditArea').destroyMCE(true); } var editor_loading = false; @@ -1003,6 +1104,8 @@ return false; } + editor_convert_if_needed(response.page_format); + $dynano('ajaxEditArea').setContent(response.src); $dynano('ajaxEditArea').object.used_draft = true; @@ -1018,3 +1121,54 @@ }, true); } +window.editor_convert_if_needed = function(targetformat, noticetitle, noticebody) +{ + // Do we need to change the format? + var need_to_mce = ( targetformat == 'xhtml' && !$dynano('ajaxEditArea').isMCE() ); + var need_to_wkt = ( targetformat == 'wikitext' && $dynano('ajaxEditArea').isMCE() ); + if ( need_to_mce ) + { + $dynano('ajaxEditArea').setContent(''); + $dynano('ajaxEditArea').switchToMCE(false); + + // Clear out existing buttons + var span_wiki = $dynano('enano_edit_btn_pt').object; + var span_mce = $dynano('enano_edit_btn_mce').object; + span_wiki.style.display = 'inline'; + span_mce.style.display = 'none'; + } + else if ( need_to_wkt ) + { + $dynano('ajaxEditArea').setContent(''); + $dynano('ajaxEditArea').destroyMCE(false); + + // Clear out existing buttons + var span_wiki = $dynano('enano_edit_btn_pt').object; + var span_mce = $dynano('enano_edit_btn_mce').object; + span_wiki.style.display = 'none'; + span_mce.style.display = 'inline'; + } + if ( need_to_mce || need_to_wkt ) + { + // explain the conversion + if ( !noticetitle ) + noticetitle = 'editor_msg_convert_draft_load_title'; + if ( !noticebody ) + noticebody = 'editor_msg_convert_draft_load_body'; + + miniPromptMessage({ + title: $lang.get(noticetitle), + message: $lang.get(noticebody), + buttons: [ + { + text: $lang.get('etc_ok'), + onclick: function() + { + miniPromptDestroy(this); + return false; + } + } + ] + }); + } +} diff -r 45e887f23282 -r 7152ca0a0ce9 includes/clientside/static/functions.js --- a/includes/clientside/static/functions.js Mon Feb 16 16:04:54 2009 -0500 +++ b/includes/clientside/static/functions.js Mon Feb 16 16:17:25 2009 -0500 @@ -104,6 +104,8 @@ // The user allowed the editor to be closed. Reset flags and knock out the on-close confirmation. editor_open = false; enableUnload(); + // destroy the MCE instance so it can be recreated later + $dynano('ajaxEditArea').destroyMCE(false); } var ajax = ajaxMakeXHR(); if ( !ajax ) @@ -136,6 +138,8 @@ // The user allowed the editor to be closed. Reset flags and knock out the on-close confirmation. editor_open = false; enableUnload(); + // destroy the MCE instance so it can be recreated later + $dynano('ajaxEditArea').destroyMCE(false); } var ajax = ajaxMakeXHR(); if ( !ajax ) @@ -448,17 +452,67 @@ } } +/** + * Return a DOMElement that uses a sprite image. + * @param string Path to sprite image + * @param int Width of resulting image + * @param int Height of resulting image + * @param int X offset + * @param int Y offset + * @return object HTMLImageElement + */ + +function gen_sprite(path, width, height, xpos, ypos) +{ + var image = document.createElement('img'); + image.src = scriptPath + '/images/spacer.gif'; + image.width = String(width); + image.height = String(height); + image.style.backgroundImage = 'url(' + path + ')'; + image.style.backgroundRepeat = 'no-repeat'; + xpos = ( xpos == 0 ) ? '0' : '-' + String(xpos); + ypos = ( ypos == 0 ) ? '0' : '-' + String(ypos); + image.style.backgroundPosition = ypos + 'px ' + xpos + 'px'; + + return image; +} + +/** + * The same as gen_sprite but generates HTML instead of a DOMElement. + * @param string Path to sprite image + * @param int Width of resulting image + * @param int Height of resulting image + * @param int X offset + * @param int Y offset + * @return object HTMLImageElement + */ + +function gen_sprite_html(path, width, height, xpos, ypos) +{ + var html = '([\s\S]*?)\([\w\W]*?)|s', $text, $matches) ) + return $text; + + foreach ( $matches[0] as $i => $match ) + { + $tag =& $matches[1][$i]; + $attribs =& $matches[2][$i]; + $inner =& $matches[3][$i]; + + $attribs = self::reverse_process_hint_attribs($attribs); + switch($tag) + { + case 'smiley': + case 'internallink': + case 'imagelink': + if ( isset($attribs['code']) ) + { + $text = str_replace($match, $attribs['code'], $text); + } + else if ( isset($attribs['src']) ) + { + $text = str_replace($match, $attribs['src'], $text); + } + break; + } + } + + return $text; + } + + public static function reverse_process_hint_attribs($attribs) + { + $return = array(); + if ( !preg_match_all('/([a-z0-9_-]+)="([^"]+?)"/', $attribs, $matches) ) + return array(); + + foreach ( $matches[0] as $i => $match ) + { + $name =& $matches[1][$i]; + $value =& $matches[2][$i]; + + $value = base64_decode($value); + + $return[$name] = $value; + } + + return $return; + } + + /** + * Escapes a string so that it's safe to use as an attribute in a parser hint. + * @param string + * @return string + */ + + public static function escape_parser_hint_attrib($text) + { + return base64_encode($text); + } + + public static function reverse_process_headings($text) + { + if ( !preg_match_all('|^(.*?)$|m', $text, $matches) ) + return $text; + + foreach ( $matches[0] as $i => $match ) + { + // generate heading tag + $heading_size = intval($matches[1][$i]); + $eq = ''; + for ( $j = 0; $j < $heading_size; $j++ ) + $eq .= '='; + + $heading =& $matches[2][$i]; + + $tag = "$eq $heading $eq"; + $text = str_replace($match, $tag, $text); + } + + return $text; + } + + public static function reverse_process_lists($text) + { + if ( !preg_match('!()!', $text) ) + return $text; + + $split = preg_split('!()!', $text, -1, PREG_SPLIT_DELIM_CAPTURE); + + $stack_height = 0; + $current_list = ''; + $old_current_list = ''; + $spaces = ''; + $marker = '*'; + $list_id = 0; + $just_terminated = false; + foreach ( $split as $tag ) + { + switch($tag) + { + case '
    ': + case '
      ': + $stack_height++; + $just_terminated = false; + if ( $stack_height > 1 ) + $spaces .= $marker; + + $marker = ( $tag == 'ol' ) ? '#' : '*'; + if ( $stack_height > 1 ) + $current_list .= "\n"; + + break; + case '
': + case '': + $stack_height--; + $spaces = substr($spaces, 1); + + if ( $stack_height == 0 ) + { + // rotate + $text = str_replace_once("{$old_current_list}{$tag}", trim($current_list), $text); + $current_list = ''; + $old_current_list = ''; + } + $just_terminated = true; + break; + case '
  • ': + if ( $stack_height < 1 ) + break; + + $current_list .= "{$spaces}{$marker} "; + break; + case '
  • ': + if ( $stack_height < 1 ) + break; + + if ( !$just_terminated ) + $current_list .= "\n"; + + $just_terminated = false; + break; + default: + if ( $stack_height > 0 ) + { + $current_list .= trim($tag); + } + break; + } + if ( $stack_height > 0 ) + { + $old_current_list .= $tag; + } + } + + return $text; + } + + public static function reverse_process_tables($text) + { + return $text; + } + + /** * Parses internal links (wikilinks) in a block of text. * @param string Text to process * @param string Optional. If included will be used as a template instead of using the default syntax. @@ -567,7 +616,8 @@ } else { - $link = "
    {$inner_text}"; + $omatch = self::escape_parser_hint_attrib($match); + $link = "{$inner_text}"; } $text = str_replace($match, $link, $text); @@ -596,7 +646,8 @@ } else { - $link = "{$inner_text}"; + $omatch = self::escape_parser_hint_attrib($match); + $link = "{$inner_text}"; } $text = str_replace($match, $link, $text); @@ -775,6 +826,9 @@ eval($cmd); } + // gently apply some reverse-processing to allow Text_Wiki to do magic with TOCs and stuff + $text = self::reverse_process_headings($text); + // Reinsert sections for($i=0;$i<$nw;$i++) { @@ -844,43 +898,31 @@ ':-[' => 'face-embarassed.png', ':[' => 'face-embarassed.png' ); - /* - $keys = array_keys($smileys); - foreach($keys as $k) - { - $regex1 = '#([\W]+)'.preg_quote($k).'([\s\n\r\.]+)#s'; - $regex2 = '\\1'.$k.'\\2'; - $text = preg_replace($regex1, $regex2, $text); - } - */ // Strip out sections //return '
    '.htmlspecialchars($text).'
    '; $nw = preg_match_all('#(.*?)<\/nowiki>#is', $text, $nowiki); - for($i=0;$i'.$nowiki[1][$i].'', '{NOWIKI:'.$random_id.':'.$i.'}', $text); + $text = str_replace('' . $nowiki[1][$i] . '', '{NOWIKI:'.$random_id.':'.$i.'}', $text); } - $keys = array_keys($smileys); - foreach($keys as $k) + foreach ( $smileys as $smiley => $smiley_path ) { - $t = hexencode($k, ' ', ''); - $t = trim($t); - $t = explode(' ', $t); - $s = ''; - foreach($t as $b) - { - $s.='&#x'.$b.';'; - } - $pfx = ( $complete_urls ) ? 'http' . ( isset($_SERVER['HTTPS']) ? 's' : '' ) . '://'.$_SERVER['HTTP_HOST'] : ''; - $text = str_replace(' '.$k, ' '.$s.'', $text); + $hex_smiley = hexencode($smiley, '&#x', ';'); + $pfx = ( $complete_urls ) ? get_server_url() : ''; + $text = str_replace(' ' . $smiley, + ' + + ' . $hex_smiley . ' + ', $text); } //*/ // Reinsert sections - for($i=0;$i<$nw;$i++) + for ( $i = 0; $i < $nw; $i++ ) { $text = str_replace('{NOWIKI:'.$random_id.':'.$i.'}', ''.$nowiki[1][$i].'', $text); } @@ -888,39 +930,6 @@ return $text; } - /* - * **** DEPRECATED **** - * Replaces some critical characters in a string with MySQL-safe equivalents - * @param $text string the text to escape - * @return array key 0 is the escaped text, key 1 is the character tag - * / - - public static function escape_page_text($text) - { - $char_tag = md5(microtime() . mt_rand()); - $text = str_replace("'", "{APOS:$char_tag}", $text); - $text = str_replace('"', "{QUOT:$char_tag}", $text); - $text = str_replace("\\", "{SLASH:$char_tag}", $text); - return Array($text, $char_tag); - } - */ - - /* **** DEPRECATED **** - * Reverses the result of RenderMan::escape_page_text(). - * @param $text string the text to unescape - * @param $char_tag string the character tag - * @return string - * / - - public static function unescape_page_text($text, $char_tag) - { - $text = str_replace("{APOS:$char_tag}", "'", $text); - $text = str_replace("{QUOT:$char_tag}", '"', $text); - $text = str_replace("{SLASH:$char_tag}", "\\", $text); - return $text; - } - */ - /** * Generates a summary of the differences between two texts, and formats it as XHTML. * @param $str1 string the first block of text @@ -1025,7 +1034,7 @@ break; } // not the height, so see if a plugin took this over - // this hook requires plugins to return true if they modified anythin + // this hook requires plugins to return true if they modified anything $code = $plugins->setHook('img_tag_parse_params'); foreach ( $code as $cmd ) { @@ -1041,7 +1050,7 @@ if ( !isPage( $paths->nslist['File'] . $filename ) ) { - $text = str_replace($full_tag, '[[' . makeUrlNS('File', $filename) . ']]', $text); + $text = str_replace($full_tag, '[[' . $paths->nslist['File'] . $filename . ']]', $text); continue; } @@ -1081,7 +1090,8 @@ $img_tag .= '/>'; - $complete_tag = ''; + $s_full_tag = self::escape_parser_hint_attrib($full_tag); + $complete_tag = ''; if ( !empty($scale_type) && !$raw_display ) { @@ -1131,12 +1141,12 @@ $complete_tag .= ''; } - $complete_tag .= "\n\n"; + $complete_tag .= ""; $taglist[$i] = $complete_tag; + /* $pos = strpos($text, $full_tag); - /* while(true) { $check1 = substr($text, $pos, 3); diff -r 45e887f23282 -r 7152ca0a0ce9 includes/rijndael.php --- a/includes/rijndael.php Mon Feb 16 16:04:54 2009 -0500 +++ b/includes/rijndael.php Mon Feb 16 16:17:25 2009 -0500 @@ -98,9 +98,9 @@ static function trace($error) { - //$bt = debug_backtrace(); + // $bt = debug_backtrace(); echo("$error\n"); - //echo(print_r($bt, true)); + // echo '
    ' . htmlspecialchars(print_r($bt, true)) . '
    '; exit(); } diff -r 45e887f23282 -r 7152ca0a0ce9 includes/search.php --- a/includes/search.php Mon Feb 16 16:04:54 2009 -0500 +++ b/includes/search.php Mon Feb 16 16:17:25 2009 -0500 @@ -256,7 +256,7 @@ // Is this search term present in the page's title? If so, give extra points preg_match("/^ns=$ns_list;pid=(.+)$/", $match, $piecesparts); $pathskey = $paths->nslist[ $piecesparts[1] ] . sanitize_page_id($piecesparts[2]); - if ( isset($paths->pages[$pathskey]) ) + if ( isPage($pathskey) ) { $test_func = ( $case_sensitive ) ? 'strstr' : 'stristr'; if ( $test_func($paths->pages[$pathskey]['name'], $row['word']) || $test_func($paths->pages[$pathskey]['urlname_nons'], $row['word']) ) @@ -298,7 +298,7 @@ // Is this search term present in the page's title? If so, give extra points preg_match("/^ns=$ns_list;pid=(.+)$/", $pages, $piecesparts); $pathskey = $paths->nslist[ $piecesparts[1] ] . sanitize_page_id($piecesparts[2]); - if ( isset($paths->pages[$pathskey]) ) + if ( isPage($pathskey) ) { $test_func = ( $case_sensitive ) ? 'strstr' : 'stristr'; if ( $test_func($paths->pages[$pathskey]['name'], $row['word']) || $test_func($paths->pages[$pathskey]['urlname_nons'], $row['word']) ) @@ -397,7 +397,7 @@ // Is this search term present in the page's title? If so, give extra points preg_match("/^ns=$ns_list;pid=(.+)$/", $id, $piecesparts); $pathskey = $paths->nslist[ $piecesparts[1] ] . sanitize_page_id($piecesparts[2]); - if ( isset($paths->pages[$pathskey]) ) + if ( isPage($pathskey) ) { $test_func = ( $case_sensitive ) ? 'strstr' : 'stristr'; foreach ( array_merge($query_phrase['any'], $query_phrase['req']) as $term ) diff -r 45e887f23282 -r 7152ca0a0ce9 includes/sessions.php --- a/includes/sessions.php Mon Feb 16 16:04:54 2009 -0500 +++ b/includes/sessions.php Mon Feb 16 16:17:25 2009 -0500 @@ -716,13 +716,17 @@ $this->sql('SELECT password,\'\' AS password_salt,old_encryption,user_id,user_level,temp_password,temp_password_time FROM '.table_prefix."users\n" . " WHERE " . ENANO_SQLFUNC_LOWERCASE . "(username) = '$username_db';"); } - if($db->numrows() < 1) + if ( $db->numrows() < 1 ) { // This wasn't logged in <1.0.2, dunno how it slipped through - if($level > USER_LEVEL_MEMBER) - $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')'); + if ( $level > USER_LEVEL_MEMBER ) + $this->sql('INSERT INTO ' . table_prefix . "logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES\n" + . ' (\'security\', \'admin_auth_bad\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', ' + . '\''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')'); else - $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_bad\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')'); + $this->sql('INSERT INTO ' . table_prefix . "logs(log_type,action,time_id,date_string,author,edit_summary) VALUES\n" + . ' (\'security\', \'auth_bad\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', ' + . '\''.$db->escape($_SERVER['REMOTE_ADDR']).'\')'); // Do we also need to increment the lockout countdown? if ( @$policy != 'disable' && !defined('IN_ENANO_INSTALL') ) @@ -783,7 +787,7 @@ $success = true; } } - else if ( $row['old_encryption'] == 2 || defined('ENANO_UPGRADE_USE_AES_PASSWORDS') ) + else if ( $row['old_encryption'] == 2 || ( defined('ENANO_UPGRADE_USE_AES_PASSWORDS') ) ) { // Our password field uses the 1.0RC1-1.1.5 encryption format $real_pass = $aes->decrypt($row['password'], $this->private_key); @@ -920,7 +924,7 @@ $salt = ''; for ( $i = 0; $i < 32; $i++ ) { - $salt .= chr(mt_rand(32, 127)); + $salt .= chr(mt_rand(32, 126)); } // Session key @@ -946,7 +950,7 @@ { // Stash it in a cookie // For now, make the cookie last forever, we can change this in 1.1.x - setcookie( 'sid', $session_key, time()+15552000, scriptPath.'/', null, ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ) ); + setcookie( 'sid', $session_key, time()+15552000, scriptPath.'/', null, $GLOBALS['is_https']); $_COOKIE['sid'] = $session_key; } // $keyhash is stored in the database, this is for compatibility with the older DB structure @@ -1354,10 +1358,6 @@ if($this->user_logged_in) { $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); - // See if we can get rid of the cached decrypted session key - $key_bin = hex2bin($this->sid); - $key_hash = sha1($key_bin . '::' . $this->private_key); - aes_decrypt_cache_destroy($key_hash); // Completely destroy our session if($this->auth_level > USER_LEVEL_CHPREF) { @@ -1811,8 +1811,6 @@ } } - $password = $aes->encrypt($password, $this->private_key, ENC_HEX); - // Require the account to be activated? switch(getConfig('account_activation')) { @@ -1836,7 +1834,7 @@ $actkey = sha1 ( microtime() . mt_rand() ); // We good, create the user - $this->sql('INSERT INTO '.table_prefix.'users ( username, password, email, real_name, theme, style, reg_time, account_active, activation_key, user_level, user_coppa, user_registration_ip ) VALUES ( \''.$username.'\', \''.$password.'\', \''.$email.'\', \''.$real_name.'\', \''.$template->default_theme.'\', \''.$template->default_style.'\', '.time().', '.$active.', \''.$actkey.'\', '.USER_LEVEL_CHPREF.', ' . $coppa_col . ', \'' . $ip . '\' );'); + $this->sql('INSERT INTO '.table_prefix.'users ( username, email, real_name, theme, style, reg_time, account_active, activation_key, user_level, user_coppa, user_registration_ip ) VALUES ( \''.$username.'\', \''.$email.'\', \''.$real_name.'\', \''.$template->default_theme.'\', \''.$template->default_style.'\', '.time().', '.$active.', \''.$actkey.'\', '.USER_LEVEL_CHPREF.', ' . $coppa_col . ', \'' . $ip . '\' );'); // Get user ID and create users_extra entry $q = $this->sql('SELECT user_id FROM '.table_prefix."users WHERE username='$username';"); @@ -1848,6 +1846,9 @@ $this->sql('INSERT INTO '.table_prefix.'users_extra(user_id) VALUES(' . $user_id . ');'); } + // Set the password + $this->set_password($user_id, $password); + // Config option added, 1.1.5 if ( getConfig('userpage_grant_acl', '1') == '1' ) { @@ -1879,8 +1880,8 @@ // Require the account to be activated? if ( $coppa ) { - $this->admin_activation_request($username); - $this->send_coppa_mail($username,$email); + $this->admin_activation_request($user_orig); + $this->send_coppa_mail($user_orig, $email); } else { @@ -1890,27 +1891,28 @@ default: break; case 'user': - $a = $this->send_activation_mail($username); + $a = $this->send_activation_mail($user_orig); if(!$a) { - $this->admin_activation_request($username); + $this->admin_activation_request($user_orig); return $lang->get('user_reg_err_actmail_failed') . ' ' . $a; } break; case 'admin': - $this->admin_activation_request($username); + $this->admin_activation_request($user_orig); break; } } // Leave some data behind for the hook - $code = $plugins->setHook('user_registered'); // , Array('username'=>$username)); + $code = $plugins->setHook('user_registered'); foreach ( $code as $cmd ) { eval($cmd); } - // $this->register_session($username, $password); + // Uncomment to automatically log the user in (WARNING: commented out for a reason - doesn't consider activation and other things) + // $this->register_session($user_orig, $password); return 'success'; } @@ -1924,9 +1926,6 @@ { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; - $q = $this->sql('SELECT username,email FROM '.table_prefix.'users WHERE user_id=2 OR user_level=' . USER_LEVEL_ADMIN . ' ORDER BY user_id ASC;'); - $un = $db->fetchrow(); - $admin_user = $un['username']; $q = $this->sql('SELECT username,activation_key,account_active,email FROM '.table_prefix.'users WHERE username=\''.$db->escape($u).'\';'); $r = $db->fetchrow(); if ( empty($r['email']) ) @@ -1935,16 +1934,24 @@ $aklink = makeUrlComplete('Special', 'ActivateAccount/'.str_replace(' ', '_', $u).'/'. ( ( is_string($actkey) ) ? $actkey : $r['activation_key'] ) ); $message = $lang->get('user_reg_activation_email', array( 'activation_link' => $aklink, - 'admin_user' => $admin_user, 'username' => $u )); - if(getConfig('smtp_enabled') == '1') + if ( getConfig('smtp_enabled') == '1' ) { $result = smtp_send_email($r['email'], $lang->get('user_reg_activation_email_subject'), preg_replace("#(?get('user_reg_activation_email_subject'), preg_replace("#(?" : ''; ( $inc == 5 ) ? $inc = 0 : null; $url = makeUrlNS('Special', 'TagCloud/' . htmlspecialchars($word)); - $popstring = ( $popularity == 1 ) ? $lang->get('pagetools_tagcloug_tip_popularity_one') : $lang->get('pagetools_tagcloug_tip_popularity_plural', array('popularity' => $popularity)); + $popstring = ( $popularity == 1 ) ? $lang->get('pagetools_tagcloud_tip_popularity_one') : $lang->get('pagetools_tagcloud_tip_popularity_plural', array('popularity' => $popularity)); $html[] = "$word"; // $newline"; } } diff -r 45e887f23282 -r 7152ca0a0ce9 includes/template.php --- a/includes/template.php Mon Feb 16 16:04:54 2009 -0500 +++ b/includes/template.php Mon Feb 16 16:17:25 2009 -0500 @@ -436,7 +436,7 @@ require(ENANO_ROOT . "/themes/{$this->theme}/theme.cfg"); - if ( $local_page_exists && isset($paths->pages[$local_page]) ) + if ( $local_page_exists && isPage($local_page) ) { $local_cdata =& $paths->pages[$local_page]; } @@ -603,7 +603,7 @@ // Page toolbar // Comments button - if ( $perms->get_permissions('read') && getConfig('enable_comments')=='1' && $local_cdata['comments_on'] == 1 ) + if ( $perms->get_permissions('read') && getConfig('enable_comments', '1')=='1' && $local_cdata['comments_on'] == 1 ) { $e = $db->sql_query('SELECT approved FROM '.table_prefix.'comments WHERE page_id=\''.$local_page_id.'\' AND namespace=\''.$local_namespace.'\';'); @@ -1151,7 +1151,7 @@ var disable_redirect = ' . ( isset($_GET['redirect']) && $_GET['redirect'] == 'no' ? 'true' : 'false' ) . '; var pref_disable_js_fx = ' . ( @$session->user_extra['disable_js_fx'] == 1 ? 'true' : 'false' ) . '; var csrf_token = "' . $session->csrf_token . '"; - var editNotice = \'' . ( (getConfig('wiki_edit_notice')=='1') ? str_replace("\n", "\\\n", RenderMan::render(getConfig('wiki_edit_notice_text'))) : '' ) . '\'; + var editNotice = \'' . ( (getConfig('wiki_edit_notice', '0')=='1') ? str_replace("\n", "\\\n", RenderMan::render(getConfig('wiki_edit_notice_text'))) : '' ) . '\'; var prot = ' . ( ($protected) ? 'true' : 'false' ) .'; // No, hacking this var won\'t work, it\'s re-checked on the server var ENANO_SPECIAL_CREATEPAGE = \''. makeUrl($paths->nslist['Special'].'CreatePage') .'\'; var ENANO_CREATEPAGE_PARAMS = \'_do=&pagename='. $urlname_clean .'&namespace=' . $local_namespace . '\'; @@ -2405,7 +2405,7 @@ eval($cmd); } - if(count($ob) > 0 || getConfig('powered_btn') == '1') $sb_links = '
    '. ( ( getConfig('powered_btn') == '1' ) ? $this->fading_button : '' ) . implode('
    ', $ob).'
    '; + if(count($ob) > 0 || getConfig('powered_btn', '1') == '1') $sb_links = '
    '. ( ( getConfig('powered_btn', '1') == '1' ) ? $this->fading_button : '' ) . implode('
    ', $ob).'
    '; else $sb_links = ''; $this->sidebar_widget('Links', $sb_links); diff -r 45e887f23282 -r 7152ca0a0ce9 includes/wikiengine/Parse/Mediawiki/Heading.php --- a/includes/wikiengine/Parse/Mediawiki/Heading.php Mon Feb 16 16:04:54 2009 -0500 +++ b/includes/wikiengine/Parse/Mediawiki/Heading.php Mon Feb 16 16:17:25 2009 -0500 @@ -52,7 +52,7 @@ * */ - var $regex = '/^(={2,6})(.*?)\1(?:\s|$)/m'; + var $regex = '/^(={2,6})(.*?)\1(?:[\t ]|$)/m'; var $conf = array( 'id_prefix' => 'toc' diff -r 45e887f23282 -r 7152ca0a0ce9 index.php --- a/index.php Mon Feb 16 16:04:54 2009 -0500 +++ b/index.php Mon Feb 16 16:17:25 2009 -0500 @@ -251,7 +251,7 @@ '; - if ( getConfig('wiki_edit_notice') == '1' ) + if ( getConfig('wiki_edit_notice', '0') == '1' ) { $notice = getConfig('wiki_edit_notice_text'); echo RenderMan::render($notice); diff -r 45e887f23282 -r 7152ca0a0ce9 install/includes/payload.php --- a/install/includes/payload.php Mon Feb 16 16:04:54 2009 -0500 +++ b/install/includes/payload.php Mon Feb 16 16:17:25 2009 -0500 @@ -433,7 +433,7 @@ function stg_lang_import() { - global $db, $languages; + global $db, $languages, $do_langimport; define('IN_ENANO_UPGRADE_POST', 1); @@ -460,7 +460,7 @@ // generate full path $language_file = ENANO_ROOT . "/language/{$languages[$row['lang_code']]['dir']}/$language_file.json"; // setting the second parameter to bool(true) causes it to skip existing strings - if ( !$lang_local->import($language_file, true) ) + if ( !$lang_local->import($language_file, ( !$do_langimport )) ) // on failure, report failure to libenanoinstall return false; } diff -r 45e887f23282 -r 7152ca0a0ce9 install/upgrade.php --- a/install/upgrade.php Mon Feb 16 16:04:54 2009 -0500 +++ b/install/upgrade.php Mon Feb 16 16:17:25 2009 -0500 @@ -21,6 +21,11 @@ $enano_versions['1.0'] = array('1.0', '1.0.1', '1.0.2b1', '1.0.2', '1.0.3', '1.0.4', '1.0.5'); $enano_versions['1.1'] = array('1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5', '1.1.6'); +// If true, this will do a full langimport instead of only adding new strings. +// Will probably be left on, but some change probably needs to be made to mark +// strings as customized in the DB. +$do_langimport = true; + // Turn on every imaginable API hack to make common load on older databases define('IN_ENANO_UPGRADE', 1); define('IN_ENANO_MIGRATION', 1); @@ -38,7 +43,8 @@ require_once('includes/common.php'); @ini_set('display_errors', 'on'); -define('ENANO_UPGRADE_USE_AES_PASSWORDS', in_array(enano_version(), array('1.0RC1', '1.0RC2', '1.0RC3', '1.0', '1.0.1', '1.0.2', '1.0.3', '1.0.4', '1.0.5', '1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5'))); +if ( in_array(enano_version(), array('1.0RC1', '1.0RC2', '1.0RC3', '1.0', '1.0.1', '1.0.2', '1.0.3', '1.0.4', '1.0.5', '1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5')) ) + define('ENANO_UPGRADE_USE_AES_PASSWORDS', 1); $ui = new Enano_Installer_UI('Enano upgrader', false); @@ -270,6 +276,15 @@
  • get('upgrade_confirm_objective_backup_fs', array('dir' => ENANO_ROOT)); ?>
  • get('upgrade_confirm_objective_backup_db', array('dbname' => $dbname)); ?>
  • + +
    + get('upgrade_confirm_warning_langimport'); ?> +
    +