浏览代码

[fix] A percentage in file name caused 404 error in case of private file while checking permissions

version-14
Anand Doshi 9 年前
父节点
当前提交
5572f24c5d
共有 5 个文件被更改,包括 28 次插入19 次删除
  1. +2
    -2
      frappe/core/doctype/error_snapshot/error_snapshot.json
  2. +13
    -2
      frappe/database.py
  3. +2
    -2
      frappe/desk/reportview.py
  4. +9
    -11
      frappe/model/db_query.py
  5. +2
    -2
      frappe/utils/error.py

+ 2
- 2
frappe/core/doctype/error_snapshot/error_snapshot.json 查看文件

@@ -61,7 +61,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"fieldname": "evalue", "fieldname": "evalue",
"fieldtype": "Data",
"fieldtype": "Small Text",
"hidden": 1, "hidden": 1,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"in_filter": 0, "in_filter": 0,
@@ -308,7 +308,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2015-12-16 09:03:57.521251",
"modified": "2015-12-21 05:07:12.840575",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Core", "module": "Core",
"name": "Error Snapshot", "name": "Error Snapshot",


+ 13
- 2
frappe/database.py 查看文件

@@ -784,8 +784,19 @@ class Database:
self._cursor = None self._cursor = None
self._conn = None self._conn = None


def escape(self, s):
def escape(self, s, percent=True):
"""Excape quotes and percent in given string.""" """Excape quotes and percent in given string."""
if isinstance(s, unicode): if isinstance(s, unicode):
s = (s or "").encode("utf-8") s = (s or "").encode("utf-8")
return unicode(MySQLdb.escape_string(s), "utf-8").replace("%","%%").replace("`", "\\`")

s = unicode(MySQLdb.escape_string(s), "utf-8").replace("`", "\\`")

# NOTE separating % escape, because % escape should only be done when using LIKE operator
# or when you use python format string to generate query that already has a %s
# for example: sql("select name from `tabUser` where name=%s and {0}".format(conditions), something)
# defaulting it to True, as this is the most frequent use case
# ideally we shouldn't have to use ESCAPE and strive to pass values via the values argument of sql
if percent:
s = s.replace("%", "%%")

return s

+ 2
- 2
frappe/desk/reportview.py 查看文件

@@ -177,7 +177,7 @@ def scrub_user_tags(tagcount):
# used in building query in queries.py # used in building query in queries.py
def get_match_cond(doctype): def get_match_cond(doctype):
cond = DatabaseQuery(doctype).build_match_conditions() cond = DatabaseQuery(doctype).build_match_conditions()
return (' and ' + cond) if cond else ""
return ((' and ' + cond) if cond else "").replace("%", "%%")


def build_match_conditions(doctype, as_condition=True): def build_match_conditions(doctype, as_condition=True):
return DatabaseQuery(doctype).build_match_conditions(as_condition=as_condition)
return (DatabaseQuery(doctype).build_match_conditions(as_condition=as_condition)).replace("%", "%%")

+ 9
- 11
frappe/model/db_query.py 查看文件

@@ -226,7 +226,7 @@ class DatabaseQuery(object):
if not isinstance(values, (list, tuple)): if not isinstance(values, (list, tuple)):
values = values.split(",") values = values.split(",")


values = (frappe.db.escape(v.strip()) for v in values)
values = (frappe.db.escape(v.strip(), percent=False) for v in values)
values = '("{0}")'.format('", "'.join(values)) values = '("{0}")'.format('", "'.join(values))


