mirror of
https://github.com/moodle/moodle.git
synced 2025-06-05 07:35:09 +02:00
mnet MDL-21473 make new tables for remote functions that don't exist locally
I also fixed up two columns in the existing table that had underscores in them
This commit is contained in:
parent
abd9a3d106
commit
8586dbe2a5
@ -57,8 +57,8 @@ function upgrade_plugin_mnet_functions($component) {
|
||||
|
||||
// Disable functions that don't exist (any more) in the source
|
||||
// Should these be deleted? What about their permissions records?
|
||||
foreach ($DB->get_records('mnet_rpc', array('pluginname'=>$plugin, 'plugintype'=>$type), 'function_name ASC ') as $rpc) {
|
||||
if (!array_key_exists($rpc->function_name, $methodservices)) {
|
||||
foreach ($DB->get_records('mnet_rpc', array('pluginname'=>$plugin, 'plugintype'=>$type), 'functionname ASC ') as $rpc) {
|
||||
if (!array_key_exists($rpc->functionname, $methodservices)) {
|
||||
$DB->set_field('mnet_rpc', 'enabled', 0, array('id' => $rpc->id));
|
||||
}
|
||||
}
|
||||
@ -77,57 +77,57 @@ function upgrade_plugin_mnet_functions($component) {
|
||||
$dataobject->filename = $f;
|
||||
|
||||
if (is_string($method)) {
|
||||
$dataobject->function_name = $method;
|
||||
$dataobject->functionname = $method;
|
||||
|
||||
} else if (is_array($method)) { // wants to override file or class
|
||||
$dataobject->function_name = $method['method'];
|
||||
$dataobject->functionname = $method['method'];
|
||||
$dataobject->classname = $method['classname'];
|
||||
$dataobject->filename = $method['filename'];
|
||||
}
|
||||
$dataobject->xmlrpc_path = $type.'/'.$plugin.'/'.$dataobject->filename.'/'.$method;
|
||||
$dataobject->xmlrpcpath = $type.'/'.$plugin.'/'.$dataobject->filename.'/'.$method;
|
||||
$dataobject->static = false;
|
||||
|
||||
require_once($path . '/' . $dataobject->filename);
|
||||
$functionreflect = null; // slightly different ways to get this depending on whether it's a class method or a function
|
||||
if (!empty($dataobject->classname)) {
|
||||
if (!class_exists($dataobject->classname)) {
|
||||
throw new moodle_exception('installnosuchmethod', 'mnet', '', (object)array('method' => $dataobject->function_name, 'class' => $dataobject->classname));
|
||||
throw new moodle_exception('installnosuchmethod', 'mnet', '', (object)array('method' => $dataobject->functionname, 'class' => $dataobject->classname));
|
||||
}
|
||||
$key = $dataobject->filename . '|' . $dataobject->classname;
|
||||
if (!array_key_exists($key, $cachedclasses)) { // look to see if we've already got a reflection object
|
||||
try {
|
||||
$cachedclasses[$key] = Zend_Server_Reflection::reflectClass($dataobject->classname);
|
||||
} catch (Zend_Server_Reflection_Exception $e) { // catch these and rethrow them to something more helpful
|
||||
throw new moodle_exception('installreflectionclasserror', 'mnet', '', (object)array('method' => $dataobject->function_name, 'class' => $dataobject->classname, 'error' => $e->getMessage()));
|
||||
throw new moodle_exception('installreflectionclasserror', 'mnet', '', (object)array('method' => $dataobject->functionname, 'class' => $dataobject->classname, 'error' => $e->getMessage()));
|
||||
}
|
||||
}
|
||||
$r =& $cachedclasses[$key];
|
||||
if (!$r->hasMethod($dataobject->function_name)) {
|
||||
throw new moodle_exception('installnosuchmethod', 'mnet', '', (object)array('method' => $dataobject->function_name, 'class' => $dataobject->classname));
|
||||
if (!$r->hasMethod($dataobject->functionname)) {
|
||||
throw new moodle_exception('installnosuchmethod', 'mnet', '', (object)array('method' => $dataobject->functionname, 'class' => $dataobject->classname));
|
||||
}
|
||||
// stupid workaround for zend not having a getMethod($name) function
|
||||
$ms = $r->getMethods();
|
||||
foreach ($ms as $m) {
|
||||
if ($m->getName() == $dataobject->function_name) {
|
||||
if ($m->getName() == $dataobject->functionname) {
|
||||
$functionreflect = $m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$dataobject->static = (int)$functionreflect->isStatic();
|
||||
} else {
|
||||
if (!function_exists($dataobject->function_name)) {
|
||||
throw new moodle_exception('installnosuchfunction', 'mnet', '', (object)array('method' => $dataobject->function_name, 'file' => $dataobject->filename));
|
||||
if (!function_exists($dataobject->functionname)) {
|
||||
throw new moodle_exception('installnosuchfunction', 'mnet', '', (object)array('method' => $dataobject->functionname, 'file' => $dataobject->filename));
|
||||
}
|
||||
try {
|
||||
$functionreflect = Zend_Server_Reflection::reflectFunction($dataobject->function_name);
|
||||
$functionreflect = Zend_Server_Reflection::reflectFunction($dataobject->functionname);
|
||||
} catch (Zend_Server_Reflection_Exception $e) { // catch these and rethrow them to something more helpful
|
||||
throw new moodle_exception('installreflectionfunctionerror', 'mnet', '', (object)array('method' => $dataobject->function_name, '' => $dataobject->filename, 'error' => $e->getMessage()));
|
||||
throw new moodle_exception('installreflectionfunctionerror', 'mnet', '', (object)array('method' => $dataobject->functionname, '' => $dataobject->filename, 'error' => $e->getMessage()));
|
||||
}
|
||||
}
|
||||
$dataobject->profile = serialize(admin_mnet_method_profile($functionreflect));
|
||||
$dataobject->help = $functionreflect->getDescription();
|
||||
|
||||
if ($record_exists = $DB->get_record('mnet_rpc', array('xmlrpc_path'=>$dataobject->xmlrpc_path))) {
|
||||
if ($record_exists = $DB->get_record('mnet_rpc', array('xmlrpcpath'=>$dataobject->xmlrpcpath))) {
|
||||
$dataobject->id = $record_exists->id;
|
||||
$dataobject->enabled = $record_exists->enabled;
|
||||
$DB->update_record('mnet_rpc', $dataobject);
|
||||
@ -136,7 +136,7 @@ function upgrade_plugin_mnet_functions($component) {
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($methodservices[$dataobject->function_name] as $service) {
|
||||
foreach ($methodservices[$dataobject->functionname] as $service) {
|
||||
if ($serviceobj = $DB->get_record('mnet_service', array('name'=>$service['servicename']))) {
|
||||
$serviceobj->apiversion = $service['apiversion'];
|
||||
$DB->update_record('mnet_service', $serviceobj);
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<XMLDB PATH="lib/db" VERSION="20100126" COMMENT="XMLDB file for core Moodle tables"
|
||||
<XMLDB PATH="lib/db" VERSION="20100129" COMMENT="XMLDB file for core Moodle tables"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
@ -1320,12 +1320,12 @@
|
||||
<INDEX NAME="hostid_userid_course" UNIQUE="false" FIELDS="hostid, userid, course"/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
<TABLE NAME="mnet_rpc" COMMENT="Functions or methods that we may publish or subscribe to" PREVIOUS="mnet_log" NEXT="mnet_service">
|
||||
<TABLE NAME="mnet_rpc" COMMENT="Functions or methods that we may publish or subscribe to" PREVIOUS="mnet_log" NEXT="mnet_remote_rpc">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" COMMENT="Unique Function ID" NEXT="function_name"/>
|
||||
<FIELD NAME="function_name" TYPE="char" LENGTH="40" NOTNULL="true" SEQUENCE="false" PREVIOUS="id" NEXT="xmlrpc_path"/>
|
||||
<FIELD NAME="xmlrpc_path" TYPE="char" LENGTH="80" NOTNULL="true" SEQUENCE="false" PREVIOUS="function_name" NEXT="plugintype"/>
|
||||
<FIELD NAME="plugintype" TYPE="char" LENGTH="20" NOTNULL="true" SEQUENCE="false" PREVIOUS="xmlrpc_path" NEXT="pluginname"/>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" COMMENT="Unique Function ID" NEXT="functionname"/>
|
||||
<FIELD NAME="functionname" TYPE="char" LENGTH="40" NOTNULL="true" SEQUENCE="false" PREVIOUS="id" NEXT="xmlrpcpath"/>
|
||||
<FIELD NAME="xmlrpcpath" TYPE="char" LENGTH="80" NOTNULL="true" SEQUENCE="false" PREVIOUS="functionname" NEXT="plugintype"/>
|
||||
<FIELD NAME="plugintype" TYPE="char" LENGTH="20" NOTNULL="true" SEQUENCE="false" PREVIOUS="xmlrpcpath" NEXT="pluginname"/>
|
||||
<FIELD NAME="pluginname" TYPE="char" LENGTH="20" NOTNULL="true" SEQUENCE="false" PREVIOUS="plugintype" NEXT="enabled"/>
|
||||
<FIELD NAME="enabled" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="pluginname" NEXT="help"/>
|
||||
<FIELD NAME="help" TYPE="text" LENGTH="medium" NOTNULL="true" SEQUENCE="false" PREVIOUS="enabled" NEXT="profile"/>
|
||||
@ -1338,10 +1338,20 @@
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="primary key of the mnet_rpc table"/>
|
||||
</KEYS>
|
||||
<INDEXES>
|
||||
<INDEX NAME="enabled_xmlrpcpath" UNIQUE="false" FIELDS="enabled, xmlrpc_path"/>
|
||||
<INDEX NAME="enabled_xmlrpcpath" UNIQUE="false" FIELDS="enabled, xmlrpcpath"/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
<TABLE NAME="mnet_service" COMMENT="A service is a group of functions" PREVIOUS="mnet_rpc" NEXT="mnet_service2rpc">
|
||||
<TABLE NAME="mnet_remote_rpc" COMMENT="This table describes functions that might be called remotely (we have less information about them than local functions)" PREVIOUS="mnet_rpc" NEXT="mnet_service">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="functionname"/>
|
||||
<FIELD NAME="functionname" TYPE="char" LENGTH="40" NOTNULL="true" SEQUENCE="false" PREVIOUS="id" NEXT="xmlrpcpath"/>
|
||||
<FIELD NAME="xmlrpcpath" TYPE="char" LENGTH="80" NOTNULL="true" SEQUENCE="false" PREVIOUS="functionname"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="mnet_service" COMMENT="A service is a group of functions" PREVIOUS="mnet_remote_rpc" NEXT="mnet_service2rpc">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" COMMENT="Unique Service ID" NEXT="name"/>
|
||||
<FIELD NAME="name" TYPE="char" LENGTH="40" NOTNULL="true" SEQUENCE="false" PREVIOUS="id" NEXT="description"/>
|
||||
@ -1353,7 +1363,7 @@
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="primary key of the mnet_service table"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="mnet_service2rpc" COMMENT="Group functions or methods under a service" PREVIOUS="mnet_service" NEXT="mnet_session">
|
||||
<TABLE NAME="mnet_service2rpc" COMMENT="Group functions or methods under a service" PREVIOUS="mnet_service" NEXT="mnet_remote_service2rpc">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" COMMENT="Required ID field" NEXT="serviceid"/>
|
||||
<FIELD NAME="serviceid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="Unique service ID" PREVIOUS="id" NEXT="rpcid"/>
|
||||
@ -1366,7 +1376,20 @@
|
||||
<INDEX NAME="rpcid_serviceid" UNIQUE="true" FIELDS="rpcid, serviceid"/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
<TABLE NAME="mnet_session" COMMENT="Store session data from users migrating to other sites" PREVIOUS="mnet_service2rpc" NEXT="mnet_sso_access_control">
|
||||
<TABLE NAME="mnet_remote_service2rpc" COMMENT="Group functions or methods under a service" PREVIOUS="mnet_service2rpc" NEXT="mnet_session">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" COMMENT="Required ID field" NEXT="serviceid"/>
|
||||
<FIELD NAME="serviceid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="Unique service ID" PREVIOUS="id" NEXT="rpcid"/>
|
||||
<FIELD NAME="rpcid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="Unique Function ID" PREVIOUS="serviceid"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="primary key of the mnet_remote_service2rpc table"/>
|
||||
</KEYS>
|
||||
<INDEXES>
|
||||
<INDEX NAME="rpcid_serviceid" UNIQUE="true" FIELDS="rpcid, serviceid"/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
<TABLE NAME="mnet_session" COMMENT="Store session data from users migrating to other sites" PREVIOUS="mnet_remote_service2rpc" NEXT="mnet_sso_access_control">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" COMMENT="Required ID field" NEXT="userid"/>
|
||||
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="Unique user ID" PREVIOUS="id" NEXT="username"/>
|
||||
@ -2365,4 +2388,4 @@
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
</TABLES>
|
||||
</XMLDB>
|
||||
</XMLDB>
|
||||
|
@ -2903,6 +2903,64 @@ WHERE gradeitemid IS NOT NULL AND grademax IS NOT NULL");
|
||||
upgrade_main_savepoint($result, 2010012600);
|
||||
}
|
||||
|
||||
if ($result && $oldversion < 2010012900) {
|
||||
|
||||
/// Define table mnet_remote_rpc to be created
|
||||
$table = new xmldb_table('mnet_remote_rpc');
|
||||
|
||||
/// Adding fields to table mnet_remote_rpc
|
||||
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
|
||||
$table->add_field('functionname', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('xmlrpcpath', XMLDB_TYPE_CHAR, '80', null, XMLDB_NOTNULL, null, null);
|
||||
|
||||
/// Adding keys to table mnet_remote_rpc
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
|
||||
/// Conditionally launch create table for mnet_remote_rpc
|
||||
if (!$dbman->table_exists($table)) {
|
||||
$dbman->create_table($table);
|
||||
}
|
||||
|
||||
|
||||
/// Define table mnet_remote_service2rpc to be created
|
||||
$table = new xmldb_table('mnet_remote_service2rpc');
|
||||
|
||||
/// Adding fields to table mnet_remote_service2rpc
|
||||
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
|
||||
$table->add_field('serviceid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
|
||||
$table->add_field('rpcid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
|
||||
|
||||
/// Adding keys to table mnet_remote_service2rpc
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
|
||||
/// Adding indexes to table mnet_remote_service2rpc
|
||||
$table->add_index('rpcid_serviceid', XMLDB_INDEX_UNIQUE, array('rpcid', 'serviceid'));
|
||||
|
||||
/// Conditionally launch create table for mnet_remote_service2rpc
|
||||
if (!$dbman->table_exists($table)) {
|
||||
$dbman->create_table($table);
|
||||
}
|
||||
|
||||
|
||||
/// Rename field function_name on table mnet_rpc to functionname
|
||||
$table = new xmldb_table('mnet_rpc');
|
||||
$field = new xmldb_field('function_name', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null, 'id');
|
||||
|
||||
/// Launch rename field function_name
|
||||
$dbman->rename_field($table, $field, 'functionname');
|
||||
|
||||
|
||||
/// Rename field xmlrpc_path on table mnet_rpc to xmlrpcpath
|
||||
$table = new xmldb_table('mnet_rpc');
|
||||
$field = new xmldb_field('xmlrpc_path', XMLDB_TYPE_CHAR, '80', null, XMLDB_NOTNULL, null, null, 'function_name');
|
||||
|
||||
/// Launch rename field xmlrpc_path
|
||||
$dbman->rename_field($table, $field, 'xmlrpcpath');
|
||||
|
||||
|
||||
/// Main savepoint reached
|
||||
upgrade_main_savepoint($result, 2010012900);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -318,7 +318,7 @@ class mnet_xmlrpc_client {
|
||||
{mnet_service2rpc} s2r,
|
||||
{mnet_host2service} h2s
|
||||
WHERE
|
||||
r.xmlrpc_path = ? AND
|
||||
r.xmlrpcpath = ? AND
|
||||
s2r.rpcid = r.id AND
|
||||
s2r.serviceid = h2s.serviceid AND
|
||||
h2s.subscribe = '1' AND
|
||||
|
@ -314,7 +314,7 @@ function mnet_server_dispatch($payload) {
|
||||
//////////////////////////////////// NORMAL PLUGIN DISPATCHER
|
||||
} else {
|
||||
// anything else comes from some sort of plugin
|
||||
if ($rpcrecord = $DB->get_record('mnet_rpc', array('xmlrpc_path' => $method))) {
|
||||
if ($rpcrecord = $DB->get_record('mnet_rpc', array('xmlrpcpath' => $method))) {
|
||||
$response = mnet_server_invoke_plugin_method($method, $callstack, $rpcrecord, $payload);
|
||||
$response = mnet_server_prepare_response($response);
|
||||
echo $response;
|
||||
@ -366,8 +366,8 @@ function mnet_system($method, $params, $hostinfo) {
|
||||
if ('system.listMethods' == $method || 'system/listMethods' == $method) {
|
||||
$query = '
|
||||
SELECT DISTINCT
|
||||
rpc.function_name,
|
||||
rpc.xmlrpc_path
|
||||
rpc.functionname,
|
||||
rpc.xmlrpcpath
|
||||
FROM
|
||||
{mnet_host2service} h2s
|
||||
JOIN {mnet_service2rpc} s2r ON h2s.serviceid = s2r.serviceid
|
||||
@ -378,19 +378,19 @@ function mnet_system($method, $params, $hostinfo) {
|
||||
h2s.publish = 1 AND rpc.enabled = 1
|
||||
' . ((count($params) > 0) ? 'AND svc.name = ? ' : '') . '
|
||||
ORDER BY
|
||||
rpc.xmlrpc_path ASC';
|
||||
rpc.xmlrpcpath ASC';
|
||||
if (count($params) > 0) {
|
||||
$params = array($params[0]);
|
||||
}
|
||||
$methods = array();
|
||||
foreach ($DB->get_records_sql($query, $params) as $result) {
|
||||
$methods[] = $result->xmlrpc_path;
|
||||
$methods[] = $result->xmlrpcpath;
|
||||
}
|
||||
return $methods;
|
||||
} elseif (in_array($method, array('system.methodSignature', 'system/methodSignature', 'system.methodHelp', 'system/methodHelp'))) {
|
||||
$query = '
|
||||
SELECT DISTINCT
|
||||
rpc.function_name,
|
||||
rpc.functionname,
|
||||
rpc.help,
|
||||
rpc.profile
|
||||
FROM
|
||||
@ -398,7 +398,7 @@ function mnet_system($method, $params, $hostinfo) {
|
||||
{mnet_service2rpc} s2r,
|
||||
{mnet_rpc} rpc
|
||||
WHERE
|
||||
rpc.xmlrpc_path = ? AND
|
||||
rpc.xmlrpcpath = ? AND
|
||||
s2r.rpcid = rpc.id AND
|
||||
h2s.publish = 1 AND rpc.enabled = 1 AND
|
||||
h2s.serviceid = s2r.serviceid AND
|
||||
@ -605,12 +605,12 @@ function mnet_setup_dummy_method($method, $callstack, $rpcrecord) {
|
||||
} catch (Exception $e) {
|
||||
throw new mnet_server_exception(709, "classerror");
|
||||
}
|
||||
if (!is_callable(array($object, $rpcrecord->function_name))) {
|
||||
if (!is_callable(array($object, $rpcrecord->functionname))) {
|
||||
throw new mnet_server_exception(706, "nosuchfunction");
|
||||
}
|
||||
$MNET_REMOTE_CLIENT->object_to_call($object);
|
||||
} else {
|
||||
if (!is_callable(array($rpcrecord->classname, $rpcrecord->function_name))) {
|
||||
if (!is_callable(array($rpcrecord->classname, $rpcrecord->functionname))) {
|
||||
throw new mnet_server_exception(706, "nosuchfunction");
|
||||
}
|
||||
$MNET_REMOTE_CLIENT->static_location($rpcrecord->classname);
|
||||
|
@ -6,7 +6,7 @@
|
||||
// This is compared against the values stored in the database to determine
|
||||
// whether upgrades should be performed (see lib/db/*.php)
|
||||
|
||||
$version = 2010012600; // YYYYMMDD = date of the last version bump
|
||||
$version = 2010012900; // YYYYMMDD = date of the last version bump
|
||||
// XX = daily increments
|
||||
|
||||
$release = '2.0 dev (Build: 20100128)'; // Human-friendly version name
|
||||
|
Loading…
x
Reference in New Issue
Block a user