1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2024-10-27 20:34:16 +00:00

Xomw: Add title parsing

This commit is contained in:
gnosygnu 2017-02-09 08:45:15 -05:00
parent 0cdd3d437f
commit 0eee0f0207
8 changed files with 2415 additions and 959 deletions

View File

@ -0,0 +1,311 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.mediawiki.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*;
public class Xomw_Defines {
// /**
// * @defgroup Constants MediaWiki constants
// */
//
// /**@{
// * Database related constants
// */
// define( 'DBO_DEBUG', 1 );
// define( 'DBO_NOBUFFER', 2 );
// define( 'DBO_IGNORE', 4 );
// define( 'DBO_TRX', 8 ); // automatically start transaction on first query
// define( 'DBO_DEFAULT', 16 );
// define( 'DBO_PERSISTENT', 32 );
// define( 'DBO_SYSDBA', 64 ); // for oracle maintenance
// define( 'DBO_DDLMODE', 128 ); // when using schema files: mostly for Oracle
// define( 'DBO_SSL', 256 );
// define( 'DBO_COMPRESS', 512 );
// /**@}*/
//
// /**@{
// * Valid database indexes
// * Operation-based indexes
// */
// define( 'DB_SLAVE', -1 ); # Read from the slave (or only server)
// define( 'DB_MASTER', -2 ); # Write to master (or only server)
// /**@}*/
//
// # Obsolete aliases
// define( 'DB_READ', -1 );
// define( 'DB_WRITE', -2 );
/**@{
* Virtual namespaces; don't appear in the page database
*/
public static final int NS_MEDIA = -2;
public static final int NS_SPECIAL = -1;
/**@}*/
/**@{
* Real namespaces
*
* Number 100 and beyond are reserved for custom namespaces;
* DO NOT assign standard namespaces at 100 or beyond.
* DO NOT Change integer values as they are most probably hardcoded everywhere
* see bug #696 which talked about that.
*/
public static final int NS_MAIN = 0;
public static final int NS_TALK = 1;
public static final int NS_USER = 2;
public static final int NS_USER_TALK = 3;
public static final int NS_PROJECT = 4;
public static final int NS_PROJECT_TALK = 5;
public static final int NS_FILE = 6;
public static final int NS_FILE_TALK = 7;
public static final int NS_MEDIAWIKI = 8;
public static final int NS_MEDIAWIKI_TALK = 9;
public static final int NS_TEMPLATE = 10;
public static final int NS_TEMPLATE_TALK = 11;
public static final int NS_HELP = 12;
public static final int NS_HELP_TALK = 13;
public static final int NS_CATEGORY = 14;
public static final int NS_CATEGORY_TALK = 15;
// /**
// * NS_IMAGE and NS_IMAGE_TALK are the pre-v1.14 names for NS_FILE and
// * NS_FILE_TALK respectively, and are kept for compatibility.
// *
// * When writing code that should be compatible with older MediaWiki
// * versions, either stick to the old names or define the new constants
// * yourself, if they're not defined already.
// */
// define( 'NS_IMAGE', NS_FILE );
// define( 'NS_IMAGE_TALK', NS_FILE_TALK );
// /**@}*/
//
// /**@{
// * Cache type
// */
// define( 'CACHE_ANYTHING', -1 ); // Use anything, as long as it works
// define( 'CACHE_NONE', 0 ); // Do not cache
// define( 'CACHE_DB', 1 ); // Store cache objects in the DB
// define( 'CACHE_MEMCACHED', 2 ); // MemCached, must specify servers in $wgMemCacheServers
// define( 'CACHE_ACCEL', 3 ); // APC, XCache or WinCache
// /**@}*/
//
// /**@{
// * Media types.
// * This defines constants for the value returned by File::getMediaType()
// */
// // unknown format
// define( 'MEDIATYPE_UNKNOWN', 'UNKNOWN' );
// // some bitmap image or image source (like psd, etc). Can't scale up.
// define( 'MEDIATYPE_BITMAP', 'BITMAP' );
// // some vector drawing (SVG, WMF, PS, ...) or image source (oo-draw, etc). Can scale up.
// define( 'MEDIATYPE_DRAWING', 'DRAWING' );
// // simple audio file (ogg, mp3, wav, midi, whatever)
// define( 'MEDIATYPE_AUDIO', 'AUDIO' );
// // simple video file (ogg, mpg, etc;
// // no not include formats here that may contain executable sections or scripts!)
// define( 'MEDIATYPE_VIDEO', 'VIDEO' );
// // Scriptable Multimedia (flash, advanced video container formats, etc)
// define( 'MEDIATYPE_MULTIMEDIA', 'MULTIMEDIA' );
// // Office Documents, Spreadsheets (office formats possibly containing apples, scripts, etc)
// define( 'MEDIATYPE_OFFICE', 'OFFICE' );
// // Plain text (possibly containing program code or scripts)
// define( 'MEDIATYPE_TEXT', 'TEXT' );
// // binary executable
// define( 'MEDIATYPE_EXECUTABLE', 'EXECUTABLE' );
// // archive file (zip, tar, etc)
// define( 'MEDIATYPE_ARCHIVE', 'ARCHIVE' );
// /**@}*/
//
// /**@{
// * Antivirus result codes, for use in $wgAntivirusSetup.
// */
// define( 'AV_NO_VIRUS', 0 ); # scan ok, no virus found
// define( 'AV_VIRUS_FOUND', 1 ); # virus found!
// define( 'AV_SCAN_ABORTED', -1 ); # scan aborted, the file is probably immune
// define( 'AV_SCAN_FAILED', false ); # scan failed (scanner not found or error in scanner)
// /**@}*/
//
// /**@{
// * Anti-synchronized flags
// * Was used by $wgAntiLockFlags, which was removed with 1.25
// * Constants kept to not have warnings when used in LocalSettings
// */
// define( 'ALF_PRELOAD_LINKS', 1 ); // unused
// define( 'ALF_PRELOAD_EXISTENCE', 2 ); // unused
// define( 'ALF_NO_LINK_LOCK', 4 ); // unused
// define( 'ALF_NO_BLOCK_LOCK', 8 ); // unused
// /**@}*/
//
// /**@{
// * Date format selectors; used in user preference storage and by
// * Language::date() and co.
// */
// define( 'MW_DATE_DEFAULT', 'default' );
// define( 'MW_DATE_MDY', 'mdy' );
// define( 'MW_DATE_DMY', 'dmy' );
// define( 'MW_DATE_YMD', 'ymd' );
// define( 'MW_DATE_ISO', 'ISO 8601' );
// /**@}*/
//
// /**@{
// * RecentChange type identifiers
// */
// define( 'RC_EDIT', 0 );
// define( 'RC_NEW', 1 );
// define( 'RC_LOG', 3 );
// define( 'RC_EXTERNAL', 5 );
// define( 'RC_CATEGORIZE', 6 );
// /**@}*/
//
// /**@{
// * Article edit flags
// */
// define( 'EDIT_NEW', 1 );
// define( 'EDIT_UPDATE', 2 );
// define( 'EDIT_MINOR', 4 );
// define( 'EDIT_SUPPRESS_RC', 8 );
// define( 'EDIT_FORCE_BOT', 16 );
// define( 'EDIT_DEFER_UPDATES', 32 ); // Unused since 1.27
// define( 'EDIT_AUTOSUMMARY', 64 );
// /**@}*/
//
// /**@{
// * Flags for Database::makeList()
// * These are also available as Database class constants
// */
// define( 'LIST_COMMA', 0 );
// define( 'LIST_AND', 1 );
// define( 'LIST_SET', 2 );
// define( 'LIST_NAMES', 3 );
// define( 'LIST_OR', 4 );
// /**@}*/
//
// /**
// * Unicode and normalisation related
// */
// require_once __DIR__ . '/compat/normal/UtfNormalDefines.php';
//
// /**@{
// * Hook support constants
// */
// define( 'MW_SUPPORTS_PARSERFIRSTCALLINIT', 1 );
// define( 'MW_SUPPORTS_LOCALISATIONCACHE', 1 );
// define( 'MW_SUPPORTS_CONTENTHANDLER', 1 );
// define( 'MW_EDITFILTERMERGED_SUPPORTS_API', 1 );
// /**@}*/
//
// /** Support for $wgResourceModules */
// define( 'MW_SUPPORTS_RESOURCE_MODULES', 1 );
//
// /**@{
// * Allowed values for Parser::$mOutputType
// * Parameter to Parser::startExternalParse().
// * Use of Parser consts is preferred:
// * - Parser::OT_HTML
// * - Parser::OT_WIKI
// * - Parser::OT_PREPROCESS
// * - Parser::OT_MSG
// * - Parser::OT_PLAIN
// */
// define( 'OT_HTML', 1 );
// define( 'OT_WIKI', 2 );
// define( 'OT_PREPROCESS', 3 );
// define( 'OT_MSG', 3 ); // b/c alias for OT_PREPROCESS
// define( 'OT_PLAIN', 4 );
// /**@}*/
//
// /**@{
// * Flags for Parser::setFunctionHook
// * Use of Parser consts is preferred:
// * - Parser::SFH_NO_HASH
// * - Parser::SFH_OBJECT_ARGS
// */
// define( 'SFH_NO_HASH', 1 );
// define( 'SFH_OBJECT_ARGS', 2 );
// /**@}*/
//
// /**@{
// * Autopromote conditions (must be here and not in Autopromote.php, so that
// * they're loaded for DefaultSettings.php before AutoLoader.php)
// */
// define( 'APCOND_EDITCOUNT', 1 );
// define( 'APCOND_AGE', 2 );
// define( 'APCOND_EMAILCONFIRMED', 3 );
// define( 'APCOND_INGROUPS', 4 );
// define( 'APCOND_ISIP', 5 );
// define( 'APCOND_IPINRANGE', 6 );
// define( 'APCOND_AGE_FROM_EDIT', 7 );
// define( 'APCOND_BLOCKED', 8 );
// define( 'APCOND_ISBOT', 9 );
// /**@}*/
//
// /** @{
// * Protocol constants for wfExpandUrl()
// */
// define( 'PROTO_HTTP', 'http://' );
// define( 'PROTO_HTTPS', 'https://' );
// define( 'PROTO_RELATIVE', '//' );
// define( 'PROTO_CURRENT', null );
// define( 'PROTO_CANONICAL', 1 );
// define( 'PROTO_INTERNAL', 2 );
// /**@}*/
//
// /**@{
// * Content model ids, used by Content and ContentHandler.
// * These IDs will be exposed in the API and XML dumps.
// *
// * Extensions that define their own content model IDs should take
// * care to avoid conflicts. Using the extension name as a prefix is recommended,
// * for example 'myextension-somecontent'.
// */
// define( 'CONTENT_MODEL_WIKITEXT', 'wikitext' );
// define( 'CONTENT_MODEL_JAVASCRIPT', 'javascript' );
// define( 'CONTENT_MODEL_CSS', 'css' );
// define( 'CONTENT_MODEL_TEXT', 'text' );
// define( 'CONTENT_MODEL_JSON', 'json' );
// /**@}*/
//
// /**@{
// * Content formats, used by Content and ContentHandler.
// * These should be MIME types, and will be exposed in the API and XML dumps.
// *
// * Extensions are free to use the below formats, or define their own.
// * It is recommended to stick with the conventions for MIME types.
// */
// // wikitext
// define( 'CONTENT_FORMAT_WIKITEXT', 'text/x-wiki' );
// // for js pages
// define( 'CONTENT_FORMAT_JAVASCRIPT', 'text/javascript' );
// // for css pages
// define( 'CONTENT_FORMAT_CSS', 'text/css' );
// // for future use, e.g. with some plain-html messages.
// define( 'CONTENT_FORMAT_TEXT', 'text/plain' );
// // for future use, e.g. with some plain-html messages.
// define( 'CONTENT_FORMAT_HTML', 'text/html' );
// // for future use with the api and for extensions
// define( 'CONTENT_FORMAT_SERIALIZED', 'application/vnd.php.serialized' );
// // for future use with the api, and for use by extensions
// define( 'CONTENT_FORMAT_JSON', 'application/json' );
// // for future use with the api, and for use by extensions
// define( 'CONTENT_FORMAT_XML', 'application/xml' );
// /**@}*/
//
// /**@{
// * Max String length for shell invocations; based on binfmts.h
// */
// define( 'SHELL_MAX_ARG_STRLEN', '100000' );
// /**@}*/
}

