Index: trunk/phase3/includes/DefaultSettings.php =================================================================== --- trunk/phase3/includes/DefaultSettings.php (revision 3118) +++ trunk/phase3/includes/DefaultSettings.php (revision 3119) @@ -1,337 +1,340 @@ "; # For using a direct (authenticated) SMTP server connection. # "host" => 'SMTP domain', "IDHost" => 'domain for MessageID', "port" => "25", "auth" => true/false, "username" => user, "password" => password $wgSMTP = false; # MySQL settings # $wgDBserver = "localhost"; $wgDBname = "wikidb"; $wgDBconnection = ""; $wgDBuser = "wikiuser"; # Sysop SQL queries $wgAllowSysopQueries = false; # Dangerous if not configured properly. $wgDBsqluser = "sqluser"; $wgDBsqlpassword = "sqlpass"; $wgDBpassword = "userpass"; $wgSqlLogFile = "{$wgUploadDirectory}/sqllog_mFhyRe6"; $wgDBminWordLen = 4; $wgDBtransactions = false; # Set to true if using InnoDB tables $wgDBmysql4 = false; # Set to true to use enhanced fulltext search $wgSqlTimeout = 30; # Other wikis on this site, can be administered from a single developer account # Array, interwiki prefix => database name $wgLocalDatabases = array(); # Database load balancer $wgDBservers = false; # e.g. array("larousse", "pliny") $wgDBloads = false; # e.g. array(0.6, 0.4); # memcached settings # See docs/memcached.doc # $wgMemCachedDebug = false; # Will be set to false in Setup.php, if the server isn't working $wgUseMemCached = false; $wgMemCachedServers = array( "127.0.0.1:11000" ); $wgMemCachedDebug = false; $wgSessionsInMemcached = false; $wgLinkCacheMemcached = false; # Not fully tested # Language settings # $wgLanguageCode = "en"; $wgLanguageFile = false; # Filename of a language file generated by dumpMessages.php $wgInterwikiMagic = true; # Treat language links as magic connectors, not inline links $wgInputEncoding = "ISO-8859-1"; $wgOutputEncoding = "ISO-8859-1"; $wgEditEncoding = ""; $wgMimeType = "text/html"; $wgDocType = "-//W3C//DTD XHTML 1.0 Transitional//EN"; $wgDTD = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"; $wgUseDynamicDates = false; # Enable to allow rewriting dates in page text # DOES NOT FORMAT CORRECTLY FOR MOST LANGUAGES $wgAmericanDates = false; # Enable for English module to print dates # as eg 'May 12' instead of '12 May' $wgLocalInterwiki = "w"; $wgShowIPinHeader = true; # For non-logged in users $wgMaxNameChars = 32; # Maximum number of bytes in username # Translation using MediaWiki: namespace # This will increase load times by 25-60% unless memcached is installed $wgUseDatabaseMessages = true; $wgMsgCacheExpiry = 86400; $wgExtraSubtitle = ""; $wgSiteSupportPage = ""; # Miscellaneous configuration settings # $wgReadOnlyFile = "{$wgUploadDirectory}/lock_yBgMBwiR"; # The debug log file should be not be publically accessible if it is # used, as it may contain private data. $wgDebugLogFile = ""; $wgDebugRedirects = false; $wgDebugComments = false; $wgReadOnly = false; $wgLogQueries = false; $wgDebugDumpSql = false; $wgUseCategoryMagic = false; $wgEnablePersistentLC = false; # Persistent link cache in linkscc table; FAILS on MySQL 3.x $wgCompressedPersistentLC = true; # use gzcompressed blobs $wgEnableParserCache = false; # requires that php was compiled --with-zlib # wgHitcounterUpdateFreq sets how often page counters should be # updated, higher values are easier on the database. A value of 1 # causes the counters to be updated on every hit, any higher value n # cause them to update *on average* every n hits. Should be set to # either 1 or something largish, eg 1000, for maximum efficiency. $wgHitcounterUpdateFreq = 1; # User rights $wgWhitelistEdit = false; # true = user must login to edit. $wgWhitelistRead = false; # Pages anonymous user may see, like: = array ( ":Main_Page", "Special:Userlogin", "Wikipedia:Help"); $wgWhitelistAccount = array ( "user" => 1, "sysop" => 1, "developer" => 1 ); $wgSysopUserBans = false; # Allow sysops to ban logged-in users $wgSysopRangeBans = false; # Allow sysops to ban IP ranges $wgDefaultBlockExpiry = "24 hours"; # default expiry time # strtotime format, or "infinite" for an infinite block $wgAutoblockExpiry = 86400; # Number of seconds before autoblock entries expire $wgBlockOpenProxies = false; # Automatic open proxy test on edit $wgProxyPorts = array( 80, 81, 1080, 3128, 6588, 8000, 8080, 8888, 65506 ); $wgProxyScriptPath = "$IP/proxy_check.php"; $wgProxyMemcExpiry = 86400; $wgProxyKey = "W1svekXc5u6lZllTZOwnzEk1nbs"; # Client-side caching: $wgCachePages = true; # Allow client-side caching of pages # Set this to current time to invalidate all prior cached pages. # Affects both client- and server-side caching. $wgCacheEpoch = "20030516000000"; # Server-side caching: # This will cache static pages for non-logged-in users # to reduce database traffic on public sites. # Must set $wgShowIPinHeader = false $wgUseFileCache = false; $wgFileCacheDirectory = "{$wgUploadDirectory}/cache"; $wgCookieExpiration = 2592000; # Squid-related settings # # Enable/disable Squid $wgUseSquid = false; # If you run Squid3 with ESI support, enable this (default:false): $wgUseESI = false; # Internal server name as known to Squid, if different # $wgInternalServer = 'http://yourinternal.tld:8000'; $wgInternalServer = $wgServer; # Cache timeout for the squid, will be sent as s-maxage (without ESI) or # Surrogate-Control (with ESI). Without ESI, you should strip out s-maxage in the Squid config. # 18000 seconds = 5 hours, more cache hits with 2678400 = 31 days $wgSquidMaxage = 18000; # A list of proxy servers (ips if possible) to purge on changes # don't specify ports here (80 is default) # $wgSquidServers = array('127.0.0.1'); # Set to set an explicit domain on the login cookies # eg, "justthis.domain.org" or ".any.subdomain.net" $wgCookieDomain = ""; $wgCookiePath = "/"; $wgDisableCookieCheck = false; $wgAllowExternalImages = true; $wgMiserMode = false; # Disable database-intensive features $wgDisableQueryPages = false; # Disable all query pages if miser mode is on, not just some $wgUseWatchlistCache = false; # Generate a watchlist once every hour or so $wgWLCacheTimeout = 3600; # The hour or so mentioned above # To use inline TeX, you need to compile 'texvc' (in the 'math' subdirectory # of the MediaWiki package and have latex, dvips, gs (ghostscript), and # convert (ImageMagick) installed and available in the PATH. # Please see math/README for more information. $wgUseTeX = false; $wgTexvc = "./math/texvc"; # Location of the texvc binary # Support for inline hieroglyphs, see http://aoineko.free.fr/ The # WikiHiero php files must be present in the same directory as the # rest of the mediawiki code, and WikiHiero must have been configured # with the correct image locations. $wgUseWikiHiero = false; # Profiling / debugging $wgProfiling = false; # Enable for more detailed by-function times in debug log $wgProfileLimit = 0.0; # Only record profiling info for pages that took longer than this $wgProfileOnly = false; # Don't put non-profiling info into log file $wgProfileToDatabase = false; # Log sums from profiling into "profiling" table in db. $wgProfileSampleRate = 1; # Only profile every n requests when profiling is turned on $wgDebugProfiling = false; # Detects non-matching wfProfileIn/wfProfileOut calls $wgDebugFunctionEntry = 0; # Output debug message on every wfProfileIn/wfProfileOut $wgDisableCounters = false; $wgDisableTextSearch = false; $wgDisableFuzzySearch = false; $wgDisableSearchUpdate = false; # If you've disabled search semi-permanently, this also disables updates to the table. If you ever re-enable, be sure to rebuild the search table. $wgDisableUploads = true; # Uploads have to be specially set up to be secure $wgRemoteUploads = false; # Set to true to enable the upload _link_ while local uploads are disabled. Assumes that the special page link will be bounced to another server where uploads do work. $wgDisableAnonTalk = false; # We can serve pages compressed in order to save bandwidth, # but this will increase CPU usage. # Requires zlib support enabled in PHP. $wgUseGzip = function_exists( "gzencode" ); # Path to the GNU diff3 utility. If the file doesn't exist, # edit conflicts will fall back to the old behaviour (no merging). $wgDiff3 = "/usr/bin/diff3"; # We can also compress text in the old revisions table. If this is set on, # old revisions will be compressed on page save if zlib support is available. # Any compressed revisions will be decompressed on load regardless of this # setting *but will not be readable at all* if zlib support is not available. $wgCompressRevisions = false; # This is the list of preferred extensions for uploading files. Uploading # files with extensions not in this list will trigger a warning. $wgFileExtensions = array( "png", "jpg", "jpeg", "ogg" ); # Files with these extensions will never be allowed as uploads. $wgFileBlacklist = array( # HTML may contain cookie-stealing JavaScript and web bugs "html", "htm", # PHP scripts may execute arbitrary code on the server "php", "phtml", "php3", "php4", "phps", # Other types that may be interpreted by some servers "shtml", "jhtml", "pl", "py", # May contain harmful executables for Windows victims "exe", "scr", "dll", "msi", "vbs", "bat", "com", "pif", "cmd", "vxd", "cpl" ); # This is a flag to determine whether or not to check file extensions on # upload. $wgCheckFileExtensions = true; # If this is turned off, users may override the warning for files not # covered by $wgFileExtensions. $wgStrictFileExtensions = true; $wgPasswordSalt = true; # For compatibility with old installations set to false # Which namespaces should support subpages? # See Language.php for a list of namespaces. # $wgNamespacesWithSubpages = array( -1 => 0, 0 => 0, 1 => 1, 2 => 1, 3 => 1, 4 => 0, 5 => 1, 6 => 0, 7 => 1, 8 => 0, 9 => 1, 10 => 0, 11 => 1); $wgNamespacesToBeSearchedDefault = array( -1 => 0, 0 => 1, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 1, 10 => 0, 11 => 1 ); # If set, a bold ugly notice will show up at the top of every page. $wgSiteNotice = ""; # Whether to allow anonymous users to set changes to 'minor' $wgAllowAnonymousMinor = false; ## Set $wgUseImageResize to true if you want to enable dynamic ## server side image resizing ("Thumbnails") # $wgUseImageResize = false; ## Resizing can be done using PHP's internal image libraries ## or using ImageMagick. The later supports more file formats ## than PHP, which only supports PNG, GIF, JPG, XBM and WBMP. ## ## Set $wgUseImageMagick to true to use Image Magick instead ## of the builtin functions # $wgUseImageMagick = false; $wgImageMagickConvertCommand = "/usr/bin/convert"; -# Enable experimental smarty skins (put Smarty/libs in your include_path!) -$wgUseSmarty = false; -$wgUsePHPTal = false; +# Make sure include_path is set correctly +$wgUsePHPTal = true; if( !isset( $wgCommandLineMode ) ) { $wgCommandLineMode = false; } # Show seconds in Recent Changes $wgRCSeconds = false; # RDF metadata toggles - $wgEnableDublinCoreRdf = false; $wgEnableCreativeCommonsRdf = false; # Override for copyright metadata. - $wgRightsPage = NULL; $wgRightsUrl = NULL; $wgRightsText = NULL; +$wgRightsIcon = NULL; # Set this to false to avoid forcing the first letter of links # to capitals. WARNING: may break links! This makes links # COMPLETELY case-sensitive. Links appearing with a capital at # the beginning of a sentence will *not* go to the same place # as links in the middle of a sentence using a lowercase initial. $wgCapitalLinks = true; +# List of interwiki prefixes for wikis we'll accept as sources +# for Special:Import (for sysops). Since complete page history +# can be imported, these should be 'trusted'. +$wgImportSources = array(); + ?> Index: trunk/phase3/includes/SpecialImport.php =================================================================== --- trunk/phase3/includes/SpecialImport.php (revision 3118) +++ trunk/phase3/includes/SpecialImport.php (revision 3119) @@ -1,418 +1,487 @@ # http://www.mediawiki.org/ # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # http://www.gnu.org/copyleft/gpl.html function wfSpecialImport( $page = "" ) { global $wgOut, $wgLang, $wgRequest, $wgTitle; + global $wgImportSources; if( $wgRequest->wasPosted() && $wgRequest->getVal( 'action' ) == 'submit') { $importer = new WikiImporter(); - if( $importer->setupFromUpload( "xmlimport" ) ) { + + switch( $wgRequest->getVal( "source" ) ) { + case "upload": + $ok = $importer->setupFromUpload( "xmlimport" ); + break; + case "interwiki": + $ok = $importer->setupFromInterwiki( + $wgRequest->getVal( "interwiki" ), + $wgRequest->getText( "frompage" ) ); + break; + default: + $ok = false; + } + + if( $ok ) { $importer->setRevisionHandler( "wfImportOldRevision" ); if( $importer->doImport() ) { # Success! $wgOut->addHTML( "

