From 4e0ebf82f06cc15651096e1d5f3c3559cb26a348 Mon Sep 17 00:00:00 2001 From: rurban Date: Mon, 6 Dec 2004 19:50:05 +0000 Subject: [PATCH] enable action=remove which is undoable and seeable in RecentChanges: ADODB ony for now. renamed delete_page to purge_page. enable action=edit&version=-1 to force creation of a new version. added BABYCART_PATH config fixed magiqc in adodb.inc.php and some more docs git-svn-id: svn://svn.code.sf.net/p/phpwiki/code/trunk@4243 96ab9672-09ca-45d6-a79d-3d69d39ca109 --- lib/CachedMarkup.php | 4 +- lib/PageType.php | 3 +- lib/Request.php | 15 ++++- lib/WikiDB.php | 56 +++++++++++++----- lib/WikiDB/ADODB.php | 4 +- lib/WikiDB/SQL.php | 4 +- lib/WikiDB/adodb/adodb.inc.php | 4 +- lib/WikiDB/backend/ADODB.php | 89 +++++++++++++++++++++++++---- lib/WikiDB/backend/PearDB.php | 20 ++++++- lib/WikiDB/backend/PearDB_oci8.php | 4 +- lib/WikiDB/backend/PearDB_pgsql.php | 4 +- lib/WikiDB/backend/cvs.php | 11 +++- lib/WikiDB/backend/dbaBase.php | 11 +++- lib/WikiDB/backend/file.php | 18 ++++-- lib/XmlElement.php | 8 ++- lib/XmlRpcServer.php | 58 ++++++++++++++++--- lib/editpage.php | 29 +++++++--- lib/install.php | 58 +++++++++++++++++++ lib/plugin/AllPages.php | 24 +++++--- lib/plugin/BackLinks.php | 8 ++- lib/plugin/LinkDatabase.php | 17 +++--- lib/plugin/ModeratedPage.php | 75 ++++++++++++++++-------- lib/plugin/PhotoAlbum.php | 13 ++++- lib/plugin/UnfoldSubpages.php | 15 ++++- lib/plugin/WikiAdminChmod.php | 27 +++++++-- lib/plugin/WikiAdminSelect.php | 14 ++++- lib/plugin/WikiAdminUtils.php | 82 ++++++++++++++++++-------- lib/removepage.php | 16 ++++-- lib/spam_babycart.php | 14 +++-- lib/stdlib.php | 14 +++-- 30 files changed, 553 insertions(+), 166 deletions(-) create mode 100644 lib/install.php diff --git a/lib/CachedMarkup.php b/lib/CachedMarkup.php index a2d65ff0c..d292f157b 100644 --- a/lib/CachedMarkup.php +++ b/lib/CachedMarkup.php @@ -1,5 +1,5 @@ * * This file is part of PhpWiki. @@ -514,4 +514,4 @@ class Cached_PluginInvocation extends Cached_DynamicContent { // c-hanging-comment-ender-p: nil // indent-tabs-mode: nil // End: -?> +?> \ No newline at end of file diff --git a/lib/PageType.php b/lib/PageType.php index 440fef41f..8aebfe114 100644 --- a/lib/PageType.php +++ b/lib/PageType.php @@ -1,5 +1,5 @@ _is_buffering_output = false; @@ -1305,6 +1304,18 @@ class HTTP_ValidatorSet { // $Log: not supported by cvs2svn $ +// Revision 1.81 2004/11/27 14:39:04 rurban +// simpified regex search architecture: +// no db specific node methods anymore, +// new sql() method for each node +// parallel to regexp() (which returns pcre) +// regex types bitmasked (op's not yet) +// new regex=sql +// clarified WikiDB::quote() backend methods: +// ->quote() adds surrounsing quotes +// ->qstr() (new method) assumes strings and adds no quotes! (in contrast to ADODB) +// pear and adodb have now unified quote methods for all generic queries. +// // Revision 1.80 2004/11/21 11:59:16 rurban // remove final \n to be ob_cache independent // diff --git a/lib/WikiDB.php b/lib/WikiDB.php index 1a749d011..9efc4bf10 100644 --- a/lib/WikiDB.php +++ b/lib/WikiDB.php @@ -1,5 +1,5 @@ _cache->delete_page($pagename); + // don't create empty revisions of already purged pages. + if ($this->_backend->get_latest_version($pagename)) + $result = $this->_cache->delete_page($pagename); + else + $result = -1; /* Generate notification emails? */ if (! $this->isWikiPage($pagename) ) { @@ -235,13 +241,13 @@ class WikiDB { //TODO: deferr it (quite a massive load if you remove some pages). //TODO: notification class which catches all changes, // and decides at the end of the request what to mail. (type, page, who, what, users, emails) - // could be used for PageModeration also. + // could be used for PageModeration and RSS2 Cloud xml-rpc also. $page = new WikiDB_Page($this, $pagename); list($emails, $userids) = $page->getPageChangeEmails($notify); if (!empty($emails)) { $editedby = sprintf(_("Removed by: %s"), $GLOBALS['request']->_user->getId()); // Todo: host_id $emails = join(',', $emails); - $subject = sprintf(_("Page deleted %s"), urlencode($pagename)); + $subject = sprintf(_("Page removed %s"), urlencode($pagename)); if (mail($emails,"[".WIKI_NAME."] ".$subject, $subject."\n". $editedby."\n\n". @@ -264,8 +270,18 @@ class WikiDB { $meta['summary'] = _("removed"); $page->save($current->getPackedContent(), $version + 1, $meta); */ + return $result; } + /** + * Completely remove the page from the WikiDB, without undo possibility. + */ + function purgePage($pagename) { + $result = $this->_cache->purge_page($pagename); + $this->deletePage($pagename); // just for the notification + return $result; + } + /** * Retrieve all pages. * @@ -287,8 +303,8 @@ class WikiDB { $mem = ini_get("memory_limit"); if ($mem and !$limit and !isWindows() and !check_php_version(4,3)) { $limit = 450; - $GLOBALS['request']->setArg('limit',$limit); - $GLOBALS['request']->setArg('paging','auto'); + $GLOBALS['request']->setArg('limit', $limit); + $GLOBALS['request']->setArg('paging', 'auto'); } } $result = $this->_backend->get_all_pages($include_empty, $sortby, $limit, $exclude); @@ -662,6 +678,7 @@ class WikiDB_Page function exists() { if (isset($this->_wikidb->_cache->_id_cache[$this->_pagename])) return true; $current = $this->getCurrentRevision(false); + if (!$current) return false; return ! $current->hasDefaultContents(); } @@ -822,7 +839,7 @@ class WikiDB_Page if (empty($data['mtime'])) $data['mtime'] = time(); - if ($latestversion) { + if ($latestversion and $version != WIKIDB_FORCE_CREATE) { // Ensure mtimes are monotonic. $pdata = $cache->get_versiondata($pagename, $latestversion); if ($data['mtime'] < $pdata['mtime']) { @@ -900,9 +917,9 @@ class WikiDB_Page $this->sendPageChangeNotification($wikitext, $version, $meta, $emails, $userids); } } + $newrevision->_transformedContent = $formatted; } - $newrevision->_transformedContent = $formatted; return $newrevision; } @@ -1099,13 +1116,13 @@ class WikiDB_Page $cache = &$this->_wikidb->_cache; $pagename = &$this->_pagename; - if (! $version ) // 0 or false + if (! $version or $version == -1) // 0 or false return new WikiDB_PageRevision($this->_wikidb, $pagename, 0); assert($version > 0); $vdata = $cache->get_versiondata($pagename, $version, $need_content); if (!$vdata) { - return false; + return new WikiDB_PageRevision($this->_wikidb, $pagename, 0); } return new WikiDB_PageRevision($this->_wikidb, $pagename, $version, $vdata); @@ -1982,11 +1999,18 @@ class WikiDB_cache } function delete_page($pagename) { - $this->_backend->delete_page($pagename); + $result = $this->_backend->delete_page($pagename); + $this->invalidate_cache($pagename); + return $result; + } + + function purge_page($pagename) { + $result = $this->_backend->purge_page($pagename); $this->invalidate_cache($pagename); + return $result; } - // FIXME: ugly and wrong. overwrites full cache with partial cache + // FIXME: ugly and wrong. may overwrite full cache with partial cache function cache_data($data) { ; //if (isset($data['pagedata'])) @@ -2095,11 +2119,15 @@ function _sql_debuglog($msg, $newline=true, $shutdown=false) { if ($newline) fputs($fp, "[$i++] $msg"); else fwrite($fp, $msg); } + function _sql_debuglog_shutdown_function() { _sql_debuglog('',false,true); } // $Log: not supported by cvs2svn $ +// Revision 1.112 2004/11/30 17:45:53 rurban +// exists_links backend implementation +// // Revision 1.111 2004/11/28 20:39:43 rurban // deactivate pagecache overwrite: it is wrong // diff --git a/lib/WikiDB/ADODB.php b/lib/WikiDB/ADODB.php index c02b2313a..4339976ce 100644 --- a/lib/WikiDB/ADODB.php +++ b/lib/WikiDB/ADODB.php @@ -1,5 +1,5 @@ +?> \ No newline at end of file diff --git a/lib/WikiDB/SQL.php b/lib/WikiDB/SQL.php index c84217c28..e703ee75b 100644 --- a/lib/WikiDB/SQL.php +++ b/lib/WikiDB/SQL.php @@ -1,4 +1,4 @@ - +?> \ No newline at end of file diff --git a/lib/WikiDB/adodb/adodb.inc.php b/lib/WikiDB/adodb/adodb.inc.php index 71850cded..88c20b74f 100644 --- a/lib/WikiDB/adodb/adodb.inc.php +++ b/lib/WikiDB/adodb/adodb.inc.php @@ -2130,9 +2130,9 @@ /** * Quotes a string, without prefixing nor appending quotes. */ - function addq($s,$magicq=false) + function addq($s, $magicq=false) { - if (!$magic_quotes) { + if (!$magicq) { if ($this->replaceQuote[0] == '\\'){ // only since php 4.0.5 diff --git a/lib/WikiDB/backend/ADODB.php b/lib/WikiDB/backend/ADODB.php index 698534c3c..1d27310e2 100644 --- a/lib/WikiDB/backend/ADODB.php +++ b/lib/WikiDB/backend/ADODB.php @@ -1,5 +1,5 @@ Execute("UPDATE $page_tbl" . " SET hits=?, pagedata=?" . " WHERE pagename=?", - array($hits, $this->_serialize($data),$pagename))) + array($hits, $this->_serialize($data),$pagename))) { $dbh->CommitTrans( ); - else + return true; + } else { $dbh->RollbackTrans( ); + return false; + } } function _get_pageid($pagename, $create_if_missing = false) { @@ -459,31 +462,77 @@ extends WikiDB_backend } /** - * Delete page from the database. + * Delete page from the database with backup possibility. + * + * deletePage increments latestversion in recent to a non-existent version, + * and removes the nonempty row, + * so that get_latest_version returns id+1 and get_previous_version returns prev id + * and page->exists returns false. */ function delete_page($pagename) { $dbh = &$this->_dbh; extract($this->_table_names); + + $dbh->BeginTrans(); + $dbh->CommitLock($recent_tbl); + if (($id = $this->_get_pageid($pagename, false)) === false) { + $dbh->RollbackTrans( ); + return false; + } + $version = $this->get_latest_version($pagename); + $mtime = time(); + $user =& $GLOBALS['request']->_user; + $meta = array('author' => $user->getId(), + 'author_id' => $user->getAuthenticatedId(), + 'mtime' => $mtime); + $this->lock(array('version','recent','nonempty','page','link')); + if ($dbh->Execute("UPDATE $recent_tbl SET latestversion=latestversion+1,latestmajor=latestversion+1,latestminor=NULL WHERE id=$id") + and $dbh->Execute("INSERT INTO $version_tbl" + . " (id,version,mtime,minor_edit,content,versiondata)" + . " VALUES(?,?,?,?,?,?)", + array($id, $version+1, $mtime, 0, + '', $this->_serialize($meta))) + and $dbh->Execute("DELETE FROM $nonempty_tbl WHERE id=$id") + and $this->set_links($pagename, false) + and $dbh->Execute("UPDATE $page_tbl SET pagedata='' WHERE id=$id") // keep hits but delete meta-data + ) + { + $this->unlock(array('version','recent','nonempty','page','link')); + $dbh->CommitTrans( ); + return true; + } else { + $this->unlock(array('version','recent','nonempty','page','link')); + $dbh->RollbackTrans( ); + return false; + } + } + + function purge_page($pagename) { + $dbh = &$this->_dbh; + extract($this->_table_names); $this->lock(array('version','recent','nonempty','page','link')); if ( ($id = $this->_get_pageid($pagename, false)) ) { $dbh->Execute("DELETE FROM $version_tbl WHERE id=$id"); $dbh->Execute("DELETE FROM $recent_tbl WHERE id=$id"); $dbh->Execute("DELETE FROM $nonempty_tbl WHERE id=$id"); - $dbh->Execute("DELETE FROM $link_tbl WHERE linkfrom=$id"); + $this->set_links($pagename, false); $row = $dbh->GetRow("SELECT COUNT(*) FROM $link_tbl WHERE linkto=$id"); if ($row and $row[0]) { // We're still in the link table (dangling link) so we can't delete this // altogether. $dbh->Execute("UPDATE $page_tbl SET hits=0, pagedata='' WHERE id=$id"); + $result = 0; } else { $dbh->Execute("DELETE FROM $page_tbl WHERE id=$id"); + $result = 1; } - $this->_update_recent_table(); - $this->_update_nonempty_table(); + } else { + $result = -1; // already purged or not existing } $this->unlock(array('version','recent','nonempty','page','link')); + return $result; } @@ -503,9 +552,8 @@ extends WikiDB_backend $this->lock(array('link')); $pageid = $this->_get_pageid($pagename, true); - $dbh->Execute("DELETE FROM $link_tbl WHERE linkfrom=$pageid"); - if ($links) { + $dbh->Execute("DELETE FROM $link_tbl WHERE linkfrom=$pageid"); foreach($links as $link) { if (isset($linkseen[$link])) continue; @@ -514,8 +562,22 @@ extends WikiDB_backend $dbh->Execute("INSERT INTO $link_tbl (linkfrom, linkto)" . " VALUES ($pageid, $linkid)"); } + } elseif (DEBUG) { + // purge page table: delete all non-referenced pages + // for all previously linked pages... + foreach ($dbh->getRow("SELECT $link_tbl.linkto as id FROM $link_tbl WHERE linkfrom=$pageid") as $id) { + // ...check if the page is empty and has no version + if ($dbh->getRow("SELECT $page_tbl.id FROM $page_tbl LEFT JOIN $nonempty_tbl USING (id) " + ." LEFT JOIN $version_tbl USING (id)" + ." WHERE ISNULL($nonempty_tbl.id) AND ISNULL($version_tbl.id) AND $page_tbl.id=$id")) { + $dbh->Execute("DELETE FROM $page_tbl WHERE id=$id"); // this purges the link + $dbh->Execute("DELETE FROM $recent_tbl WHERE id=$id"); // may fail + } + } + $dbh->Execute("DELETE FROM $link_tbl WHERE linkfrom=$pageid"); } $this->unlock(array('link')); + return true; } /** @@ -614,7 +676,7 @@ extends WikiDB_backend $sql = "SELECT " . $this->page_tbl_fields . " FROM $page_tbl" - . $exclude ? " WHERE $exclude" : '' + . ($exclude ? " WHERE $exclude" : '') . $orderby; } else { $sql = "SELECT " @@ -1128,13 +1190,13 @@ extends WikiDB_backend_search $this->_case_exact = $search->_case_exact; } function _pagename_match_clause($node) { - $word = $node->sql($word); + $word = $node->sql(); return $this->_case_exact ? "pagename LIKE '$word'" : "LOWER(pagename) LIKE '$word'"; } function _fulltext_match_clause($node) { - $word = $node->sql($word); + $word = $node->sql(); return $this->_case_exact ? "pagename LIKE '$word' OR content LIKE '$word'" : "LOWER(pagename) LIKE '$word' OR content LIKE '$word'"; @@ -1301,6 +1363,9 @@ extends WikiDB_backend_search } // $Log: not supported by cvs2svn $ +// Revision 1.61 2004/11/30 17:45:53 rurban +// exists_links backend implementation +// // Revision 1.60 2004/11/28 20:42:18 rurban // Optimize PearDB _extract_version_data and _extract_page_data. // diff --git a/lib/WikiDB/backend/PearDB.php b/lib/WikiDB/backend/PearDB.php index 9a38ae024..ad6e089bb 100644 --- a/lib/WikiDB/backend/PearDB.php +++ b/lib/WikiDB/backend/PearDB.php @@ -1,5 +1,5 @@ unlock(); } + /** + * See ADODB for a better delete_page(), which can be undone and is seen in RecentChanges. + */ + function delete_page($pagename) { + $this->purge_page($pagename); + } + /** * Delete page completely from the database. * I'm not sure if this is what we want. Maybe just delete the revisions */ - function delete_page($pagename) { + function purge_page($pagename) { $dbh = &$this->_dbh; extract($this->_table_names); @@ -428,16 +435,20 @@ extends WikiDB_backend // We're still in the link table (dangling link) so we can't delete this // altogether. $dbh->query("UPDATE $page_tbl SET hits=0, pagedata='' WHERE id=$id"); + $result = 0; } else { $dbh->query("DELETE FROM $page_tbl WHERE id=$id"); + $result = 1; } $this->_update_recent_table(); $this->_update_nonempty_table(); + } else { + $result = -1; // already purged or not existing } $this->unlock(); + return $result; } - // The only thing we might be interested in updating which we can // do fast in the flags (minor_edit). I think the default @@ -1171,6 +1182,9 @@ extends WikiDB_backend_search } // $Log: not supported by cvs2svn $ +// Revision 1.76 2004/11/30 17:45:53 rurban +// exists_links backend implementation +// // Revision 1.75 2004/11/28 20:42:33 rurban // Optimize PearDB _extract_version_data and _extract_page_data. // diff --git a/lib/WikiDB/backend/PearDB_oci8.php b/lib/WikiDB/backend/PearDB_oci8.php index f0b9842b5..83b329f35 100644 --- a/lib/WikiDB/backend/PearDB_oci8.php +++ b/lib/WikiDB/backend/PearDB_oci8.php @@ -1,5 +1,5 @@ +?> \ No newline at end of file diff --git a/lib/WikiDB/backend/PearDB_pgsql.php b/lib/WikiDB/backend/PearDB_pgsql.php index f4a138633..2e65ec894 100644 --- a/lib/WikiDB/backend/PearDB_pgsql.php +++ b/lib/WikiDB/backend/PearDB_pgsql.php @@ -1,5 +1,5 @@ +?> \ No newline at end of file diff --git a/lib/WikiDB/backend/cvs.php b/lib/WikiDB/backend/cvs.php index 818c5bd56..4eb75210b 100644 --- a/lib/WikiDB/backend/cvs.php +++ b/lib/WikiDB/backend/cvs.php @@ -1,5 +1,5 @@ purge_page($pagename); + } + /** * This returns false if page was not deleted or could not be deleted * else return true. */ - function delete_page($pagename) + function purge_page($pagename) { $this->_cvsDebug( "delete_page [$pagename]") ; $filename = $this->_docDir . "/" . $pagename; diff --git a/lib/WikiDB/backend/dbaBase.php b/lib/WikiDB/backend/dbaBase.php index 520f1a6b3..9875b70ce 100644 --- a/lib/WikiDB/backend/dbaBase.php +++ b/lib/WikiDB/backend/dbaBase.php @@ -1,4 +1,4 @@ -purge_page($pagename); + } + + /** + * Completely delete page from the database. + */ + function purge_page($pagename) { $pagedb = &$this->_pagedb; $versdb = &$this->_versiondb; diff --git a/lib/WikiDB/backend/file.php b/lib/WikiDB/backend/file.php index 297c12f9f..d3b025842 100644 --- a/lib/WikiDB/backend/file.php +++ b/lib/WikiDB/backend/file.php @@ -1,5 +1,5 @@ purge_page($pagename); + } + /** * Delete page from the database. * @@ -408,9 +413,9 @@ extends WikiDB_backend * * @param $pagename string Page name. */ - function delete_page($pagename) { + function purge_page($pagename) { $ver = $this->get_latest_version($pagename); - while($ver > 0) { + while ($ver > 0) { $this->_removePage('ver_data', $pagename, $ver); $ver = $this->get_previous_version($pagename, $ver); } @@ -730,6 +735,9 @@ class WikiDB_backend_file_iter extends WikiDB_backend_iterator } // $Log: not supported by cvs2svn $ +// Revision 1.21 2004/11/25 17:20:52 rurban +// and again a couple of more native db args: backlinks +// // Revision 1.20 2004/11/23 13:35:49 rurban // add case_exact search // diff --git a/lib/XmlElement.php b/lib/XmlElement.php index 742331038..27cde084d 100644 --- a/lib/XmlElement.php +++ b/lib/XmlElement.php @@ -1,8 +1,9 @@ - * * LICENCE @@ -28,8 +28,8 @@ * for details. * * PHP >= 4.1.0 includes experimental support for the xmlrpc-epi c library - * written by Dan Libby (see http://uk2.php.net/manual/en/ref.xmlrpc.php). This - * is not compiled into PHP by default. If it *is* compiled into your installation + * written by Dan Libby (see http://uk2.php.net/manual/en/ref.xmlrpc.php). + * This is not compiled into PHP by default. If it *is* compiled into your installation * (ie you have --with-xmlrpc) there may well be namespace conflicts with the xml-rpc * library used by this code, and you will get errors. * @@ -50,7 +50,7 @@ // Make use of the xmlrpc extension if found. Resolve namespace conflicts // Remove all warnings from xmlrpc.inc // Return list of external links in listLinks - +// RSS2 cloud subscription // Intercept GET requests from confused users. Only POST is allowed here! // There is some indication that $HTTP_SERVER_VARS is deprecated in php > 4.1.0 @@ -84,7 +84,7 @@ global $_xmlrpcs_debug; include_once("lib/XMLRPC/xmlrpcs.inc"); // API version -define ("WIKI_XMLRPC_VERSION", 1); +define ("WIKI_XMLRPC_VERSION", "1.1"); /** * Helper function: Looks up a page revision (most recent by default) in the wiki database @@ -185,7 +185,7 @@ $wiki_dmap['getRPCVersionSupported'] // method. function getRPCVersionSupported($params) { - return new xmlrpcresp(new xmlrpcval(WIKI_XMLRPC_VERSION, "int")); + return new xmlrpcresp(new xmlrpcval(WIKI_XMLRPC_VERSION, "string")); } /** @@ -443,9 +443,51 @@ function listLinks($params) return new xmlrpcresp(new xmlrpcval ($linkstruct, "array")); } + +/** + * Publish-Subscribe + * Client subscribes to a RecentChanges-like channel, getting a short + * callback notification on every change. Like PageChangeNotification, just shorter + * and more complicated + * RSS2 support (not yet), since radio userland's rss-0.92. now called RSS2. + * BTW: Radio Userland deprecated this interface. + * + * boolean wiki.rssPleaseNotify ( notifyProcedure, port, path, protocol, urlList ) + * returns: true or false + * + * Check of the channel behind the rssurl has a cloud element, + * if the client has a direct IP connection (no NAT), + * register the client on the WikiDB notification handler + * + * http://backend.userland.com/publishSubscribeWalkthrough + * http://www.soapware.org/xmlStorageSystem#rssPleaseNotify + * http://www.thetwowayweb.com/soapmeetsrss#rsscloudInterface + */ +$wiki_dmap['rssPleaseNotify'] += array('signature' => array(array($xmlrpcStruct, $xmlrpcBoolean)), + 'documentation' => 'RSS2 change notification subscriber channel', + 'function' => 'rssPleaseNotify'); + +function rssPleaseNotify($params) +{ + // register the clients IP + return new xmlrpcresp(new xmlrpcval (false, "boolean")); +} + +$wiki_dmap['mailPasswordToUser'] += array('signature' => array(array($xmlrpcStruct, $xmlrpcString)), + 'documentation' => 'RSS2 change notification subscriber channel', + 'function' => 'mailPasswordToUser'); + +function mailPasswordToUser($params) +{ + return new xmlrpcresp(new xmlrpcval (false, "boolean")); +} -// Construct the server instance, and set up the despatch map, which maps -// the XML-RPC methods onto the wiki functions +/** + * Construct the server instance, and set up the dispatch map, which maps + * the XML-RPC methods on to the wiki functions. + */ class XmlRpcServer extends xmlrpc_server { function XmlRpcServer ($request = false) { diff --git a/lib/editpage.php b/lib/editpage.php index 0fcc107fb..a281c49f0 100644 --- a/lib/editpage.php +++ b/lib/editpage.php @@ -1,5 +1,5 @@ version = $this->_currentVersion; $unresolved = $diff->ConflictingBlocks; $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage($unresolved); + } elseif ($saveFailed) { + $tokens['CONCURRENT_UPDATE_MESSAGE'] = + HTML(HTML::h2(_("Some internal editing error")), + HTML::p(_("Your are probably trying to edit/create an invalid version of this page.")), + HTML::p(HTML::em(_("&version=-1 might help.")))); } if ($this->editaction == 'preview') @@ -455,8 +460,10 @@ function undo_save() { // Save new revision $this->_content = $this->getContent(); - $newrevision = $page->save($this->_content, $this->_currentVersion + 1, $meta); - if (!isa($newrevision, 'wikidb_pagerevision')) { + $newrevision = $page->save($this->_content, + $this->version == -1 ? -1 : $this->_currentVersion + 1, // force new? + $meta); + if (!isa($newrevision, 'WikiDB_PageRevision')) { // Save failed. (Concurrent updates). return false; } @@ -524,22 +531,25 @@ function undo_save() { /** * Handle AntiSpam here. How? http://wikiblacklist.blogspot.com/ - * Need to check dynamically some blacklist content (plugin WikiAccessRestrictions) + * Need to check dynamically some blacklist wikipage settings (plugin WikiAccessRestrictions) + * and some static blacklist. * DONE: * More then 20 new external links + * content patterns by babycart (only php >= 4.3 for now) * TODO: * IP BlackList * domain blacklist * url patterns - * content patterns by babycart */ function isSpam () { $current = &$this->current; $request = &$this->request; + $oldtext = $current->getPackedContent(); $newtext =& $this->_content; // 1. Not more then 20 new external links if ($this->numLinks($newtext) - $this->numLinks($oldtext) >= 20) { + // mail the admin? $this->tokens['PAGE_LOCKED_MESSAGE'] = HTML($this->getSpamMessage(), HTML::p(HTML::em(_("Too many external links.")))); @@ -551,10 +561,11 @@ function undo_save() { $user = $request->getUser(); include_once("lib/spam_babycart.php"); if ($babycart = check_babycart($newtext, $request->get("REMOTE_ADDR"), $user->getId())) { + // mail the admin? if (is_array($babycart)) $this->tokens['PAGE_LOCKED_MESSAGE'] = HTML($this->getSpamMessage(), - HTML::p(HTML::em(_("SpamAssassin reports: ", join("\n",$babycart))))); + HTML::p(HTML::em(_("SpamAssassin reports: ", join("\n", $babycart))))); return true; } } @@ -879,6 +890,10 @@ extends PageEditor /** $Log: not supported by cvs2svn $ + Revision 1.84 2004/12/04 12:58:26 rurban + enable babycart Blog::SpamAssassin module on ENABLE_SPAMASSASSIN=true + (currently only for php >= 4.3.0) + Revision 1.83 2004/12/04 11:55:39 rurban First simple AntiSpam prevention: No more than 20 new http:// links allowed diff --git a/lib/install.php b/lib/install.php new file mode 100644 index 000000000..6b80669f8 --- /dev/null +++ b/lib/install.php @@ -0,0 +1,58 @@ + \ No newline at end of file diff --git a/lib/plugin/AllPages.php b/lib/plugin/AllPages.php index c5342ac0f..e44be0101 100644 --- a/lib/plugin/AllPages.php +++ b/lib/plugin/AllPages.php @@ -1,5 +1,5 @@ getArgs($argstr, $request); + $pages = false; // Todo: extend given _GET args if ($args['debug']) $timer = new DebugTimer; @@ -92,10 +93,9 @@ extends WikiPlugin } else { if (! $request->getArg('count')) $args['count'] = $dbi->numPages($args['include_empty'],$args['exclude']); else $args['count'] = $request->getArg('count'); - //$pages = false; // ?? } - //if (empty($args['count']) and !empty($pages)) - // $args['count'] = count($pages); + if (empty($args['count']) and !empty($pages)) + $args['count'] = count($pages); $pagelist = new PageList($args['info'], $args['exclude'], $args); if (!$args['noheader']) $pagelist->setCaption($caption); @@ -103,10 +103,10 @@ extends WikiPlugin if ($args['include_empty']) $pagelist->_addColumn('version'); - /*if ($pages !== false) + if ($pages !== false) $pagelist->addPageList($pages); - else */ - $pagelist->addPages( $dbi->getAllPages($args['include_empty'], $args['sortby'], $args['limit']) ); + else + $pagelist->addPages( $dbi->getAllPages($args['include_empty'], $args['sortby'], $args['limit']) ); if ($args['debug']) { return HTML($pagelist, HTML::p(fmt("Elapsed time: %s s", $timer->getStats()))); @@ -122,6 +122,14 @@ extends WikiPlugin }; // $Log: not supported by cvs2svn $ +// Revision 1.34 2004/11/23 15:17:19 rurban +// better support for case_exact search (not caseexact for consistency), +// plugin args simplification: +// handle and explode exclude and pages argument in WikiPlugin::getArgs +// and exclude in advance (at the sql level if possible) +// handle sortby and limit from request override in WikiPlugin::getArgs +// ListSubpages: renamed pages to maxpages +// // Revision 1.33 2004/11/01 10:43:59 rurban // seperate PassUser methods into seperate dir (memory usage) // fix WikiUser (old) overlarge data session diff --git a/lib/plugin/BackLinks.php b/lib/plugin/BackLinks.php index c7cefbe44..61fedee83 100644 --- a/lib/plugin/BackLinks.php +++ b/lib/plugin/BackLinks.php @@ -1,5 +1,5 @@ '[pagename]', @@ -63,18 +65,18 @@ extends WikiPlugin $page = $dbi->getPage($args['page']); $moderation = $page->get("moderation"); if ($moderation) { - if (isset($moderation['id']) and $moderation['id'] == $args['id']) { - // handle defaults: - // approve or reject - if ($args['pass'] == 'approve') - return $this->approve($args, $moderation); - elseif ($args['pass'] == 'reject') - return $this->reject($args, $moderation); - else - return $this->error("Wrong pass ".$args['pass']); - } else { - return $this->error("Wrong id"); - } + if (isset($moderation['id']) and $moderation['id'] == $args['id']) { + // handle defaults: + // approve or reject + if ($args['pass'] == 'approve') + return $this->approve($args, $moderation); + elseif ($args['pass'] == 'reject') + return $this->reject($args, $moderation); + else + return $this->error("Wrong pass ".$args['pass']); + } else { + return $this->error("Wrong id"); + } } } return ''; @@ -109,6 +111,15 @@ extends WikiPlugin $users[$userid] = 0; } list($args['emails'], $args['moderators']) = $page->getPageChangeEmails(array($page->getName() => $users)); + + if (!empty($args['require_access'])) { + $args['require_access'] = preg_split("/\s*,\s*/", $args['require_access']); + if (empty($args['require_access'])) + unset($args['require_access']); + } + if ($args['require_level'] !== false) { + $args['require_level'] = (integer) $args['require_level']; + } unset($args['id']); unset($args['page']); unset($args['pass']); @@ -175,7 +186,7 @@ extends WikiPlugin } /** - * Handle client-side moderation request on any moderated page. + * Handle client-side POST moderation request on any moderated page. * if ($page->get('moderation')) WikiPlugin_ModeratedPage::handler(...); * return false if not handled (pass through), true if handled and displayed. */ @@ -195,14 +206,22 @@ extends WikiPlugin return true; } // which action? - if ($action == 'edit') { + if (!empty($status['require_access']) and !in_array(action2access($action), $status['require_access'])) + return false; // allow and fall through, not moderated + if (!empty($status['require_level']) and $request->_user->_level >= $status['require_level']) + return false; // allow and fall through, not moderated + // else all post actions are moderated by default + if (1) /* or in_array($action, array('edit','remove','rename')*/ { //$moderated = $page->get('moderated'); $id = $this->generateId(); while (!empty($moderated[$id])) $id = $this->generateId(); // avoid duplicates - $moderated['id'] = $id; - $moderated['data'][$id] = array('args' => $request->getArgs(), + $moderated['id'] = $id; // overwrite current id + $moderated['data'][$id] = array( // add current request 'timestamp' => time(), - 'userid' => $request->_user->getId()); + 'userid' => $request->_user->getId(), + 'args' => $request->getArgs(), + 'user' => serialize($request->_user), + ); $this->_tokens['CONTENT'] = HTML::div(array('class' => 'wikitext'), fmt("%s: action forwarded to moderator %s", $action, @@ -215,8 +234,10 @@ extends WikiPlugin $subject, $action.': '._("ModeratedPage").' '.$pagename."\n" . serialize($moderated['data'][$id]) - ."\n<".WikiURL($pagename, array('id' => $id,'pass' => 'approve'),1).">" - ."\n<".WikiURL($pagename, array('id' => $id,'pass' => 'reject'),1).">\n" + ."\n<".WikiURL($pagename, array('action' => _("ModeratedPage"), + 'id' => $id, 'pass' => 'approve'), 1).">" + ."\n<".WikiURL($pagename, array('action' => _("ModeratedPage"), + 'id' => $id, 'pass' => 'reject'), 1).">\n" )) { $page->set('moderated', $moderated); return false; // pass thru @@ -231,14 +252,17 @@ extends WikiPlugin /** * Handle admin-side moderation resolve. + * We might have to convert the GET to a POST request to continue with the left-over stored request. */ function approve($args, $moderation) { + // check id, convert to POST, continue ; } /** * Handle admin-side moderation resolve. */ function reject($args, $moderation) { + // check id, delete action ; } @@ -269,6 +293,9 @@ extends WikiPlugin }; // $Log: not supported by cvs2svn $ +// Revision 1.2 2004/11/30 17:46:49 rurban +// added ModeratedPage POST action hook (part 2/3) +// // Revision 1.1 2004/11/19 19:22:35 rurban // ModeratePage part1: change status // diff --git a/lib/plugin/PhotoAlbum.php b/lib/plugin/PhotoAlbum.php index d998c3e13..d3ef085e3 100644 --- a/lib/plugin/PhotoAlbum.php +++ b/lib/plugin/PhotoAlbum.php @@ -1,5 +1,5 @@ run consistency: request as reference, added basepage. // encountered strange bug in AllPages (and the test) which destroys ->_dbi diff --git a/lib/plugin/UnfoldSubpages.php b/lib/plugin/UnfoldSubpages.php index 82f8d5ba4..0e446a878 100644 --- a/lib/plugin/UnfoldSubpages.php +++ b/lib/plugin/UnfoldSubpages.php @@ -1,5 +1,5 @@ * Author: Reini Urban */ +include_once("lib/PageList.php"); class WikiPlugin_UnfoldSubpages extends WikiPlugin { @@ -41,7 +42,7 @@ extends WikiPlugin function getVersion() { return preg_replace("/[Revision: $]/", '', - "\$Revision: 1.17 $"); + "\$Revision: 1.18 $"); } function getDefaultArguments() { @@ -150,6 +151,14 @@ extends WikiPlugin }; // $Log: not supported by cvs2svn $ +// Revision 1.17 2004/11/23 15:17:19 rurban +// better support for case_exact search (not caseexact for consistency), +// plugin args simplification: +// handle and explode exclude and pages argument in WikiPlugin::getArgs +// and exclude in advance (at the sql level if possible) +// handle sortby and limit from request override in WikiPlugin::getArgs +// ListSubpages: renamed pages to maxpages +// // Revision 1.16 2004/09/25 16:35:09 rurban // use stdlib firstNWordsOfContent, extractSection // diff --git a/lib/plugin/WikiAdminChmod.php b/lib/plugin/WikiAdminChmod.php index d58f6f2d4..b6fc76b7e 100644 --- a/lib/plugin/WikiAdminChmod.php +++ b/lib/plugin/WikiAdminChmod.php @@ -1,5 +1,5 @@ new _PageList_Column_perm('perm', _("Permission"))); $pagelist = new PageList_Selectable($args['info'], $args['exclude'], $args); $pagelist->addPageList($pages); @@ -186,17 +187,33 @@ extends WikiPlugin_WikiAdminSelect 'name' => 'admin_chmod[updatechildren]', 'value' => 1)); if (!empty($post_args['updatechildren'])) $checkbox->setAttr('checked','checked'); - $header->pushContent($checkbox, + $header->pushContent($checkbox, HTML::raw(" "), _("Propagate new permissions to all subpages?"), HTML::raw("  "), HTML::em(_("(disable individual page permissions, enable inheritance)?"))); $header->pushContent(HTML::hr(),HTML::p()); return $header; } - } +class _PageList_Column_perm extends _PageList_Column { + function _getValue ($page_handle, &$revision_handle) { + $perm_array = pagePermissions($page_handle->_pagename); + return pagePermissionsSimpleFormat($perm_array, + $page_handle->get('author'), + $page_handle->get('group')); + } +}; + // $Log: not supported by cvs2svn $ +// Revision 1.12 2004/11/23 15:17:19 rurban +// better support for case_exact search (not caseexact for consistency), +// plugin args simplification: +// handle and explode exclude and pages argument in WikiPlugin::getArgs +// and exclude in advance (at the sql level if possible) +// handle sortby and limit from request override in WikiPlugin::getArgs +// ListSubpages: renamed pages to maxpages +// // Revision 1.11 2004/06/16 10:38:59 rurban // Disallow refernces in calls if the declaration is a reference // ("allow_call_time_pass_reference clean"). @@ -256,4 +273,4 @@ extends WikiPlugin_WikiAdminSelect // c-hanging-comment-ender-p: nil // indent-tabs-mode: nil // End: -?> +?> \ No newline at end of file diff --git a/lib/plugin/WikiAdminSelect.php b/lib/plugin/WikiAdminSelect.php index f06268294..2eeb3cd2e 100644 --- a/lib/plugin/WikiAdminSelect.php +++ b/lib/plugin/WikiAdminSelect.php @@ -1,5 +1,5 @@ +?> \ No newline at end of file diff --git a/lib/plugin/WikiAdminUtils.php b/lib/plugin/WikiAdminUtils.php index 9f48e3220..82d0f51e9 100644 --- a/lib/plugin/WikiAdminUtils.php +++ b/lib/plugin/WikiAdminUtils.php @@ -1,7 +1,7 @@ disabled("(action != 'browse')"); $posted = $request->getArg('wikiadminutils'); - $request->setArg('wikiadminutils', false); - if ($request->isPost()) { + if ($request->isPost() and $posted['action'] == $action) { // a different form. we might have multiple $user = $request->getUser(); if (!$user->isAdmin()) { $request->_notAuthorized(WIKIAUTH_ADMIN); @@ -67,10 +72,9 @@ extends WikiPlugin } return $this->do_action($request, $posted); } - if (empty($label)) $label = $default_label; - + return $this->_makeButton($request, $args, $label); } @@ -101,7 +105,8 @@ extends WikiPlugin function _getLabel($action) { $labels = array('purge-cache' => _("Purge Markup Cache"), - 'purge-bad-pagenames' => _("Delete Pages With Invalid Names")); + 'purge-bad-pagenames' => _("Purge all Pages With Invalid Names"), + 'purge-empty-pages' => _("Purge all empty, unreferenced Pages")); return @$labels[$action]; } @@ -117,27 +122,58 @@ extends WikiPlugin function _do_purge_bad_pagenames(&$request, $args) { // FIXME: this should be moved into WikiDB::normalize() or something... $dbi = $request->getDbh(); + $count = 0; + $list = HTML::ol(array('align'=>'left')); $pages = $dbi->getAllPages('include_empty'); // Do we really want the empty ones too? - $badpages = array(); while (($page = $pages->next())) { $pagename = $page->getName(); $wpn = new WikiPageName($pagename); - if (! $wpn->isValid()) - $badpages[] = $pagename; + if (! $wpn->isValid()) { + $dbi->purgePage($pagename); + $list->pushContent(HTML::li($pagename)); + $count++; + } } - - if (!$badpages) + $pages->free(); + if (!$count) return _("No pages with bad names were found."); - - $list = HTML::ul(); - foreach ($badpages as $pagename) { - $dbi->deletePage($pagename); - $list->pushContent(HTML::li($pagename)); + else { + return HTML(fmt("Deleted %s pages with invalid names:", $count), + HTML::div(array('align'=>'left'), $list)); } - - return HTML(fmt("Deleted %s pages with invalid names:", - count($badpages)), - $list); + } + + /** + * Purge all non-referenced empty pages. Mainly those created by bad link extraction. + */ + function _do_purge_empty_pages(&$request, $args) { + $dbi = $request->getDbh(); + $count = 0; $notpurgable = 0; + $list = HTML::ol(array('align'=>'left')); + $pages = $dbi->getAllPages('include_empty'); + while (($page = $pages->next())) { + if (!$page->exists() and ($links = $page->getBackLinks('include_empty')) and !$links->next()) { + $pagename = $page->getName(); + if ($pagename == 'global_data' or $pagename == '.') continue; + if ($dbi->purgePage($pagename)) + $list->pushContent(HTML::li($pagename.' '._("[purged]"))); + else { + $list->pushContent(HTML::li($pagename.' '._("[not purgable]"))); + $notpurgable++; + } + $count++; + } + } + $pages->free(); + if (!$count) + return _("No empty, unreferenced pages were found."); + else + return HTML(fmt("Deleted %s unreferenced pages:", $count), + HTML::div(array('align'=>'left'), $list), + ($notpurgable ? + fmt("The %d not-purgable pages/links are links in some page(s). You might want to edit them.", + $notpurgable) + : '')); } //TODO: We need a seperate plugin for this. diff --git a/lib/removepage.php b/lib/removepage.php index 3c528bd27..423252843 100644 --- a/lib/removepage.php +++ b/lib/removepage.php @@ -1,5 +1,5 @@ getCurrentRevision(); - $version = $current->getVersion(); - if (!$version) { + if (!$current or !($version = $current->getVersion())) { $html = HTML(HTML::h2(_("Already deleted")), HTML::p(_("Sorry, this page is not in the database."))); } @@ -23,7 +22,6 @@ function RemovePage (&$request) { $removeB = Button('submit:verify', _("Remove Page"), 'wikiadmin'); $cancelB = Button('submit:cancel', _("Cancel"), 'button'); // use generic wiki button look - $sample = firstNWordsOfContent(100, $current->getPackedContent()); $html = HTML(HTML::h2(fmt("You are about to remove '%s' permanently!", $pagelink)), HTML::form(array('method' => 'post', @@ -36,9 +34,15 @@ function RemovePage (&$request) { $removeB, $WikiTheme->getButtonSeparator(), $cancelB)), - HTML::hr(), - HTML::div(array('class' => 'transclusion'), $sample) + HTML::hr() ); + $sample = HTML::div(array('class' => 'transclusion')); + // simple and fast preview expanding only newlines + foreach (explode("\n", firstNWordsOfContent(100, $current->getPackedContent())) as $s) { + $sample->pushContent($s, HTML::br()); + } + $html->pushContent(HTML::div(array('class' => 'wikitext'), + $sample)); } elseif ($request->getArg('currentversion') != $version) { $html = HTML(HTML::h2(_("Someone has edited the page!")), diff --git a/lib/spam_babycart.php b/lib/spam_babycart.php index b7e81f9cb..8748e1a04 100644 --- a/lib/spam_babycart.php +++ b/lib/spam_babycart.php @@ -1,7 +1,7 @@ * Proof-of-concept PHP fragment to flag blog/wiki spam * @@ -14,8 +14,10 @@ rcs_id('$Id: spam_babycart.php,v 1.1 2004-12-04 12:58:26 rurban Exp $'); function check_babycart(&$text, $ip, $user_id='') { // $X_babycart = '/usr/bin/perl /home/apthorpe/pjx/babycart/babycart'; // cygwin: - // $X_babycart = 'n:/bin/perl /usr/local/bin/babycart'; - $X_babycart = '/usr/local/bin/babycart'; + if (!defined('BABYCART_PATH')) + define('BABYCART_PATH', '/usr/local/bin/babycart'); + // cygwin: + //$X_babycart = 'n:/bin/perl /usr/local/bin/babycart'; $comment = "IP: $ip\n"; $subject = $GLOBALS['request']->getArg('pagename'); @@ -24,7 +26,7 @@ function check_babycart(&$text, $ip, $user_id='') { $comment .= $text; $descriptorspec = array(0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w")); - $process = proc_open($X_babycart, $descriptorspec, $pipes); + $process = proc_open(BABYCART_PATH, $descriptorspec, $pipes); if (is_resource($process)) { // $pipes now looks like this: // 0 => writeable handle connected to child stdin @@ -70,7 +72,7 @@ function check_babycart(&$text, $ip, $user_id='') { return explode(',', $response, 4); } } - trigger_error("Couldn't process $X_babycart.\n".$error, E_USER_WARNING); + trigger_error("Couldn't process ".BABYCART_PATH.".\n".$error, E_USER_WARNING); return -1; // process error } ?> \ No newline at end of file diff --git a/lib/stdlib.php b/lib/stdlib.php index ea2c9c068..469589ec6 100644 --- a/lib/stdlib.php +++ b/lib/stdlib.php @@ -1,4 +1,4 @@ -HTML_DUMP_SUFFIX)) { - $url = $get_abs_url ? SERVER_URL . VIRTUAL_PATH . "/" : ""; - $url .= preg_replace('/%2f/i', '/', rawurlencode($pagename)); + $url = $get_abs_url ? (SERVER_URL . VIRTUAL_PATH . "/") : ""; + $url = $url . preg_replace('/%2f/i', '/', rawurlencode($pagename)); if (!empty($GLOBALS['WikiTheme']->HTML_DUMP_SUFFIX)) $url .= $GLOBALS['WikiTheme']->HTML_DUMP_SUFFIX; if ($args) @@ -1761,10 +1761,11 @@ function extractSection ($section, $content, $page, $quiet = false, $sectionhead return array(sprintf(_("<%s: no such section>"), $mesg)); } +// use this faster version: only load ExternalReferrer if we came from an external referrer function isExternalReferrer(&$request) { if ($referrer = $request->get('HTTP_REFERER')) { - $home = SCRIPT_NAME; // was SERVER_URL, but we want to check sister wiki's also - if (substr(strtolower($referrer),0,strlen($home)) == strtolower($home)) return false; + $home = SERVER_URL; // SERVER_URL or SCRIPT_NAME, if we want to check sister wiki's also + if (string_starts_with(strtolower($referrer), strtolower($home))) return false; require_once("lib/ExternalReferrer.php"); $se = new SearchEngines(); return $se->parseSearchQuery($referrer); @@ -1814,6 +1815,9 @@ function printSimpleTrace($bt) { } // $Log: not supported by cvs2svn $ +// Revision 1.220 2004/11/30 17:47:41 rurban +// added mt_srand, check for native isa +// // Revision 1.219 2004/11/26 18:39:02 rurban // new regex search parser and SQL backends (90% complete, glob and pcre backends missing) // -- 2.45.0