condition = 'ifnull({tname}.{fname}, "") {operator} {value}'.format( condition = 'ifnull({tname}.{fname}, "") {operator} {value}'.format(
@@ -253,9 +253,9 @@ class DatabaseQuery(object):
value = "" if f.value==None else f.value value = "" if f.value==None else f.value
fallback = '""' fallback = '""'


if f.operator == "like" and isinstance(value, basestring):
if f.operator in ("like", "not like") and isinstance(value, basestring):
# because "like" uses backslash (\) for escaping # because "like" uses backslash (\) for escaping
value = value.replace("\\", "\\\\")
value = value.replace("\\", "\\\\").replace("%", "%%")


else: else:
value = flt(f.value) value = flt(f.value)
@@ -263,14 +263,13 @@ class DatabaseQuery(object):


# put it inside double quotes # put it inside double quotes
if isinstance(value, basestring): if isinstance(value, basestring):
value = '"{0}"'.format(frappe.db.escape(value))
value = '"{0}"'.format(frappe.db.escape(value, percent=False))


condition = 'ifnull({tname}.{fname}, {fallback}) {operator} {value}'.format( condition = 'ifnull({tname}.{fname}, {fallback}) {operator} {value}'.format(
tname=tname, fname=f.fieldname, fallback=fallback, operator=f.operator, tname=tname, fname=f.fieldname, fallback=fallback, operator=f.operator,
value=value) value=value)


# replace % with %% to prevent python format string error
return condition.replace("%", "%%")
return condition


def get_filter(self, f): def get_filter(self, f):
"""Returns a _dict like """Returns a _dict like
@@ -341,7 +340,7 @@ class DatabaseQuery(object):


if role_permissions.get("if_owner", {}).get("read"): if role_permissions.get("if_owner", {}).get("read"):
self.match_conditions.append("`tab{0}`.owner = '{1}'".format(self.doctype, self.match_conditions.append("`tab{0}`.owner = '{1}'".format(self.doctype,
frappe.db.escape(frappe.session.user)))
frappe.db.escape(frappe.session.user, percent=False)))


if as_condition: if as_condition:
conditions = "" conditions = ""
@@ -358,15 +357,14 @@ class DatabaseQuery(object):
conditions = "({conditions}) or ({shared_condition})".format( conditions = "({conditions}) or ({shared_condition})".format(
conditions=conditions, shared_condition=self.get_share_condition()) conditions=conditions, shared_condition=self.get_share_condition())


# replace % with %% to prevent python format string error
return conditions.replace("%", "%%")
return conditions


else: else:
return self.match_filters return self.match_filters


def get_share_condition(self): def get_share_condition(self):
return """`tab{0}`.name in ({1})""".format(self.doctype, ", ".join(["'%s'"] * len(self.shared))) % \ return """`tab{0}`.name in ({1})""".format(self.doctype, ", ".join(["'%s'"] * len(self.shared))) % \
tuple([frappe.db.escape(s) for s in self.shared])
tuple([frappe.db.escape(s, percent=False) for s in self.shared])


def add_user_permissions(self, user_permissions, user_permission_doctypes=None): def add_user_permissions(self, user_permissions, user_permission_doctypes=None):
user_permission_doctypes = frappe.permissions.get_user_permission_doctypes(user_permission_doctypes, user_permissions) user_permission_doctypes = frappe.permissions.get_user_permission_doctypes(user_permission_doctypes, user_permissions)
@@ -383,7 +381,7 @@ class DatabaseQuery(object):
if user_permission_values: if user_permission_values:
condition += """ or `tab{doctype}`.`{fieldname}` in ({values})""".format( condition += """ or `tab{doctype}`.`{fieldname}` in ({values})""".format(
doctype=self.doctype, fieldname=df.fieldname, doctype=self.doctype, fieldname=df.fieldname,
values=", ".join([('"'+frappe.db.escape(v)+'"') for v in user_permission_values])
values=", ".join([('"'+frappe.db.escape(v, percent=False)+'"') for v in user_permission_values])
) )
match_conditions.append("({condition})".format(condition=condition)) match_conditions.append("({condition})".format(condition=condition))




+ 2
- 2
frappe/utils/error.py 查看文件

@@ -128,14 +128,14 @@ def get_snapshot(exception, context=10):
value = pydoc.text.repr(getattr(evalue, name)) value = pydoc.text.repr(getattr(evalue, name))


# render multilingual string properly # render multilingual string properly
if type(value)==str and value.startswith("u'"):
if type(value)==str and value.startswith(b"u'"):
value = eval(value) value = eval(value)


s['exception'][name] = encode(value) s['exception'][name] = encode(value)


# add all local values (of last frame) to the snapshot # add all local values (of last frame) to the snapshot
for name, value in locals.items(): for name, value in locals.items():
if type(value)==str and value.startswith("u'"):
if type(value)==str and value.startswith(b"u'"):
value = eval(value) value = eval(value)


s['locals'][name] = pydoc.text.repr(value) s['locals'][name] = pydoc.text.repr(value)


正在加载...
取消
保存