Backend: SQL LIKE command added

This commit is contained in:
Sepalani 2016-07-21 11:26:46 +04:00
parent 89495cabc1
commit 341293dade
3 changed files with 82 additions and 6 deletions

View File

@ -49,6 +49,7 @@
<Compile Include="gamespy\gs_utility.py" />
<Compile Include="gamespy\__init__.py" />
<Compile Include="other\dlc.py" />
<Compile Include="other\sql.py" />
<Compile Include="other\utils.py" />
<Compile Include="other\__init__.py" />
<Compile Include="tools\import_wiimm_data.py" />

View File

@ -53,6 +53,7 @@ import ast
from multiprocessing.managers import BaseManager
from multiprocessing import freeze_support
from other.sql import sql_commands, LIKE
import other.utils as utils
import dwc_config
@ -142,6 +143,12 @@ class GameSpyBackendServer(object):
numplayers < 11 and dwc_mtype = 0 and dwc_hoststate = 2 and
dwc_suspend = 0 and (rk = 'vs_123' and (ev > 4263 or ev <= 5763)
and p = 0)
Example with LIKE from Fortune Street:
dwc_mver = 90 and dwc_pid != 15 and maxplayers = 3 and
numplayers < 3 and dwc_mtype = 0 and dwc_suspend = 0 and
dwc_hoststate = 2 and ((zvar LIKE '102') AND (zmtp LIKE 'EU') AND
(zrule LIKE '1') AND (zpnum LIKE '2') AND (zaddc LIKE '0') AND rel='1')
"""
i = 0
start = i
@ -249,14 +256,19 @@ class GameSpyBackendServer(object):
token = "=="
elif token_type == TokenType.FIELD:
# Each server has its own variables so handle it later.
variables.append(len(output))
if token.upper() in sql_commands:
# Convert "A SQL_COMMAND B" into "A |SQL_COMMAND| B"
output.extend(["|", token.upper(), "|"])
continue
else:
# Each server has its own variables so handle it later.
variables.append(len(output))
output.append(token)
return output, variables
def validate_ast(self, node, num_literal_only):
def validate_ast(self, node, num_literal_only, is_sql=False):
# This function tries to verify that the expression is a valid
# expression before it gets evaluated.
# Anything besides the whitelisted things below are strictly
@ -278,7 +290,7 @@ class GameSpyBackendServer(object):
valid_node = True
elif isinstance(node, ast.Str):
if not num_literal_only:
if is_sql or not num_literal_only:
valid_node = True
elif isinstance(node, ast.BoolOp):
@ -289,10 +301,16 @@ class GameSpyBackendServer(object):
break
elif isinstance(node, ast.BinOp):
valid_node = self.validate_ast(node.left, True)
# Allow SQL_COMMAND infix operator with more types
is_sql |= \
hasattr(node, "left") and \
hasattr(node.left, "right") and \
isinstance(node.left.right, ast.Name) and \
node.left.right.id in sql_commands
valid_node = self.validate_ast(node.left, True, is_sql)
if valid_node:
valid_node = self.validate_ast(node.right, True)
valid_node = self.validate_ast(node.right, True, is_sql)
elif isinstance(node, ast.UnaryOp):
valid_node = self.validate_ast(node.operand, num_literal_only)
@ -322,6 +340,9 @@ class GameSpyBackendServer(object):
elif isinstance(node, ast.Call):
valid_node = False
elif isinstance(node, ast.Name):
valid_node = node.id in sql_commands
return valid_node
def find_servers(self, gameid, filters, fields, max_count):

54
other/sql.py Normal file
View File

@ -0,0 +1,54 @@
"""DWC Network Server Emulator
Copyright (C) 2016 Sepalani
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/>.
"""
class Infix(object):
"""Infix operator class.
A |Infix| B
"""
def __init__(self, function):
self.function = function
def __ror__(self, other):
return Infix(lambda x, self=self: self.function(other, x))
def __or__(self, other):
return self.function(other)
def sql_like(a, b):
"""SQL LIKE command.
TODO:
- Handle % character
- Handle _ character
- Handle escape character
- Handle []
- Handle [^]
"""
a = str(a).lower()
b = str(b).lower()
return a == b
LIKE = Infix(sql_like)
sql_commands = {
"LIKE": LIKE
}