" . wfMsg( "importsuccess" ) . "

" ); } else { $wgOut->addHTML( "

" . wfMsg( "importfailed", htmlspecialchars( $importer->getError() ) ) . "

" ); } } else { $wgOut->addWikiText( htmlspecialchars( $importer->getError() ) ); } } $wgOut->addWikiText( "

" . wfMsg( "importtext" ) . "

" ); $action = $wgTitle->escapeLocalUrl(); $wgOut->addHTML( " -
- - -
- -
+
+ Upload XML +
+ + + + + +
+
+" ); + + if( !empty( $wgImportSources ) ) { + $wgOut->addHTML( " +
+ Interwiki import +
+ + + + + +
+
" ); + } } -function wfImportOldRevision( $revision ) { +function wfImportOldRevision( &$revision ) { global $wgOut; $fname = "wfImportOldRevision"; # Sneak a single revision into place $ns = IntVal( $revision->title->getNamespace() ); $t = wfStrencode( $revision->title->getDBkey() ); $text = wfStrencode( $revision->getText() ); $ts = wfStrencode( $revision->timestamp ); $its = wfStrencode( wfInvertTimestamp( $revision->timestamp ) ) ; $comment = wfStrencode( $revision->getComment() ); $user = User::newFromName( $revision->getUser() ); $user_id = IntVal( $user->getId() ); $user_text = wfStrencode( $user->getName() ); $minor = 0; # ?? $flags = ""; # Make sure it doesn't already exist $sql = "SELECT 1 FROM old WHERE old_namespace=$ns AND old_title='$t' AND old_timestamp='$ts'"; - $wgOut->addHtml( htmlspecialchars( $sql ) . "
\n" ); - $res = wfQuery( $sql, DB_WRITE, $fname ); $numrows = wfNumRows( $res ); wfFreeResult( $res ); if( $numrows > 0 ) { - $wgOut->addHTML( "DIE
" ); - return false; + return wfMsg( "importhistoryconflict" ); } $res = wfQuery( "INSERT INTO old " . "(old_namespace,old_title,old_text,old_comment,old_user,old_user_text," . "old_timestamp,inverse_timestamp,old_minor_edit,old_flags) " . "VALUES ($ns,'$t','$text','$comment',$user_id,'$user_text','$ts','$its',$minor,'$flags')", DB_WRITE, $fname ); - $wgOut->addHTML( "OK
" ); - return true; + return wfMsg( "ok" ); } class WikiRevision { var $title = NULL; var $timestamp = "20010115000000"; var $user = 0; var $user_text = ""; var $text = ""; var $comment = ""; function setTitle( $text ) { $text = $this->fixEncoding( $text ); $this->title = Title::newFromText( $text ); } function setTimestamp( $ts ) { # 2003-08-05T18:30:02Z $this->timestamp = preg_replace( '/^(....)-(..)-(..)T(..):(..):(..)Z$/', '$1$2$3$4$5$6', $ts ); } function setUsername( $user ) { $this->user_text = $this->fixEncoding( $user ); } function setUserIP( $ip ) { $this->user_text = $this->fixEncoding( $ip ); } function setText( $text ) { $this->text = $this->fixEncoding( $text ); } function setComment( $text ) { $this->comment = $this->fixEncoding( $text ); } function fixEncoding( $data ) { global $wgLang, $wgInputEncoding; if( strcasecmp( $wgInputEncoding, "utf-8" ) == 0 ) { return $data; } else { return $wgLang->iconv( "utf-8", $wgInputEncoding, $data ); } } function getTitle() { return $this->title; } function getTimestamp() { return $this->timestamp; } function getUser() { return $this->user_text; } function getText() { return $this->text; } function getComment() { return $this->comment; } } class WikiImporter { var $mSource = NULL; var $mError = ""; var $mXmlError = XML_ERROR_NONE; var $mRevisionHandler = NULL; var $lastfield; function WikiImporter() { $this->setRevisionHandler( array( &$this, "defaultRevisionHandler" ) ); } function setError( $err ) { $this->mError = $err; return false; } function getError() { if( $this->mXmlError == XML_ERROR_NONE ) { return $this->mError; } else { return xml_error_string( $this->mXmlError ); } } function throwXmlError( $err ) { $this->debug( "FAILURE: $err" ); } function setupFromFile( $filename ) { $this->mSource = file_get_contents( $filename ); return true; } function setupFromUpload( $fieldname = "xmlimport" ) { global $wgOut; $upload =& $_FILES[$fieldname]; if( !isset( $upload ) ) { return $this->setError( wfMsg( "importnofile" ) ); } if( !empty( $upload['error'] ) ) { return $this->setError( wfMsg( "importuploaderror", $upload['error'] ) ); } $fname = $upload['tmp_name']; if( is_uploaded_file( $fname ) ) { return $this->setupFromFile( $fname ); } else { return $this->setError( wfMsg( "importnofile" ) ); } } function setupFromURL( $url ) { - # FIXME - wfDebugDieBacktrace( "Not yet implemented." ); + # fopen-wrappers are normally turned off for security. + ini_set( "allow_url_fopen", true ); + $ret = $this->setupFromFile( $url ); + ini_set( "allow_url_fopen", false ); + return $ret; } + function setupFromInterwiki( $interwiki, $page ) { + $base = Title::getInterwikiLink( $interwiki ); + if( empty( $base ) ) { + return false; + } else { + $import = wfUrlencode( "Special:Export/$page" ); + $url = str_replace( "$1", $import, $base ); + $this->notice( "Importing from $url" ); + return $this->setupFromURL( $url ); + } + } + + # -------------- + function doImport() { if( empty( $this->mSource ) ) { return $this->setError( wfMsg( "importnotext" ) ); } $parser = xml_parser_create( "UTF-8" ); # case folding violates XML standard, turn it off xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false ); xml_set_object( $parser, &$this ); xml_set_element_handler( $parser, "in_start", "" ); if( !xml_parse( $parser, $this->mSource, true ) ) { # return error message $this->mXmlError = xml_get_error_code( $parser ); xml_parser_free( $parser ); return false; } xml_parser_free( $parser ); return true; } function debug( $data ) { global $wgOut; - # $wgOut->addHTML( htmlspecialchars( $data ) . "
\n" ); + # $this->notice( "DEBUG: $data\n" ); + } + + function notice( $data ) { + global $wgCommandLineMode; + if( $wgCommandLineMode ) { + print "$data\n"; + } else { + global $wgOut; + $wgOut->addHTML( "
  • $data
  • \n" ); + } } function setRevisionHandler( $functionref ) { $this->mRevisionHandler = $functionref; } - function defaultRevisionHandler( $revision ) { + function defaultRevisionHandler( &$revision ) { $this->debug( "Got revision:" ); if( is_object( $revision->title ) ) { $this->debug( "-- Title: " . $revision->title->getPrefixedText() ); } else { $this->debug( "-- Title: " ); } $this->debug( "-- User: " . $revision->user_text ); $this->debug( "-- Timestamp: " . $revision->timestamp ); $this->debug( "-- Comment: " . $revision->comment ); $this->debug( "-- Text: " . $revision->text ); } # XML parser callbacks from here out -- beware! function donothing( $parser, $x, $y="" ) { #$this->debug( "donothing" ); } function in_start( $parser, $name, $attribs ) { $this->debug( "in_start $name" ); if( $name != "mediawiki" ) { return $this->throwXMLerror( "Expected , got <$name>" ); } xml_set_element_handler( $parser, "in_mediawiki", "out_mediawiki" ); } function in_mediawiki( $parser, $name, $attribs ) { $this->debug( "in_mediawiki $name" ); if( $name != "page" ) { return $this->throwXMLerror( "Expected , got <$name>" ); } xml_set_element_handler( $parser, "in_page", "out_page" ); } function out_mediawiki( $parser, $name ) { $this->debug( "out_mediawiki $name" ); if( $name != "mediawiki" ) { return $this->throwXMLerror( "Expected , got " ); } xml_set_element_handler( $parser, "donothing", "donothing" ); } function in_page( $parser, $name, $attribs ) { $this->debug( "in_page $name" ); switch( $name ) { case "id": case "title": case "restrictions": $this->appendfield = $name; $this->appenddata = ""; $this->parenttag = "page"; xml_set_element_handler( $parser, "in_nothing", "out_append" ); xml_set_character_data_handler( $parser, "char_append" ); break; case "revision": $this->workRevision = new WikiRevision; $this->workRevision->setTitle( $this->workTitle ); xml_set_element_handler( $parser, "in_revision", "out_revision" ); break; default: return $this->throwXMLerror( "Element <$name> not allowed in a ." ); } } function out_page( $parser, $name ) { $this->debug( "out_page $name" ); if( $name != "page" ) { return $this->throwXMLerror( "Expected , got " ); } xml_set_element_handler( $parser, "in_mediawiki", "out_mediawiki" ); $this->workTitle = NULL; $this->workRevision = NULL; } function in_nothing( $parser, $name, $attribs ) { $this->debug( "in_nothing $name" ); return $this->throwXMLerror( "No child elements allowed here; got <$name>" ); } function char_append( $parser, $data ) { $this->debug( "char_append '$data'" ); $this->appenddata .= $data; } function out_append( $parser, $name ) { $this->debug( "out_append $name" ); if( $name != $this->appendfield ) { return $this->throwXMLerror( "Expected appendfield}>, got " ); } xml_set_element_handler( $parser, "in_$this->parenttag", "out_$this->parenttag" ); xml_set_character_data_handler( $parser, "donothing" ); switch( $this->appendfield ) { case "title": $this->workTitle = $this->appenddata; break; case "text": $this->workRevision->setText( $this->appenddata ); break; case "username": $this->workRevision->setUsername( $this->appenddata ); break; case "ip": $this->workRevision->setUserIP( $this->appenddata ); break; case "timestamp": $this->workRevision->setTimestamp( $this->appenddata ); break; case "comment": $this->workRevision->setComment( $this->appenddata ); break; default; $this->debug( "Bad append: {$this->appendfield}" ); } $this->appendfield = ""; $this->appenddata = ""; } function in_revision( $parser, $name, $attribs ) { $this->debug( "in_revision $name" ); switch( $name ) { case "id": case "timestamp": case "comment": case "text": $this->parenttag = "revision"; $this->appendfield = $name; xml_set_element_handler( $parser, "in_nothing", "out_append" ); xml_set_character_data_handler( $parser, "char_append" ); break; case "contributor": xml_set_element_handler( $parser, "in_contributor", "out_contributor" ); break; default: return $this->throwXMLerror( "Element <$name> not allowed in a ." ); } } + function out_revision( $parser, $name ) { $this->debug( "out_revision $name" ); if( $name != "revision" ) { return $this->throwXMLerror( "Expected , got " ); } xml_set_element_handler( $parser, "in_page", "out_page" ); - call_user_func( $this->mRevisionHandler, $this->workRevision ); + $out = call_user_func( $this->mRevisionHandler, &$this->workRevision, &$this ); + if( !empty( $out ) ) { + global $wgOut; + $wgOut->addHTML( "
  • " . $out . "
  • \n" ); + } } function in_contributor( $parser, $name, $attribs ) { $this->debug( "in_contributor $name" ); switch( $name ) { case "username": case "ip": $this->parenttag = "contributor"; $this->appendfield = $name; xml_set_element_handler( $parser, "in_nothing", "out_append" ); xml_set_character_data_handler( $parser, "char_append" ); break; default: $this->throwXMLerror( "Invalid tag <$name> in " ); } } function out_contributor( $parser, $name ) { $this->debug( "out_contributor $name" ); if( $name != "contributor" ) { return $this->throwXMLerror( "Expected , got " ); } xml_set_element_handler( $parser, "in_revision", "out_revision" ); } } ?>