From c8334fae82ba2428f5d2a4bd953deeadf97c58bc Mon Sep 17 00:00:00 2001 From: friendica Date: Tue, 26 Nov 2013 00:06:56 -0800 Subject: will be doing some stuff for which handcrafting xmlrpc requests is too bloody painful. xmlrpc is long dead, but it's the language of wordpress - which is far from dead. --- library/IXR_Library.php | 1371 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1371 insertions(+) create mode 100644 library/IXR_Library.php (limited to 'library') diff --git a/library/IXR_Library.php b/library/IXR_Library.php new file mode 100644 index 000000000..9e2537701 --- /dev/null +++ b/library/IXR_Library.php @@ -0,0 +1,1371 @@ +data = $data; + if (!$type) { + $type = $this->calculateType(); + } + $this->type = $type; + if ($type == 'struct') { + // Turn all the values in the array in to new IXR_Value objects + foreach ($this->data as $key => $value) { + $this->data[$key] = new IXR_Value($value); + } + } + if ($type == 'array') { + for ($i = 0, $j = count($this->data); $i < $j; $i++) { + $this->data[$i] = new IXR_Value($this->data[$i]); + } + } + } + + function calculateType() + { + if ($this->data === true || $this->data === false) { + return 'boolean'; + } + if (is_integer($this->data)) { + return 'int'; + } + if (is_double($this->data)) { + return 'double'; + } + + // Deal with IXR object types base64 and date + if (is_object($this->data) && is_a($this->data, 'IXR_Date')) { + return 'date'; + } + if (is_object($this->data) && is_a($this->data, 'IXR_Base64')) { + return 'base64'; + } + + // If it is a normal PHP object convert it in to a struct + if (is_object($this->data)) { + $this->data = get_object_vars($this->data); + return 'struct'; + } + if (!is_array($this->data)) { + return 'string'; + } + + // We have an array - is it an array or a struct? + if ($this->isStruct($this->data)) { + return 'struct'; + } else { + return 'array'; + } + } + + function getXml() + { + // Return XML for this value + switch ($this->type) { + case 'boolean': + return ''.(($this->data) ? '1' : '0').''; + break; + case 'int': + return ''.$this->data.''; + break; + case 'double': + return ''.$this->data.''; + break; + case 'string': + return ''.htmlspecialchars($this->data).''; + break; + case 'array': + $return = ''."\n"; + foreach ($this->data as $item) { + $return .= ' '.$item->getXml()."\n"; + } + $return .= ''; + return $return; + break; + case 'struct': + $return = ''."\n"; + foreach ($this->data as $name => $value) { + $return .= " $name"; + $return .= $value->getXml()."\n"; + } + $return .= ''; + return $return; + break; + case 'date': + case 'base64': + return $this->data->getXml(); + break; + } + return false; + } + + /** + * Checks whether or not the supplied array is a struct or not + * + * @param unknown_type $array + * @return boolean + */ + function isStruct($array) + { + $expected = 0; + foreach ($array as $key => $value) { + if ((string)$key != (string)$expected) { + return true; + } + $expected++; + } + return false; + } +} + +/** + * IXR_MESSAGE + * + * @package IXR + * @since 1.5 + * + */ +class IXR_Message +{ + var $message; + var $messageType; // methodCall / methodResponse / fault + var $faultCode; + var $faultString; + var $methodName; + var $params; + + // Current variable stacks + var $_arraystructs = array(); // The stack used to keep track of the current array/struct + var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array + var $_currentStructName = array(); // A stack as well + var $_param; + var $_value; + var $_currentTag; + var $_currentTagContents; + // The XML parser + var $_parser; + + function IXR_Message($message) + { + $this->message =& $message; + } + + function parse() + { + // first remove the XML declaration + // merged from WP #10698 - this method avoids the RAM usage of preg_replace on very large messages + $header = preg_replace( '/<\?xml.*?\?'.'>/', '', substr($this->message, 0, 100), 1); + $this->message = substr_replace($this->message, $header, 0, 100); + if (trim($this->message) == '') { + return false; + } + $this->_parser = xml_parser_create(); + // Set XML parser to take the case of tags in to account + xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false); + // Set XML parser callback functions + xml_set_object($this->_parser, $this); + xml_set_element_handler($this->_parser, 'tag_open', 'tag_close'); + xml_set_character_data_handler($this->_parser, 'cdata'); + $chunk_size = 262144; // 256Kb, parse in chunks to avoid the RAM usage on very large messages + do { + if (strlen($this->message) <= $chunk_size) { + $final = true; + } + $part = substr($this->message, 0, $chunk_size); + $this->message = substr($this->message, $chunk_size); + if (!xml_parse($this->_parser, $part, $final)) { + return false; + } + if ($final) { + break; + } + } while (true); + xml_parser_free($this->_parser); + + // Grab the error messages, if any + if ($this->messageType == 'fault') { + $this->faultCode = $this->params[0]['faultCode']; + $this->faultString = $this->params[0]['faultString']; + } + return true; + } + + function tag_open($parser, $tag, $attr) + { + $this->_currentTagContents = ''; + $this->currentTag = $tag; + switch($tag) { + case 'methodCall': + case 'methodResponse': + case 'fault': + $this->messageType = $tag; + break; + /* Deal with stacks of arrays and structs */ + case 'data': // data is to all intents and puposes more interesting than array + $this->_arraystructstypes[] = 'array'; + $this->_arraystructs[] = array(); + break; + case 'struct': + $this->_arraystructstypes[] = 'struct'; + $this->_arraystructs[] = array(); + break; + } + } + + function cdata($parser, $cdata) + { + $this->_currentTagContents .= $cdata; + } + + function tag_close($parser, $tag) + { + $valueFlag = false; + switch($tag) { + case 'int': + case 'i4': + $value = (int)trim($this->_currentTagContents); + $valueFlag = true; + break; + case 'double': + $value = (double)trim($this->_currentTagContents); + $valueFlag = true; + break; + case 'string': + $value = (string)trim($this->_currentTagContents); + $valueFlag = true; + break; + case 'dateTime.iso8601': + $value = new IXR_Date(trim($this->_currentTagContents)); + $valueFlag = true; + break; + case 'value': + // "If no type is indicated, the type is string." + if (trim($this->_currentTagContents) != '') { + $value = (string)$this->_currentTagContents; + $valueFlag = true; + } + break; + case 'boolean': + $value = (boolean)trim($this->_currentTagContents); + $valueFlag = true; + break; + case 'base64': + $value = base64_decode($this->_currentTagContents); + $valueFlag = true; + break; + /* Deal with stacks of arrays and structs */ + case 'data': + case 'struct': + $value = array_pop($this->_arraystructs); + array_pop($this->_arraystructstypes); + $valueFlag = true; + break; + case 'member': + array_pop($this->_currentStructName); + break; + case 'name': + $this->_currentStructName[] = trim($this->_currentTagContents); + break; + case 'methodName': + $this->methodName = trim($this->_currentTagContents); + break; + } + + if ($valueFlag) { + if (count($this->_arraystructs) > 0) { + // Add value to struct or array + if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') { + // Add to struct + $this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value; + } else { + // Add to array + $this->_arraystructs[count($this->_arraystructs)-1][] = $value; + } + } else { + // Just add as a paramater + $this->params[] = $value; + } + } + $this->_currentTagContents = ''; + } +} + +/** + * IXR_Server + * + * @package IXR + * @since 1.5 + */ +class IXR_Server +{ + var $data; + var $callbacks = array(); + var $message; + var $capabilities; + + function IXR_Server($callbacks = false, $data = false, $wait = false) + { + $this->setCapabilities(); + if ($callbacks) { + $this->callbacks = $callbacks; + } + $this->setCallbacks(); + if (!$wait) { + $this->serve($data); + } + } + + function serve($data = false) + { + if (!$data) { + if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] !== 'POST') { + header('Content-Type: text/plain'); // merged from WP #9093 + die('XML-RPC server accepts POST requests only.'); + } + + global $HTTP_RAW_POST_DATA; + if (empty($HTTP_RAW_POST_DATA)) { + // workaround for a bug in PHP 5.2.2 - http://bugs.php.net/bug.php?id=41293 + $data = file_get_contents('php://input'); + } else { + $data =& $HTTP_RAW_POST_DATA; + } + } + $this->message = new IXR_Message($data); + if (!$this->message->parse()) { + $this->error(-32700, 'parse error. not well formed'); + } + if ($this->message->messageType != 'methodCall') { + $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall'); + } + $result = $this->call($this->message->methodName, $this->message->params); + + // Is the result an error? + if (is_a($result, 'IXR_Error')) { + $this->error($result); + } + + // Encode the result + $r = new IXR_Value($result); + $resultxml = $r->getXml(); + + // Create the XML + $xml = << + + + + $resultxml + + + + + +EOD; + // Send it + $this->output($xml); + } + + function call($methodname, $args) + { + if (!$this->hasMethod($methodname)) { + return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.'); + } + $method = $this->callbacks[$methodname]; + + // Perform the callback and send the response + if (count($args) == 1) { + // If only one paramater just send that instead of the whole array + $args = $args[0]; + } + + // Are we dealing with a function or a method? + if (is_string($method) && substr($method, 0, 5) == 'this:') { + // It's a class method - check it exists + $method = substr($method, 5); + if (!method_exists($this, $method)) { + return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.'); + } + + //Call the method + $result = $this->$method($args); + } else { + // It's a function - does it exist? + if (is_array($method)) { + if (!method_exists($method[0], $method[1])) { + return new IXR_Error(-32601, 'server error. requested object method "'.$method[1].'" does not exist.'); + } + } else if (!function_exists($method)) { + return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.'); + } + + // Call the function + $result = call_user_func($method, $args); + } + return $result; + } + + function error($error, $message = false) + { + // Accepts either an error object or an error code and message + if ($message && !is_object($error)) { + $error = new IXR_Error($error, $message); + } + $this->output($error->getXml()); + } + + function output($xml) + { + $xml = ''."\n".$xml; + $length = strlen($xml); + header('Connection: close'); + header('Content-Length: '.$length); + header('Content-Type: text/xml'); + header('Date: '.date('r')); + echo $xml; + exit; + } + + function hasMethod($method) + { + return in_array($method, array_keys($this->callbacks)); + } + + function setCapabilities() + { + // Initialises capabilities array + $this->capabilities = array( + 'xmlrpc' => array( + 'specUrl' => 'http://www.xmlrpc.com/spec', + 'specVersion' => 1 + ), + 'faults_interop' => array( + 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php', + 'specVersion' => 20010516 + ), + 'system.multicall' => array( + 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208', + 'specVersion' => 1 + ), + ); + } + + function getCapabilities($args) + { + return $this->capabilities; + } + + function setCallbacks() + { + $this->callbacks['system.getCapabilities'] = 'this:getCapabilities'; + $this->callbacks['system.listMethods'] = 'this:listMethods'; + $this->callbacks['system.multicall'] = 'this:multiCall'; + } + + function listMethods($args) + { + // Returns a list of methods - uses array_reverse to ensure user defined + // methods are listed before server defined methods + return array_reverse(array_keys($this->callbacks)); + } + + function multiCall($methodcalls) + { + // See http://www.xmlrpc.com/discuss/msgReader$1208 + $return = array(); + foreach ($methodcalls as $call) { + $method = $call['methodName']; + $params = $call['params']; + if ($method == 'system.multicall') { + $result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden'); + } else { + $result = $this->call($method, $params); + } + if (is_a($result, 'IXR_Error')) { + $return[] = array( + 'faultCode' => $result->code, + 'faultString' => $result->message + ); + } else { + $return[] = array($result); + } + } + return $return; + } +} + +/** + * IXR_Request + * + * @package IXR + * @since 1.5 + */ +class IXR_Request +{ + var $method; + var $args; + var $xml; + + function IXR_Request($method, $args) + { + $this->method = $method; + $this->args = $args; + $this->xml = << + +{$this->method} + + +EOD; + foreach ($this->args as $arg) { + $this->xml .= ''; + $v = new IXR_Value($arg); + $this->xml .= $v->getXml(); + $this->xml .= "\n"; + } + $this->xml .= ''; + } + + function getLength() + { + return strlen($this->xml); + } + + function getXml() + { + return $this->xml; + } +} + +/** + * IXR_Client + * + * @package IXR + * @since 1.5 + * + */ +class IXR_Client +{ + var $server; + var $port; + var $path; + var $useragent; + var $response; + var $message = false; + var $debug = false; + var $timeout; + + // Storage place for an error message + var $error = false; + + function IXR_Client($server, $path = false, $port = 80, $timeout = 15) + { + if (!$path) { + // Assume we have been given a URL instead + $bits = parse_url($server); + $this->server = $bits['host']; + $this->port = isset($bits['port']) ? $bits['port'] : 80; + $this->path = isset($bits['path']) ? $bits['path'] : '/'; + + // Make absolutely sure we have a path + if (!$this->path) { + $this->path = '/'; + } + } else { + $this->server = $server; + $this->path = $path; + $this->port = $port; + } + $this->useragent = 'The Incutio XML-RPC PHP Library'; + $this->timeout = $timeout; + } + + function query() + { + $args = func_get_args(); + $method = array_shift($args); + $request = new IXR_Request($method, $args); + $length = $request->getLength(); + $xml = $request->getXml(); + $r = "\r\n"; + $request = "POST {$this->path} HTTP/1.0$r"; + + // Merged from WP #8145 - allow custom headers + $this->headers['Host'] = $this->server; + $this->headers['Content-Type'] = 'text/xml'; + $this->headers['User-Agent'] = $this->useragent; + $this->headers['Content-Length']= $length; + + foreach( $this->headers as $header => $value ) { + $request .= "{$header}: {$value}{$r}"; + } + $request .= $r; + + $request .= $xml; + + // Now send the request + if ($this->debug) { + echo '
'.htmlspecialchars($request)."\n
\n\n"; + } + + if ($this->timeout) { + $fp = @fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout); + } else { + $fp = @fsockopen($this->server, $this->port, $errno, $errstr); + } + if (!$fp) { + $this->error = new IXR_Error(-32300, 'transport error - could not open socket'); + return false; + } + fputs($fp, $request); + $contents = ''; + $debugContents = ''; + $gotFirstLine = false; + $gettingHeaders = true; + while (!feof($fp)) { + $line = fgets($fp, 4096); + if (!$gotFirstLine) { + // Check line for '200' + if (strstr($line, '200') === false) { + $this->error = new IXR_Error(-32300, 'transport error - HTTP status code was not 200'); + return false; + } + $gotFirstLine = true; + } + if (trim($line) == '') { + $gettingHeaders = false; + } + if (!$gettingHeaders) { + // merged from WP #12559 - remove trim + $contents .= $line; + } + if ($this->debug) { + $debugContents .= $line; + } + } + if ($this->debug) { + echo '
'.htmlspecialchars($debugContents)."\n
\n\n"; + } + + // Now parse what we've got back + $this->message = new IXR_Message($contents); + if (!$this->message->parse()) { + // XML error + $this->error = new IXR_Error(-32700, 'parse error. not well formed'); + return false; + } + + // Is the message a fault? + if ($this->message->messageType == 'fault') { + $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString); + return false; + } + + // Message must be OK + return true; + } + + function getResponse() + { + // methodResponses can only have one param - return that + return $this->message->params[0]; + } + + function isError() + { + return (is_object($this->error)); + } + + function getErrorCode() + { + return $this->error->code; + } + + function getErrorMessage() + { + return $this->error->message; + } +} + + +/** + * IXR_Error + * + * @package IXR + * @since 1.5 + */ +class IXR_Error +{ + var $code; + var $message; + + function IXR_Error($code, $message) + { + $this->code = $code; + $this->message = htmlspecialchars($message); + } + + function getXml() + { + $xml = << + + + + + faultCode + {$this->code} + + + faultString + {$this->message} + + + + + + +EOD; + return $xml; + } +} + +/** + * IXR_Date + * + * @package IXR + * @since 1.5 + */ +class IXR_Date { + var $year; + var $month; + var $day; + var $hour; + var $minute; + var $second; + var $timezone; + + function IXR_Date($time) + { + // $time can be a PHP timestamp or an ISO one + if (is_numeric($time)) { + $this->parseTimestamp($time); + } else { + $this->parseIso($time); + } + } + + function parseTimestamp($timestamp) + { + $this->year = date('Y', $timestamp); + $this->month = date('m', $timestamp); + $this->day = date('d', $timestamp); + $this->hour = date('H', $timestamp); + $this->minute = date('i', $timestamp); + $this->second = date('s', $timestamp); + $this->timezone = ''; + } + + function parseIso($iso) + { + $this->year = substr($iso, 0, 4); + $this->month = substr($iso, 4, 2); + $this->day = substr($iso, 6, 2); + $this->hour = substr($iso, 9, 2); + $this->minute = substr($iso, 12, 2); + $this->second = substr($iso, 15, 2); + $this->timezone = substr($iso, 17); + } + + function getIso() + { + return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second.$this->timezone; + } + + function getXml() + { + return ''.$this->getIso().''; + } + + function getTimestamp() + { + return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year); + } +} + +/** + * IXR_Base64 + * + * @package IXR + * @since 1.5 + */ +class IXR_Base64 +{ + var $data; + + function IXR_Base64($data) + { + $this->data = $data; + } + + function getXml() + { + return ''.base64_encode($this->data).''; + } +} + +/** + * IXR_IntrospectionServer + * + * @package IXR + * @since 1.5 + */ +class IXR_IntrospectionServer extends IXR_Server +{ + var $signatures; + var $help; + + function IXR_IntrospectionServer() + { + $this->setCallbacks(); + $this->setCapabilities(); + $this->capabilities['introspection'] = array( + 'specUrl' => 'http://xmlrpc.usefulinc.com/doc/reserved.html', + 'specVersion' => 1 + ); + $this->addCallback( + 'system.methodSignature', + 'this:methodSignature', + array('array', 'string'), + 'Returns an array describing the return type and required parameters of a method' + ); + $this->addCallback( + 'system.getCapabilities', + 'this:getCapabilities', + array('struct'), + 'Returns a struct describing the XML-RPC specifications supported by this server' + ); + $this->addCallback( + 'system.listMethods', + 'this:listMethods', + array('array'), + 'Returns an array of available methods on this server' + ); + $this->addCallback( + 'system.methodHelp', + 'this:methodHelp', + array('string', 'string'), + 'Returns a documentation string for the specified method' + ); + } + + function addCallback($method, $callback, $args, $help) + { + $this->callbacks[$method] = $callback; + $this->signatures[$method] = $args; + $this->help[$method] = $help; + } + + function call($methodname, $args) + { + // Make sure it's in an array + if ($args && !is_array($args)) { + $args = array($args); + } + + // Over-rides default call method, adds signature check + if (!$this->hasMethod($methodname)) { + return new IXR_Error(-32601, 'server error. requested method "'.$this->message->methodName.'" not specified.'); + } + $method = $this->callbacks[$methodname]; + $signature = $this->signatures[$methodname]; + $returnType = array_shift($signature); + + // Check the number of arguments + if (count($args) != count($signature)) { + return new IXR_Error(-32602, 'server error. wrong number of method parameters'); + } + + // Check the argument types + $ok = true; + $argsbackup = $args; + for ($i = 0, $j = count($args); $i < $j; $i++) { + $arg = array_shift($args); + $type = array_shift($signature); + switch ($type) { + case 'int': + case 'i4': + if (is_array($arg) || !is_int($arg)) { + $ok = false; + } + break; + case 'base64': + case 'string': + if (!is_string($arg)) { + $ok = false; + } + break; + case 'boolean': + if ($arg !== false && $arg !== true) { + $ok = false; + } + break; + case 'float': + case 'double': + if (!is_float($arg)) { + $ok = false; + } + break; + case 'date': + case 'dateTime.iso8601': + if (!is_a($arg, 'IXR_Date')) { + $ok = false; + } + break; + } + if (!$ok) { + return new IXR_Error(-32602, 'server error. invalid method parameters'); + } + } + // It passed the test - run the "real" method call + return parent::call($methodname, $argsbackup); + } + + function methodSignature($method) + { + if (!$this->hasMethod($method)) { + return new IXR_Error(-32601, 'server error. requested method "'.$method.'" not specified.'); + } + // We should be returning an array of types + $types = $this->signatures[$method]; + $return = array(); + foreach ($types as $type) { + switch ($type) { + case 'string': + $return[] = 'string'; + break; + case 'int': + case 'i4': + $return[] = 42; + break; + case 'double': + $return[] = 3.1415; + break; + case 'dateTime.iso8601': + $return[] = new IXR_Date(time()); + break; + case 'boolean': + $return[] = true; + break; + case 'base64': + $return[] = new IXR_Base64('base64'); + break; + case 'array': + $return[] = array('array'); + break; + case 'struct': + $return[] = array('struct' => 'struct'); + break; + } + } + return $return; + } + + function methodHelp($method) + { + return $this->help[$method]; + } +} + +/** + * IXR_ClientMulticall + * + * @package IXR + * @since 1.5 + */ +class IXR_ClientMulticall extends IXR_Client +{ + var $calls = array(); + + function IXR_ClientMulticall($server, $path = false, $port = 80) + { + parent::IXR_Client($server, $path, $port); + $this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)'; + } + + function addCall() + { + $args = func_get_args(); + $methodName = array_shift($args); + $struct = array( + 'methodName' => $methodName, + 'params' => $args + ); + $this->calls[] = $struct; + } + + function query() + { + // Prepare multicall, then call the parent::query() method + return parent::query('system.multicall', $this->calls); + } +} + +/** + * Client for communicating with a XML-RPC Server over HTTPS. + * + * @author Jason Stirk (@link http://blog.griffin.homelinux.org/projects/xmlrpc/) + * @version 0.2.0 26May2005 08:34 +0800 + * @copyright (c) 2004-2005 Jason Stirk + * @package IXR + */ +class IXR_ClientSSL extends IXR_Client +{ + /** + * Filename of the SSL Client Certificate + * @access private + * @since 0.1.0 + * @var string + */ + var $_certFile; + + /** + * Filename of the SSL CA Certificate + * @access private + * @since 0.1.0 + * @var string + */ + var $_caFile; + + /** + * Filename of the SSL Client Private Key + * @access private + * @since 0.1.0 + * @var string + */ + var $_keyFile; + + /** + * Passphrase to unlock the private key + * @access private + * @since 0.1.0 + * @var string + */ + var $_passphrase; + + /** + * Constructor + * @param string $server URL of the Server to connect to + * @since 0.1.0 + */ + function IXR_ClientSSL($server, $path = false, $port = 443, $timeout = false) + { + parent::IXR_Client($server, $path, $port, $timeout); + $this->useragent = 'The Incutio XML-RPC PHP Library for SSL'; + + // Set class fields + $this->_certFile=false; + $this->_caFile=false; + $this->_keyFile=false; + $this->_passphrase=''; + } + + /** + * Set the client side certificates to communicate with the server. + * + * @since 0.1.0 + * @param string $certificateFile Filename of the client side certificate to use + * @param string $keyFile Filename of the client side certificate's private key + * @param string $keyPhrase Passphrase to unlock the private key + */ + function setCertificate($certificateFile, $keyFile, $keyPhrase='') + { + // Check the files all exist + if (is_file($certificateFile)) { + $this->_certFile = $certificateFile; + } else { + die('Could not open certificate: ' . $certificateFile); + } + + if (is_file($keyFile)) { + $this->_keyFile = $keyFile; + } else { + die('Could not open private key: ' . $keyFile); + } + + $this->_passphrase=(string)$keyPhrase; + } + + function setCACertificate($caFile) + { + if (is_file($caFile)) { + $this->_caFile = $caFile; + } else { + die('Could not open CA certificate: ' . $caFile); + } + } + + /** + * Sets the connection timeout (in seconds) + * @param int $newTimeOut Timeout in seconds + * @returns void + * @since 0.1.2 + */ + function setTimeOut($newTimeOut) + { + $this->timeout = (int)$newTimeOut; + } + + /** + * Returns the connection timeout (in seconds) + * @returns int + * @since 0.1.2 + */ + function getTimeOut() + { + return $this->timeout; + } + + /** + * Set the query to send to the XML-RPC Server + * @since 0.1.0 + */ + function query() + { + $args = func_get_args(); + $method = array_shift($args); + $request = new IXR_Request($method, $args); + $length = $request->getLength(); + $xml = $request->getXml(); + + if ($this->debug) { + echo '
'.htmlspecialchars($xml)."\n
\n\n"; + } + + //This is where we deviate from the normal query() + //Rather than open a normal sock, we will actually use the cURL + //extensions to make the calls, and handle the SSL stuff. + + //Since 04Aug2004 (0.1.3) - Need to include the port (duh...) + //Since 06Oct2004 (0.1.4) - Need to include the colon!!! + // (I swear I've fixed this before... ESP in live... But anyhu...) + $curl=curl_init('https://' . $this->server . ':' . $this->port . $this->path); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + + //Since 23Jun2004 (0.1.2) - Made timeout a class field + curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout); + + if ($this->debug) { + curl_setopt($curl, CURLOPT_VERBOSE, 1); + } + + curl_setopt($curl, CURLOPT_HEADER, 1); + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $xml); + curl_setopt($curl, CURLOPT_PORT, $this->port); + curl_setopt($curl, CURLOPT_HTTPHEADER, array( + "Content-Type: text/xml", + "Content-length: {$length}")); + + // Process the SSL certificates, etc. to use + if (!($this->_certFile === false)) { + // We have a certificate file set, so add these to the cURL handler + curl_setopt($curl, CURLOPT_SSLCERT, $this->_certFile); + curl_setopt($curl, CURLOPT_SSLKEY, $this->_keyFile); + + if ($this->debug) { + echo "SSL Cert at : " . $this->_certFile . "\n"; + echo "SSL Key at : " . $this->_keyFile . "\n"; + } + + // See if we need to give a passphrase + if (!($this->_passphrase === '')) { + curl_setopt($curl, CURLOPT_SSLCERTPASSWD, $this->_passphrase); + } + + if ($this->_caFile === false) { + // Don't verify their certificate, as we don't have a CA to verify against + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); + } else { + // Verify against a CA + curl_setopt($curl, CURLOPT_CAINFO, $this->_caFile); + } + } + + // Call cURL to do it's stuff and return us the content + $contents = curl_exec($curl); + curl_close($curl); + + // Check for 200 Code in $contents + if (!strstr($contents, '200 OK')) { + //There was no "200 OK" returned - we failed + $this->error = new IXR_Error(-32300, 'transport error - HTTP status code was not 200'); + return false; + } + + if ($this->debug) { + echo '
'.htmlspecialchars($contents)."\n
\n\n"; + } + // Now parse what we've got back + // Since 20Jun2004 (0.1.1) - We need to remove the headers first + // Why I have only just found this, I will never know... + // So, remove everything before the first < + $contents = substr($contents,strpos($contents, '<')); + + $this->message = new IXR_Message($contents); + if (!$this->message->parse()) { + // XML error + $this->error = new IXR_Error(-32700, 'parse error. not well formed'); + return false; + } + // Is the message a fault? + if ($this->message->messageType == 'fault') { + $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString); + return false; + } + + // Message must be OK + return true; + } +} + +/** + * Extension of the {@link IXR_Server} class to easily wrap objects. + * + * Class is designed to extend the existing XML-RPC server to allow the + * presentation of methods from a variety of different objects via an + * XML-RPC server. + * It is intended to assist in organization of your XML-RPC methods by allowing + * you to "write once" in your existing model classes and present them. + * + * @author Jason Stirk + * @version 1.0.1 19Apr2005 17:40 +0800 + * @copyright Copyright (c) 2005 Jason Stirk + * @package IXR + */ +class IXR_ClassServer extends IXR_Server +{ + var $_objects; + var $_delim; + + function IXR_ClassServer($delim = '.', $wait = false) + { + $this->IXR_Server(array(), false, $wait); + $this->_delimiter = $delim; + $this->_objects = array(); + } + + function addMethod($rpcName, $functionName) + { + $this->callbacks[$rpcName] = $functionName; + } + + function registerObject($object, $methods, $prefix=null) + { + if (is_null($prefix)) + { + $prefix = get_class($object); + } + $this->_objects[$prefix] = $object; + + // Add to our callbacks array + foreach($methods as $method) + { + if (is_array($method)) + { + $targetMethod = $method[0]; + $method = $method[1]; + } + else + { + $targetMethod = $method; + } + $this->callbacks[$prefix . $this->_delimiter . $method]=array($prefix, $targetMethod); + } + } + + function call($methodname, $args) + { + if (!$this->hasMethod($methodname)) { + return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.'); + } + $method = $this->callbacks[$methodname]; + + // Perform the callback and send the response + if (count($args) == 1) { + // If only one paramater just send that instead of the whole array + $args = $args[0]; + } + + // See if this method comes from one of our objects or maybe self + if (is_array($method) || (substr($method, 0, 5) == 'this:')) { + if (is_array($method)) { + $object=$this->_objects[$method[0]]; + $method=$method[1]; + } else { + $object=$this; + $method = substr($method, 5); + } + + // It's a class method - check it exists + if (!method_exists($object, $method)) { + return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.'); + } + + // Call the method + $result = $object->$method($args); + } else { + // It's a function - does it exist? + if (!function_exists($method)) { + return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.'); + } + + // Call the function + $result = $method($args); + } + return $result; + } +} -- cgit v1.2.3 From b61658ee738edbebccfb0670c330522362c895d5 Mon Sep 17 00:00:00 2001 From: Christian Vogeley Date: Sun, 8 Dec 2013 19:37:41 +0100 Subject: bootbox --- library/bootstrap/js/bootbox.min.js | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 library/bootstrap/js/bootbox.min.js (limited to 'library') diff --git a/library/bootstrap/js/bootbox.min.js b/library/bootstrap/js/bootbox.min.js new file mode 100644 index 000000000..4ea792f3a --- /dev/null +++ b/library/bootstrap/js/bootbox.min.js @@ -0,0 +1,6 @@ +/** + * bootbox.js v4.1.0 + * + * http://bootboxjs.com/license.txt + */ +window.bootbox=window.bootbox||function a(b,c){"use strict";function d(a){var b=r[p.locale];return b?b[a]:r.en[a]}function e(a,c,d){a.preventDefault();var e=b.isFunction(d)&&d(a)===!1;e||c.modal("hide")}function f(a){var b,c=0;for(b in a)c++;return c}function g(a,c){var d=0;b.each(a,function(a,b){c(a,b,d++)})}function h(a){var c,d;if("object"!=typeof a)throw new Error("Please supply an object of options");if(!a.message)throw new Error("Please specify a message");return a=b.extend({},p,a),a.buttons||(a.buttons={}),a.backdrop=a.backdrop?"static":!1,c=a.buttons,d=f(c),g(c,function(a,e,f){if(b.isFunction(e)&&(e=c[a]={callback:e}),"object"!==b.type(e))throw new Error("button with key "+a+" must be an object");e.label||(e.label=a),e.className||(e.className=2>=d&&f===d-1?"btn-primary":"btn-default")}),a}function i(a,b){var c=a.length,d={};if(1>c||c>2)throw new Error("Invalid argument length");return 2===c||"string"==typeof a[0]?(d[b[0]]=a[0],d[b[1]]=a[1]):d=a[0],d}function j(a,c,d){return b.extend(!0,{},a,i(c,d))}function k(a,b,c,d){var e={className:"bootbox-"+a,buttons:l.apply(null,b)};return m(j(e,d,c),b)}function l(){for(var a={},b=0,c=arguments.length;c>b;b++){var e=arguments[b],f=e.toLowerCase(),g=e.toUpperCase();a[f]={label:d(g)}}return a}function m(a,b){var d={};return g(b,function(a,b){d[b]=!0}),g(a.buttons,function(a){if(d[a]===c)throw new Error("button key "+a+" is not allowed (options are "+b.join("\n")+")")}),a}var n={dialog:"",header:"",footer:"",closeButton:"",form:"
",inputs:{text:"",email:"",select:"",checkbox:"
"}},o=b("body"),p={locale:"en",backdrop:!0,animate:!0,className:null,closeButton:!0,show:!0},q={};q.alert=function(){var a;if(a=k("alert",["ok"],["message","callback"],arguments),a.callback&&!b.isFunction(a.callback))throw new Error("alert requires callback property to be a function when provided");return a.buttons.ok.callback=a.onEscape=function(){return b.isFunction(a.callback)?a.callback():!0},q.dialog(a)},q.confirm=function(){var a;if(a=k("confirm",["cancel","confirm"],["message","callback"],arguments),a.buttons.cancel.callback=a.onEscape=function(){return a.callback(!1)},a.buttons.confirm.callback=function(){return a.callback(!0)},!b.isFunction(a.callback))throw new Error("confirm requires a callback");return q.dialog(a)},q.prompt=function(){var a,d,e,f,h,i,k;if(f=b(n.form),d={className:"bootbox-prompt",buttons:l("cancel","confirm"),value:"",inputType:"text"},a=m(j(d,arguments,["title","callback"]),["cancel","confirm"]),i=a.show===c?!0:a.show,a.message=f,a.buttons.cancel.callback=a.onEscape=function(){return a.callback(null)},a.buttons.confirm.callback=function(){var c;switch(a.inputType){case"text":case"email":case"select":c=h.val();break;case"checkbox":var d=h.find("input:checked");c=[],g(d,function(a,d){c.push(b(d).val())})}return a.callback(c)},a.show=!1,!a.title)throw new Error("prompt requires a title");if(!b.isFunction(a.callback))throw new Error("prompt requires a callback");if(!n.inputs[a.inputType])throw new Error("invalid prompt type");switch(h=b(n.inputs[a.inputType]),a.inputType){case"text":case"email":h.val(a.value);break;case"select":var o={};if(k=a.inputOptions||[],!k.length)throw new Error("prompt with select requires options");g(k,function(a,d){var e=h;if(d.value===c||d.text===c)throw new Error("given options in wrong format");d.group&&(o[d.group]||(o[d.group]=b("").attr("label",d.group)),e=o[d.group]),e.append("")}),g(o,function(a,b){h.append(b)}),h.val(a.value);break;case"checkbox":var p=b.isArray(a.value)?a.value:[a.value];if(k=a.inputOptions||[],!k.length)throw new Error("prompt with checkbox requires options");if(!k[0].value||!k[0].text)throw new Error("given options in wrong format");h=b("
"),g(k,function(c,d){var e=b(n.inputs[a.inputType]);e.find("input").attr("value",d.value),e.find("label").append(d.text),g(p,function(a,b){b===d.value&&e.find("input").prop("checked",!0)}),h.append(e)})}return a.placeholder&&h.attr("placeholder",a.placeholder),f.append(h),f.on("submit",function(a){a.preventDefault(),e.find(".btn-primary").click()}),e=q.dialog(a),e.off("shown.bs.modal"),e.on("shown.bs.modal",function(){h.focus()}),i===!0&&e.modal("show"),e},q.dialog=function(a){a=h(a);var c=b(n.dialog),d=c.find(".modal-body"),f=a.buttons,i="",j={onEscape:a.onEscape};if(g(f,function(a,b){i+="",j[a]=b.callback}),d.find(".bootbox-body").html(a.message),a.animate===!0&&c.addClass("fade"),a.className&&c.addClass(a.className),a.title&&d.before(n.header),a.closeButton){var k=b(n.closeButton);a.title?c.find(".modal-header").prepend(k):k.css("margin-top","-10px").prependTo(d)}return a.title&&c.find(".modal-title").html(a.title),i.length&&(d.after(n.footer),c.find(".modal-footer").html(i)),c.on("hidden.bs.modal",function(a){a.target===this&&c.remove()}),c.on("shown.bs.modal",function(){c.find(".btn-primary:first").focus()}),c.on("escape.close.bb",function(a){j.onEscape&&e(a,c,j.onEscape)}),c.on("click",".modal-footer button",function(a){var d=b(this).data("bb-handler");e(a,c,j[d])}),c.on("click",".bootbox-close-button",function(a){e(a,c,j.onEscape)}),c.on("keyup",function(a){27===a.which&&c.trigger("escape.close.bb")}),o.append(c),c.modal({backdrop:a.backdrop,keyboard:!1,show:!1}),a.show&&c.modal("show"),c},q.setDefaults=function(){var a={};2===arguments.length?a[arguments[0]]=arguments[1]:a=arguments[0],b.extend(p,a)},q.hideAll=function(){b(".bootbox").modal("hide")};var r={br:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Sim"},da:{OK:"OK",CANCEL:"Annuller",CONFIRM:"Accepter"},de:{OK:"OK",CANCEL:"Abbrechen",CONFIRM:"Akzeptieren"},en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},es:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Aceptar"},fi:{OK:"OK",CANCEL:"Peruuta",CONFIRM:"OK"},fr:{OK:"OK",CANCEL:"Annuler",CONFIRM:"D'accord"},it:{OK:"OK",CANCEL:"Annulla",CONFIRM:"Conferma"},nl:{OK:"OK",CANCEL:"Annuleren",CONFIRM:"Accepteren"},no:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},pl:{OK:"OK",CANCEL:"Anuluj",CONFIRM:"Potwierdź"},ru:{OK:"OK",CANCEL:"Отмена",CONFIRM:"Применить"},zh_CN:{OK:"OK",CANCEL:"取消",CONFIRM:"确认"},zh_TW:{OK:"OK",CANCEL:"取消",CONFIRM:"確認"}};return q.init=function(c){window.bootbox=a(c||b)},q}(window.jQuery); \ No newline at end of file -- cgit v1.2.3 From 6a9432c725efb9f313282c7ca8ce954ea9be8c75 Mon Sep 17 00:00:00 2001 From: marijus Date: Mon, 9 Dec 2013 11:30:32 +0100 Subject: editor_plugin_src.js compressed at jscompress.com --- library/tinymce/jscripts/tiny_mce/plugins/bbcode/editor_plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library') diff --git a/library/tinymce/jscripts/tiny_mce/plugins/bbcode/editor_plugin.js b/library/tinymce/jscripts/tiny_mce/plugins/bbcode/editor_plugin.js index 8f8821fd6..81b69e736 100644 --- a/library/tinymce/jscripts/tiny_mce/plugins/bbcode/editor_plugin.js +++ b/library/tinymce/jscripts/tiny_mce/plugins/bbcode/editor_plugin.js @@ -1 +1 @@ -(function(){tinymce.create("tinymce.plugins.BBCodePlugin",{init:function(a,b){var d=this,c=a.getParam("bbcode_dialect","punbb").toLowerCase();a.onBeforeSetContent.add(function(e,f){f.content=d["_"+c+"_bbcode2html"](f.content)});a.onPostProcess.add(function(e,f){if(f.set){f.content=d["_"+c+"_bbcode2html"](f.content)}if(f.get){f.content=d["_"+c+"_html2bbcode"](f.content)}})},getInfo:function(){return{longname:"BBCode Plugin",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/bbcode",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_punbb_html2bbcode:function(a){a=tinymce.trim(a);function b(c,d){a=a.replace(c,d)}b(/(.*?)<\/a>/gi,"[url=$1]$2[/url]");b(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");b(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");b(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");b(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");b(/(.*?)<\/span>/gi,"[color=$1]$2[/color]");b(/(.*?)<\/font>/gi,"[color=$1]$2[/color]");b(/(.*?)<\/span>/gi,"[size=$1]$2[/size]");b(/(.*?)<\/font>/gi,"$1");b(//gi,"[img]$1[/img]");b(/(.*?)<\/span>/gi,"[code]$1[/code]");b(/(.*?)<\/span>/gi,"[quote]$1[/quote]");b(/(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]");b(/(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]");b(/(.*?)<\/em>/gi,"[code][i]$1[/i][/code]");b(/(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]");b(/(.*?)<\/u>/gi,"[code][u]$1[/u][/code]");b(/(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]");b(/<\/(strong|b)>/gi,"[/b]");b(/<(strong|b)>/gi,"[b]");b(/<\/(em|i)>/gi,"[/i]");b(/<(em|i)>/gi,"[i]");b(/<\/u>/gi,"[/u]");b(/(.*?)<\/span>/gi,"[u]$1[/u]");b(//gi,"[u]");b(/]*>/gi,"[quote]");b(/<\/blockquote>/gi,"[/quote]");b(/
/gi,"\n");b(//gi,"\n");b(/
/gi,"\n");b(/

/gi,"");b(/<\/p>/gi,"\n");b(/ |\u00a0/gi," ");b(/"/gi,'"');b(/</gi,"<");b(/>/gi,">");b(/&/gi,"&");return a},_punbb_bbcode2html:function(a){a=tinymce.trim(a);function b(c,d){a=a.replace(c,d)}b(/\n/gi,"
");b(/\[b\]/gi,"");b(/\[\/b\]/gi,"");b(/\[i\]/gi,"");b(/\[\/i\]/gi,"");b(/\[u\]/gi,"");b(/\[\/u\]/gi,"");b(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'$2');b(/\[url\](.*?)\[\/url\]/gi,'$1');b(/\[img\](.*?)\[\/img\]/gi,'');b(/\[color=(.*?)\](.*?)\[\/color\]/gi,'$2');b(/\[code\](.*?)\[\/code\]/gi,'$1 ');b(/\[quote.*?\](.*?)\[\/quote\]/gi,'$1 ');return a}});tinymce.PluginManager.add("bbcode",tinymce.plugins.BBCodePlugin)})(); \ No newline at end of file +(function(){tinymce.create("tinymce.plugins.BBCodePlugin",{init:function(e,t){var n=this,r=e.getParam("bbcode_dialect","dfrn").toLowerCase();e.onBeforeSetContent.add(function(e,t){t.content=n["_"+r+"_bbcode2html"](t.content)});e.onPostProcess.add(function(e,t){if(t.set)t.content=n["_"+r+"_bbcode2html"](t.content);if(t.get)t.content=n["_"+r+"_html2bbcode"](t.content)})},getInfo:function(){return{longname:"BBCode Plugin",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/bbcode",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_dfrn_html2bbcode:function(e){function t(t,n){e=e.replace(t,n)}function n(e){var t,n,r=[],i=[];var s=/]*class *= *[\"'](?:[^\"']* )*oembed(?: [^\"']*)*[\"'][^>]*>(.*?(?:]*>(.*?)<\/span *>)*.*?)<\/span *>/ig;while(t=s.exec(e)){var o=/]* rel=[\"']oembed[\"'][^>]*)>.*?<\/a *>/ig;if(n=o.exec(t[1])){var u=/href=[\"']([^\"']*)[\"']/ig;var a=u.exec(n[1]);if(a[1]){r.push(t[0]);i.push("[EMBED]"+a[1]+"[/EMBED]")}}}for(var f=0;f=0){e=n(e)}t(/(.*?)<\/a>/gi,"[url=$1]$2[/url]");t(/(.*?)<\/span>/gi,"[size=$1]$2[/size]");t(/(.*?)<\/span>/gi,"[color=$1]$2[/color]");t(/(.*?)<\/font>/gi,"$1");t(//gi,"[img=$1x$2]$3[/img]");t(//gi,"[img=$2x$1]$3[/img]");t(//gi,"[img=$3x$2]$1[/img]");t(//gi,"[img=$2x$3]$1[/img]");t(//gi,"[img]$1[/img]");t(/

    (.*?)<\/ul>/gi,"[list]$1[/list]");t(/
      (.*?)<\/ul>/gi,"[list=]$1[/list]");t(/
        (.*?)<\/ul>/gi,"[list=1]$1[/list]");t(/
          (.*?)<\/ul>/gi,"[list=i]$1[/list]");t(/
            (.*?)<\/ul>/gi,"[list=I]$1[/list]");t(/
              (.*?)<\/ul>/gi,"[list=a]$1[/list]");t(/
                (.*?)<\/ul>/gi,"[list=A]$1[/list]");t(/
              • (.*?)<\/li>/gi,"[li]$1[/li]");t(/(.*?)<\/code>/gi,"[code]$1[/code]");t(/<\/(strong|b)>/gi,"[/b]");t(/<(strong|b)>/gi,"[b]");t(/<\/(em|i)>/gi,"[/i]");t(/<(em|i)>/gi,"[i]");t(/<\/u>/gi,"[/u]");t(/(.*?)<\/span>/gi,"[u]$1[/u]");t(//gi,"[u]");t(/]*>/gi,"[quote]");t(/<\/blockquote>/gi,"[/quote]");t(/
                /gi,"[hr]");t(/
                /gi,"\n");t(//gi,"\n");t(/
                /gi,"\n");t(/

                /gi,"");t(/<\/p>/gi,"\n");t(/ /gi," ");t(/"/gi,'"');t(/</gi,"<");t(/>/gi,">");t(/&/gi,"&");return e},_dfrn_bbcode2html:function(e){function t(t,n){var r=new Array;var i=e.split("[code]");var o=0;var u="";u=i.shift();u=u.replace(t,n);r.push(u);for(o=0;o");t(/\[b\]/gi,"");t(/\[\/b\]/gi,"");t(/\[i\]/gi,"");t(/\[\/i\]/gi,"");t(/\[u\]/gi,"");t(/\[\/u\]/gi,"");t(/\[hr\]/gi,"


                ");t(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'$2');t(/\[url\](.*?)\[\/url\]/gi,'$1');t(/\[img=(.*?)x(.*?)\](.*?)\[\/img\]/gi,'');t(/\[img\](.*?)\[\/img\]/gi,'');t(/\[list\](.*?)\[\/list\]/gi,'
                  $1
                ');t(/\[list=\](.*?)\[\/list\]/gi,'
                  $1
                ');t(/\[list=1\](.*?)\[\/list\]/gi,'
                  $1
                ');t(/\[list=i\](.*?)\[\/list\]/gi,'
                  $1
                ');t(/\[list=I\](.*?)\[\/list\]/gi,'
                  $1
                ');t(/\[list=a\](.*?)\[\/list\]/gi,'
                  $1
                ');t(/\[list=A\](.*?)\[\/list\]/gi,'
                  $1
                ');t(/\[li\](.*?)\[\/li\]/gi,"
              • $1
              • ");t(/\[color=(.*?)\](.*?)\[\/color\]/gi,'$2');t(/\[size=(.*?)\](.*?)\[\/size\]/gi,'$2');t(/\[code\](.*?)\[\/code\]/gi,"$1");t(/\[quote.*?\](.*?)\[\/quote\]/gi,"
                $1
                ");e=e.replace(/\[embed\](.*?)\[\/embed\]/gi,n);return e}});tinymce.PluginManager.add("bbcode",tinymce.plugins.BBCodePlugin)})() -- cgit v1.2.3