View File

@ -0,0 +1,623 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.mediawiki.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*;
import gplx.xowa.mediawiki.includes.title.*;
/**
* MediaWikiServices is the service locator for the application scope of MediaWiki.
* Its implemented as a simple configurable DI container.
* MediaWikiServices acts as a top level factory/registry for top level services, and builds
* the network of service objects that defines MediaWiki's application logic.
* It acts as an entry point to MediaWiki's dependency injection mechanism.
*
* Services are defined in the "wiring" array passed to the constructor,
* or by calling defineService().
*
* @see docs/injection.txt for an overview of using dependency injection in the
* MediaWiki code super.
*/
public class Xomw_MediaWikiServices {
/**
* @var MediaWikiServices|null
*/
private static Xomw_MediaWikiServices instance = null;
/**
* Returns the global default instance of the top level service locator.
*
* @since 1.27
*
* The default instance is initialized using the service instantiator functions
* defined in ServiceWiring.php.
*
* @note This should only be called by static functions! The instance returned here
* should not be passed around! Objects that need access to a service should have
* that service injected into the constructor, never a service locator!
*
* @return MediaWikiServices
*/
public static Xomw_MediaWikiServices getInstance() {
if (instance == null) {
// NOTE: constructing GlobalVarConfig here is not particularly pretty,
// but some information from the global scope has to be injected here,
// even if it's just a file name or database credentials to load
// configuration from.
// $bootstrapConfig = new GlobalVarConfig();
// self::$instance = self::newInstance($bootstrapConfig, 'load');
instance = new Xomw_MediaWikiServices();
}
return instance;
}
// /**
// * Replaces the global MediaWikiServices instance.
// *
// * @since 1.28
// *
// * @note This is for use in PHPUnit tests only!
// *
// * @throws MWException if called outside of PHPUnit tests.
// *
// * @param MediaWikiServices $services The new MediaWikiServices Object.
// *
// * @return MediaWikiServices The old MediaWikiServices Object, so it can be restored later.
// */
// public static function forceGlobalInstance( MediaWikiServices $services ) {
// if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
// throw new MWException( __METHOD__ . ' must not be used outside unit tests.' );
// }
//
// $old = self::getInstance();
// self::$instance = $services;
//
// return $old;
// }
//
// /**
// * Creates a new instance of MediaWikiServices and sets it as the global default
// * instance. getInstance() will return a different MediaWikiServices Object
// * after every call to resetGlobalInstance().
// *
// * @since 1.28
// *
// * @warning This should not be used during normal operation. It is intended for use
// * when the configuration has changed significantly since bootstrap time, e.g.
// * during the installation process or during testing.
// *
// * @warning Calling resetGlobalInstance() may leave the application in an inconsistent
// * state. Calling this is only safe under the ASSUMPTION that NO REFERENCE to
// * any of the services managed by MediaWikiServices exist. If any service objects
// * managed by the old MediaWikiServices instance remain in use, they may INTERFERE
// * with the operation of the services managed by the new MediaWikiServices.
// * Operating with a mix of services created by the old and the new
// * MediaWikiServices instance may lead to INCONSISTENCIES and even DATA LOSS!
// * Any class implementing LAZY LOADING is especially prone to this problem,
// * since instances would typically retain a reference to a storage layer service.
// *
// * @see forceGlobalInstance()
// * @see resetGlobalInstance()
// * @see resetBetweenTest()
// *
// * @param Config|null $bootstrapConfig The Config Object to be registered as the
// * 'BootstrapConfig' service. This has to contain at least the information
// * needed to set up the 'ConfigFactory' service. If not given, the bootstrap
// * config of the old instance of MediaWikiServices will be re-used. If there
// * was no previous instance, a new GlobalVarConfig Object will be used to
// * bootstrap the services.
// *
// * @param String $quick Set this to "quick" to allow expensive resources to be re-used.
// * See SalvageableService for details.
// *
// * @throws MWException If called after MW_SERVICE_BOOTSTRAP_COMPLETE has been defined in
// * Setup.php (unless MW_PHPUNIT_TEST or MEDIAWIKI_INSTALL or RUN_MAINTENANCE_IF_MAIN
// * is defined).
// */
// public static function resetGlobalInstance( Config $bootstrapConfig = null, $quick = '' ) {
// if ( self::$instance === null ) {
// // no global instance yet, nothing to reset
// return;
// }
//
// self::failIfResetNotAllowed( __METHOD__ );
//
// if ( $bootstrapConfig === null ) {
// $bootstrapConfig = self::$instance->getBootstrapConfig();
// }
//
// $oldInstance = self::$instance;
//
// self::$instance = self::newInstance( $bootstrapConfig, 'load' );
// self::$instance->importWiring( $oldInstance, [ 'BootstrapConfig' ] );
//
// if ( $quick === 'quick' ) {
// self::$instance->salvage( $oldInstance );
// } else {
// $oldInstance->destroy();
// }
// }
//
// /**
// * Salvages the state of any salvageable service instances in $other.
// *
// * @note $other will have been destroyed when salvage() returns.
// *
// * @param MediaWikiServices $other
// */
// private function salvage( self $other ) {
// foreach ( $this->getServiceNames() as $name ) {
// // The service could be new in the new instance and not registered in the
// // other instance (e.g. an extension that was loaded after the instantiation of
// // the other instance. Skip this service in this case. See T143974
// try {
// $oldService = $other->peekService( $name );
// } catch ( NoSuchServiceException $e ) {
// continue;
// }
//
// if ( $oldService instanceof SalvageableService ) {
// /** @var SalvageableService $newService */
// $newService = $this->getService( $name );
// $newService->salvage( $oldService );
// }
// }
//
// $other->destroy();
// }
//
// /**
// * Creates a new MediaWikiServices instance and initializes it according to the
// * given $bootstrapConfig. In particular, all wiring files defined in the
// * ServiceWiringFiles setting are loaded, and the MediaWikiServices hook is called.
// *
// * @param Config|null $bootstrapConfig The Config Object to be registered as the
// * 'BootstrapConfig' service.
// *
// * @param String $loadWiring set this to 'load' to load the wiring files specified
// * in the 'ServiceWiringFiles' setting in $bootstrapConfig.
// *
// * @return MediaWikiServices
// * @throws MWException
// * @throws \FatalError
// */
// private static function newInstance( Config $bootstrapConfig, $loadWiring = '' ) {
// $instance = new self( $bootstrapConfig );
//
// // Load the default wiring from the specified files.
// if ( $loadWiring === 'load' ) {
// $wiringFiles = $bootstrapConfig->get( 'ServiceWiringFiles' );
// $instance->loadWiringFiles( $wiringFiles );
// }
//
// // Provide a traditional hook point to allow extensions to configure services.
// Hooks::run( 'MediaWikiServices', [ $instance ] );
//
// return $instance;
// }
//
// /**
// * Disables all storage layer services. After calling this, any attempt to access the
// * storage layer will result in an error. Use resetGlobalInstance() to restore normal
// * operation.
// *
// * @since 1.28
// *
// * @warning This is intended for extreme situations only and should never be used
// * while serving normal web requests. Legitimate use cases for this method include
// * the installation process. Test fixtures may also use this, if the fixture relies
// * on globalState.
// *
// * @see resetGlobalInstance()
// * @see resetChildProcessServices()
// */
// public static function disableStorageBackend() {
// // TODO: also disable some Caches, JobQueues, etc
// $destroy = [ 'DBLoadBalancer', 'DBLoadBalancerFactory' ];
// $services = self::getInstance();
//
// foreach ( $destroy as $name ) {
// $services->disableService( $name );
// }
//
// ObjectCache::clear();
// }
//
// /**
// * Resets any services that may have become stale after a child process
// * returns from after pcntl_fork(). It's also safe, but generally unnecessary,
// * to call this method from the parent process.
// *
// * @since 1.28
// *
// * @note This is intended for use in the context of process forking only!
// *
// * @see resetGlobalInstance()
// * @see disableStorageBackend()
// */
// public static function resetChildProcessServices() {
// // NOTE: for now, just reset everything. Since we don't know the interdependencies
// // between services, we can't do this more selectively at this time.
// self::resetGlobalInstance();
//
// // Child, reseed because there is no bug in PHP:
// // https://bugs.php.net/bug.php?id=42465
// mt_srand( getmypid() );
// }
//
// /**
// * Resets the given service for testing purposes.
// *
// * @since 1.28
// *
// * @warning This is generally unsafe! Other services may still retain references
// * to the stale service instance, leading to failures and inconsistencies. Subclasses
// * may use this method to reset specific services under specific instances, but
// * it should not be exposed to application logic.
// *
// * @note With proper dependency injection used throughout the codebase, this method
// * should not be needed. It is provided to allow tests that pollute global service
// * instances to clean up.
// *
// * @param String $name
// * @param boolean $destroy Whether the service instance should be destroyed if it exists.
// * When set to false, any existing service instance will effectively be detached
// * from the container.
// *
// * @throws MWException if called outside of PHPUnit tests.
// */
// public function resetServiceForTesting( $name, $destroy = true ) {
// if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MW_PARSER_TEST' ) ) {
// throw new MWException( 'resetServiceForTesting() must not be used outside unit tests.' );
// }
//
// $this->resetService( $name, $destroy );
// }
//
// /**
// * Convenience method that throws an exception unless it is called during a phase in which
// * resetting of global services is allowed. In general, services should not be reset
// * individually, since that may introduce inconsistencies.
// *
// * @since 1.28
// *
// * This method will throw an exception if:
// *
// * - self::$resetInProgress is false (to allow all services to be reset together
// * via resetGlobalInstance)
// * - and MEDIAWIKI_INSTALL is not defined (to allow services to be reset during installation)
// * - and MW_PHPUNIT_TEST is not defined (to allow services to be reset during testing)
// *
// * This method is intended to be used to safeguard against accidentally resetting
// * global service instances that are not yet managed by MediaWikiServices. It is
// * defined here in the MediaWikiServices services class to have a central place
// * for managing service bootstrapping and resetting.
// *
// * @param String $method the name of the caller method, as given by __METHOD__.
// *
// * @throws MWException if called outside bootstrap mode.
// *
// * @see resetGlobalInstance()
// * @see forceGlobalInstance()
// * @see disableStorageBackend()
// */
// public static function failIfResetNotAllowed( $method ) {
// if ( !defined( 'MW_PHPUNIT_TEST' )
// && !defined( 'MW_PARSER_TEST' )
// && !defined( 'MEDIAWIKI_INSTALL' )
// && !defined( 'RUN_MAINTENANCE_IF_MAIN' )
// && defined( 'MW_SERVICE_BOOTSTRAP_COMPLETE' )
// ) {
// throw new MWException( $method . ' may only be called during bootstrapping and unit tests!' );
// }
// }
//
// /**
// * @param Config $config The Config Object to be registered as the 'BootstrapConfig' service.
// * This has to contain at least the information needed to set up the 'ConfigFactory'
// * service.
// */
// public function __construct( Config $config ) {
// parent::__construct();
//
// // Register the given Config Object as the bootstrap config service.
// $this->defineService( 'BootstrapConfig', function() use ( $config ) {
// return $config;
// } );
// }
//
// // CONVENIENCE GETTERS ////////////////////////////////////////////////////
//
// /**
// * Returns the Config Object containing the bootstrap configuration.
// * Bootstrap configuration would typically include database credentials
// * and other information that may be needed before the ConfigFactory
// * service can be instantiated.
// *
// * @note This should only be used during bootstrapping, in particular
// * when creating the MainConfig service. Application logic should
// * use getMainConfig() to get a Config instances.
// *
// * @since 1.27
// * @return Config
// */
// public function getBootstrapConfig() {
// return $this->getService( 'BootstrapConfig' );
// }
//
// /**
// * @since 1.27
// * @return ConfigFactory
// */
// public function getConfigFactory() {
// return $this->getService( 'ConfigFactory' );
// }
//
// /**
// * Returns the Config Object that provides configuration for MediaWiki core.
// * This may or may not be the same Object that is returned by getBootstrapConfig().
// *
// * @since 1.27
// * @return Config
// */
// public function getMainConfig() {
// return $this->getService( 'MainConfig' );
// }
//
// /**
// * @since 1.27
// * @return SiteLookup
// */
// public function getSiteLookup() {
// return $this->getService( 'SiteLookup' );
// }
//
// /**
// * @since 1.27
// * @return SiteStore
// */
// public function getSiteStore() {
// return $this->getService( 'SiteStore' );
// }
//
// /**
// * @since 1.28
// * @return InterwikiLookup
// */
// public function getInterwikiLookup() {
// return $this->getService( 'InterwikiLookup' );
// }
//
// /**
// * @since 1.27
// * @return StatsdDataFactory
// */
// public function getStatsdDataFactory() {
// return $this->getService( 'StatsdDataFactory' );
// }
//
// /**
// * @since 1.27
// * @return EventRelayerGroup
// */
// public function getEventRelayerGroup() {
// return $this->getService( 'EventRelayerGroup' );
// }
//
// /**
// * @since 1.27
// * @return SearchEngine
// */
// public function newSearchEngine() {
// // New engine Object every time, since they keep state
// return $this->getService( 'SearchEngineFactory' )->create();
// }
//
// /**
// * @since 1.27
// * @return SearchEngineFactory
// */
// public function getSearchEngineFactory() {
// return $this->getService( 'SearchEngineFactory' );
// }
//
// /**
// * @since 1.27
// * @return SearchEngineConfig
// */
// public function getSearchEngineConfig() {
// return $this->getService( 'SearchEngineConfig' );
// }
//
// /**
// * @since 1.27
// * @return SkinFactory
// */
// public function getSkinFactory() {
// return $this->getService( 'SkinFactory' );
// }
//
// /**
// * @since 1.28
// * @return LBFactory
// */
// public function getDBLoadBalancerFactory() {
// return $this->getService( 'DBLoadBalancerFactory' );
// }
//
// /**
// * @since 1.28
// * @return LoadBalancer The main DB load balancer for the local wiki.
// */
// public function getDBLoadBalancer() {
// return $this->getService( 'DBLoadBalancer' );
// }
//
// /**
// * @since 1.28
// * @return WatchedItemStore
// */
// public function getWatchedItemStore() {
// return $this->getService( 'WatchedItemStore' );
// }
//
// /**
// * @since 1.28
// * @return WatchedItemQueryService
// */
// public function getWatchedItemQueryService() {
// return $this->getService( 'WatchedItemQueryService' );
// }
//
// /**
// * @since 1.28
// * @return CryptRand
// */
// public function getCryptRand() {
// return $this->getService( 'CryptRand' );
// }
//
// /**
// * @since 1.28
// * @return CryptHKDF
// */
// public function getCryptHKDF() {
// return $this->getService( 'CryptHKDF' );
// }
//
// /**
// * @since 1.28
// * @return MediaHandlerFactory
// */
// public function getMediaHandlerFactory() {
// return $this->getService( 'MediaHandlerFactory' );
// }
//
// /**
// * @since 1.28
// * @return MimeAnalyzer
// */
// public function getMimeAnalyzer() {
// return $this->getService( 'MimeAnalyzer' );
// }
//
// /**
// * @since 1.28
// * @return ProxyLookup
// */
// public function getProxyLookup() {
// return $this->getService( 'ProxyLookup' );
// }
//
// /**
// * @since 1.29
// * @return Parser
// */
// public function getParser() {
// return $this->getService( 'Parser' );
// }
//
// /**
// * @since 1.28
// * @return GenderCache
// */
// public function getGenderCache() {
// return $this->getService( 'GenderCache' );
// }
//
// /**
// * @since 1.28
// * @return LinkCache
// */
// public function getLinkCache() {
// return $this->getService( 'LinkCache' );
// }
//
// /**
// * @since 1.28
// * @return LinkRendererFactory
// */
// public function getLinkRendererFactory() {
// return $this->getService( 'LinkRendererFactory' );
// }
//
// /**
// * LinkRenderer instance that can be used
// * if no custom options are needed
// *
// * @since 1.28
// * @return LinkRenderer
// */
// public function getLinkRenderer() {
// return $this->getService( 'LinkRenderer' );
// }
//
// /**
// * @since 1.28
// * @return TitleFormatter
// */
// public function getTitleFormatter() {
// return $this->getService( 'TitleFormatter' );
// }
/**
* @since 1.28
* @return TitleParser
*/
public Xomw_MediaWikiTitleCodec getTitleParser() {
// return $this->getService( 'TitleParser' );
return titleParser;
}
private Xomw_MediaWikiTitleCodec titleParser = new Xomw_MediaWikiTitleCodec();
// /**
// * @since 1.28
// * @return \BagOStuff
// */
// public function getMainObjectStash() {
// return $this->getService( 'MainObjectStash' );
// }
//
// /**
// * @since 1.28
// * @return \WANObjectCache
// */
// public function getMainWANObjectCache() {
// return $this->getService( 'MainWANObjectCache' );
// }
//
// /**
// * @since 1.28
// * @return \BagOStuff
// */
// public function getLocalServerObjectCache() {
// return $this->getService( 'LocalServerObjectCache' );
// }
//
// /**
// * @since 1.28
// * @return VirtualRESTServiceClient
// */
// public function getVirtualRESTServiceClient() {
// return $this->getService( 'VirtualRESTServiceClient' );
// }
//
// ///////////////////////////////////////////////////////////////////////////
// // NOTE: When adding a service getter here, don't forget to add a test
// // case for it in MediaWikiServicesTest::provideGetters() and in
// // MediaWikiServicesTest::provideGetService()!
// ///////////////////////////////////////////////////////////////////////////
}

View File

@ -253,6 +253,8 @@ public class Xomw_lnki_wkr {// THREAD.UNSAFE: caching for repeated calls
// Strip off leading ':'
link = Bry_.Mid(link, 1);
}
// $nt = is_string( $unstrip ) ? Title::newFromText( $unstrip ) : null;
// Xomw_Title nt2 = Xomw_Title.newFromText(link);
Xoa_ttl nt = wiki.Ttl_parse(link);
// Make subpage if necessary

View File

@ -0,0 +1,20 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.mediawiki.includes.title; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*;
public class MalformedTitleException extends Err { public MalformedTitleException(String name, byte[] text) {super(false, "", name, name);}
}

View File

@ -0,0 +1,454 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.mediawiki.includes.title; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*;
import gplx.xowa.mediawiki.includes.utls.*;
public class Xomw_MediaWikiTitleCodec {
// /**
// * @var Language
// */
// protected $language;
//
// /**
// * @var GenderCache
// */
// protected $genderCache;
//
// /**
// * @var String[]
// */
// protected $localInterwikis;
//
// /**
// * @param Language $language The language Object to use for localizing namespace names.
// * @param GenderCache $genderCache The gender cache for generating gendered namespace names
// * @param String[]|String $localInterwikis
// */
// public function __construct(Language $language, GenderCache $genderCache,
// $localInterwikis = []
// ) {
// $this->language = $language;
// $this->genderCache = $genderCache;
// $this->localInterwikis = (array)$localInterwikis;
// }
//
// /**
// * @see TitleFormatter::getNamespaceName()
// *
// * @param int $namespace
// * @param String $text
// *
// * @throws InvalidArgumentException If the namespace is invalid
// * @return String
// */
// public function getNamespaceName($namespace, $text) {
// if ($this->language->needsGenderDistinction() &&
// MWNamespace::hasGenderDistinction($namespace)
// ) {
//
// // NOTE: we are assuming here that the title text is a user name!
// $gender = $this->genderCache->getGenderOf($text, __METHOD__);
// $name = $this->language->getGenderNsText($namespace, $gender);
// } else {
// $name = $this->language->getNsText($namespace);
// }
//
// if ($name === false) {
// throw new InvalidArgumentException('Unknown namespace ID: ' . $namespace);
// }
//
// return $name;
// }
//
// /**
// * @see TitleFormatter::formatTitle()
// *
// * @param int|boolean $namespace The namespace ID (or false, if the namespace should be ignored)
// * @param String $text The page title. Should be valid. Only minimal normalization is applied.
// * Underscores will be replaced.
// * @param String $fragment The fragment name (may be empty).
// * @param String $interwiki The interwiki name (may be empty).
// *
// * @throws InvalidArgumentException If the namespace is invalid
// * @return String
// */
// public function formatTitle($namespace, $text, $fragment = '', $interwiki = '') {
// if ($namespace !== false) {
// $namespace = $this->getNamespaceName($namespace, $text);
//
// if ($namespace !== '') {
// $text = $namespace . ':' . $text;
// }
// }
//
// if ($fragment !== '') {
// $text = $text . '#' . $fragment;
// }
//
// if ($interwiki !== '') {
// $text = $interwiki . ':' . $text;
// }
//
// $text = str_replace('_', ' ', $text);
//
// return $text;
// }
//
// /**
// * Parses the given text and constructs a TitleValue. Normalization
// * is applied according to the rules appropriate for the form specified by $form.
// *
// * @param String $text The text to parse
// * @param int $defaultNamespace Namespace to assume per default (usually NS_MAIN)
// *
// * @throws MalformedTitleException
// * @return TitleValue
// */
// public function parseTitle($text, $defaultNamespace) {
// // NOTE: this is an ugly cludge that allows this class to share the
// // code for parsing with the old Title class. The parser code should
// // be refactored to avoid this.
// $parts = $this->splitTitleString($text, $defaultNamespace);
//
// // Relative fragment links are not supported by TitleValue
// if ($parts['dbkey'] === '') {
// throw new MalformedTitleException('title-invalid-empty', $text);
// }
//
// return new TitleValue(
// $parts['namespace'],
// $parts['dbkey'],
// $parts['fragment'],
// $parts['interwiki']
// );
// }
//
// /**
// * @see TitleFormatter::getText()
// *
// * @param LinkTarget $title
// *
// * @return String $title->getText()
// */
// public function getText(LinkTarget $title) {
// return $this->formatTitle(false, $title->getText(), '');
// }
//
// /**
// * @see TitleFormatter::getText()
// *
// * @param LinkTarget $title
// *
// * @return String
// */
// public function getPrefixedText(LinkTarget $title) {
// return $this->formatTitle(
// $title->getNamespace(),
// $title->getText(),
// '',
// $title->getInterwiki()
// );
// }
//
// /**
// * @since 1.27
// * @see TitleFormatter::getPrefixedDBkey()
// * @param LinkTarget $target
// * @return String
// */
// public function getPrefixedDBkey(LinkTarget $target) {
// $key = '';
// if ($target->isExternal()) {
// $key .= $target->getInterwiki() . ':';
// }
// // Try to get a namespace name, but fallback
// // to empty String if it doesn't exist
// try {
// $nsName = $this->getNamespaceName(
// $target->getNamespace(),
// $target->getText()
// );
// } catch (InvalidArgumentException $e) {
// $nsName = '';
// }
//
// if ($target->getNamespace() !== 0) {
// $key .= $nsName . ':';
// }
//
// $key .= $target->getText();
//
// return strtr($key, ' ', '_');
// }
//
// /**
// * @see TitleFormatter::getText()
// *
// * @param LinkTarget $title
// *
// * @return String
// */
// public function getFullText(LinkTarget $title) {
// return $this->formatTitle(
// $title->getNamespace(),
// $title->getText(),
// $title->getFragment(),
// $title->getInterwiki()
// );
// }
/**
* Normalizes and splits a title String.
*
* This function removes illegal characters, splits off the interwiki and
* namespace prefixes, sets the other forms, and canonicalizes
* everything.
*
* @todo this method is only exposed as a temporary measure to ease refactoring.
* It was copied with minimal changes from Title::secureAndSplit().
*
* @todo This method should be split up and an appropriate interface
* defined for use by the Title class.
*
* @param String $text
* @param int $defaultNamespace
*
* @throws MalformedTitleException If $text is not a valid title String.
* @return array A map with the fields 'interwiki', 'fragment', 'namespace',
* 'user_case_dbkey', and 'dbkey'.
*/
public Xomw_MediaWikiTitleCodec_Parts splitTitleString(byte[] text, int defaultNamespace) {
byte[] dbkey = Php_str_.str_replace(Byte_ascii.Space, Byte_ascii.Underline, text);
// Initialisation
Xomw_MediaWikiTitleCodec_Parts parts = new Xomw_MediaWikiTitleCodec_Parts(dbkey, defaultNamespace);
// Strip Unicode bidi override characters.
// Sometimes they slip into cut-n-pasted page titles, where the
// override chars get included in list displays.
// dbkey = preg_replace('/\xE2\x80[\x8E\x8F\xAA-\xAE]/S', '', dbkey);
// Clean up whitespace
// Note: use of the /u option on preg_replace here will cause
// input with invalid UTF-8 sequences to be nullified out in PHP 5.2.x,
// conveniently disabling them.
// dbkey = preg_replace(
// '/[ _\xA0\x{1680}\x{180E}\x{2000}-\x{200A}\x{2028}\x{2029}\x{202F}\x{205F}\x{3000}]+/u',
// '_',
// dbkey
// );
// dbkey = trim(dbkey, '_');
// if (strpos(dbkey, UtfNormal\Constants::UTF8_REPLACEMENT) !== false) {
// // Contained illegal UTF-8 sequences or forbidden Unicode chars.
// throw new MalformedTitleException('title-invalid-utf8', text);
// }
parts.dbkey = dbkey;
// Initial colon indicates main namespace rather than specified default
// but should not create invalid {ns,title} pairs such as {0,Project:Foo}
// if (dbkey !== '' && ':' == dbkey[0]) {
// parts['namespace'] = NS_MAIN;
// dbkey = substr(dbkey, 1); # remove the colon but continue processing
// dbkey = trim(dbkey, '_'); # remove any subsequent whitespace
// }
if (dbkey == Bry_.Empty) {
throw new MalformedTitleException("title-invalid-empty", text);
}
// Namespace or interwiki prefix
// $prefixRegexp = "/^(.+?)_*:_*(.*)$/S";
// do {
// $m = [];
// if (preg_match($prefixRegexp, dbkey, $m)) {
// $p = $m[1];
// $ns = $this->language->getNsIndex($p);
// if ($ns !== false) {
// // Ordinary namespace
// dbkey = $m[2];
// parts['namespace'] = $ns;
// // For Talk:X pages, check if X has a "namespace" prefix
// if ($ns == NS_TALK && preg_match($prefixRegexp, dbkey, $x)) {
// if ($this->language->getNsIndex($x[1])) {
// // Disallow Talk:File:x type titles...
// throw new MalformedTitleException('title-invalid-talk-namespace', text);
// } elseif (Interwiki::isValidInterwiki($x[1])) {
// // TODO: get rid of global state!
// // Disallow Talk:Interwiki:x type titles...
// throw new MalformedTitleException('title-invalid-talk-namespace', text);
// }
// }
// } elseif (Interwiki::isValidInterwiki($p)) {
// // Interwiki link
// dbkey = $m[2];
// parts['interwiki'] = $this->language->lc($p);
//
// // Redundant interwiki prefix to the local wiki
// foreach ($this->localInterwikis as $localIW) {
// if (0 == strcasecmp(parts['interwiki'], $localIW)) {
// if (dbkey == '') {
// // Empty self-links should point to the Main Page, to ensure
// // compatibility with cross-wiki transclusions and the like.
// $mainPage = Title::newMainPage();
// return [
// 'interwiki' => $mainPage->getInterwiki(),
// 'local_interwiki' => true,
// 'fragment' => $mainPage->getFragment(),
// 'namespace' => $mainPage->getNamespace(),
// 'dbkey' => $mainPage->getDBkey(),
// 'user_case_dbkey' => $mainPage->getUserCaseDBKey()
// ];
// }
// parts['interwiki'] = '';
// // local interwikis should behave like initial-colon links
// parts['local_interwiki'] = true;
//
// // Do another namespace split...
// continue 2;
// }
// }
//
// // If there's an initial colon after the interwiki, that also
// // resets the default namespace
// if (dbkey !== '' && dbkey[0] == ':') {
// parts['namespace'] = NS_MAIN;
// dbkey = substr(dbkey, 1);
// }
// }
// // If there's no recognized interwiki or namespace,
// // then let the colon expression be part of the title.
// }
// break;
// } while (true);
// $fragment = strstr(dbkey, '#');
// if (false !== $fragment) {
// parts['fragment'] = str_replace('_', ' ', substr($fragment, 1));
// dbkey = substr(dbkey, 0, strlen(dbkey) - strlen($fragment));
// // remove whitespace again: prevents "Foo_bar_#"
// // becoming "Foo_bar_"
// dbkey = preg_replace('/_*$/', '', dbkey);
// }
// Reject illegal characters.
// $rxTc = self::getTitleInvalidRegex();
// $matches = [];
// if (preg_match($rxTc, dbkey, $matches)) {
// throw new MalformedTitleException('title-invalid-characters', text, [ $matches[0] ]);
// }
// Pages with "/./" or "/../" appearing in the URLs will often be un-
// reachable due to the way web browsers deal with 'relative' URLs.
// Also, they conflict with subpage syntax. Forbid them explicitly.
// if (
// strpos(dbkey, '.') !== false &&
// (
// dbkey === '.' || dbkey === '..' ||
// strpos(dbkey, './') === 0 ||
// strpos(dbkey, '../') === 0 ||
// strpos(dbkey, '/./') !== false ||
// strpos(dbkey, '/../') !== false ||
// substr(dbkey, -2) == '/.' ||
// substr(dbkey, -3) == '/..'
// )
// ) {
// throw new MalformedTitleException('title-invalid-relative', text);
// }
// Magic tilde sequences? Nu-uh!
// if (strpos(dbkey, '~~~') !== false) {
// throw new MalformedTitleException('title-invalid-magic-tilde', text);
// }
// Limit the size of titles to 255 bytes. This is typically the size of the
// underlying database field. We make an exception for special pages, which
// don't need to be stored in the database, and may edge over 255 bytes due
// to subpage syntax for long titles, e.g. [[Special:Block/Long name]]
// $maxLength = (parts['namespace'] != NS_SPECIAL) ? 255 : 512;
// if (strlen(dbkey) > $maxLength) {
// throw new MalformedTitleException('title-invalid-too-long', text,
// [ Message::numParam($maxLength) ]);
// }
// Normally, all wiki links are forced to have an initial capital letter so [[foo]]
// and [[Foo]] point to the same place. Don't force it for interwikis, since the
// other site might be case-sensitive.
// parts['user_case_dbkey'] = dbkey;
// if (parts['interwiki'] === '') {
// dbkey = Title::capitalize(dbkey, parts['namespace']);
// }
// Can't make a link to a namespace alone... "empty" local links can only be
// self-links with a fragment identifier.
// if (dbkey == '' && parts['interwiki'] === '') {
// if (parts['namespace'] != NS_MAIN) {
// throw new MalformedTitleException('title-invalid-empty', text);
// }
// }
// Allow IPv6 usernames to start with '::' by canonicalizing IPv6 titles.
// IP names are not allowed for accounts, and can only be referring to
// edits from the IP. Given '::' abbreviations and caps/lowercaps,
// there are numerous ways to present the same IP. Having sp:contribs scan
// them all is silly and having some show the edits and others not is
// inconsistent. Same for talk/userpages. Keep them normalized instead.
// if (parts['namespace'] == NS_USER || parts['namespace'] == NS_USER_TALK) {
// dbkey = IP::sanitizeIP(dbkey);
// }
// Any remaining initial :s are illegal.
if (dbkey != Bry_.Empty && Byte_ascii.Colon == dbkey[0]) {
throw new MalformedTitleException("title-invalid-leading-colon", text);
}
// Fill fields
parts.dbkey = dbkey;
return parts;
}
// /**
// * Returns a simple regex that will match on characters and sequences invalid in titles.
// * Note that this doesn't pick up many things that could be wrong with titles, but that
// * replacing this regex with something valid will make many titles valid.
// * Previously Title::getTitleInvalidRegex()
// *
// * @return String Regex String
// * @since 1.25
// */
// public static function getTitleInvalidRegex() {
// static $rxTc = false;
// if (!$rxTc) {
// // Matching titles will be held as illegal.
// $rxTc = '/' .
// // Any character not allowed is forbidden...
// '[^' . Title::legalChars() . ']' .
// // URL percent encoding sequences interfere with the ability
// // to round-trip titles -- you can't link to them consistently.
// '|%[0-9A-Fa-f]{2}' .
// // XML/HTML character references produce similar issues.
// '|&[A-Za-z0-9\x80-\xff]+;' .
// '|&#[0-9]+;' .
// '|&#x[0-9A-Fa-f]+;' .
// '/S';
// }
//
// return $rxTc;
// }
}

View File

@ -0,0 +1,34 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.mediawiki.includes.title; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*;
public class Xomw_MediaWikiTitleCodec_Parts {
public byte[] interwiki;
public boolean local_interwiki;
public byte[] fragment = Bry_.Empty;
public int ns;
public byte[] dbkey;
public byte[] user_case_dbkey;
public Xomw_MediaWikiTitleCodec_Parts(byte[] dbkey, int defaultNamespace) {
this.interwiki = Bry_.Empty;
this.local_interwiki = false;
this.fragment = Bry_.Empty;
this.ns = defaultNamespace;
this.dbkey = dbkey;
this.user_case_dbkey = dbkey;
}
}

View File

@ -149,4 +149,7 @@ public class Php_str_ {
public static byte[] strtr(byte[] src, byte find, byte repl) {
return Bry_.Replace(src, 0, src.length, find, repl);
}
public static byte[] str_replace(byte find, byte repl, byte[] src) {
return Bry_.Replace(src, 0, src.length, find, repl);
}
}