annotate libervia/backend/plugins/plugin_xep_0080.py @ 4094:c3b68fdc2de7

component AP gateway: fix handling of XMPP comments authors: the gateway was supposing that comments where emitted from PEP of author. While this is the case for most blog posts, it's not for comments. Instead the component is now using `author_jid` which is retrieved by XEP-0277 plugin, and reject the item if the auhor is not verified (i.e. if `publisher` attribute is not set by XMPP service).
author Goffi <goffi@goffi.org>
date Mon, 12 Jun 2023 14:50:43 +0200
parents 4b842c1fb686
children 0d7bb4df2343
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3894
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/env python3
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
2
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
3 # Copyright (C) 2009-2022 Jérôme Poisson (goffi@goffi.org)
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
4
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
5 # This program is free software: you can redistribute it and/or modify
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
6 # it under the terms of the GNU Affero General Public License as published by
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # the Free Software Foundation, either version 3 of the License, or
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # (at your option) any later version.
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
9
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
10 # This program is distributed in the hope that it will be useful,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # GNU Affero General Public License for more details.
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
14
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
15 # You should have received a copy of the GNU Affero General Public License
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
17
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
18 from typing import Dict, Any
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
19
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
20 from twisted.words.xish import domish
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
21
4071
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
22 from libervia.backend.core.constants import Const as C
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
23 from libervia.backend.core.i18n import _
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
24 from libervia.backend.core.log import getLogger
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
25 from libervia.backend.core import exceptions
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
26 from libervia.backend.tools import utils
3894
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
27
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
28 log = getLogger(__name__)
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
29
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
30
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
31 PLUGIN_INFO = {
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 C.PI_NAME: "User Location",
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 C.PI_IMPORT_NAME: "XEP-0080",
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
34 C.PI_TYPE: "XEP",
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 C.PI_MODES: C.PLUG_MODE_BOTH,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
36 C.PI_PROTOCOLS: ["XEP-0080"],
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
37 C.PI_MAIN: "XEP_0080",
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
38 C.PI_HANDLER: "no",
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
39 C.PI_DESCRIPTION: _("""Implementation of XEP-0080 (User Location)"""),
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
40 }
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
41
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
42 NS_GEOLOC = "http://jabber.org/protocol/geoloc"
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
43 KEYS_TYPES = {
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
44 "accuracy": float,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
45 "alt": float,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
46 "altaccuracy": float,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 "area": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
48 "bearing": float,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 "building": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
50 "country": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
51 "countrycode": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
52 "datum": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
53 "description": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
54 "error": float,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
55 "floor": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
56 "lat": float,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
57 "locality": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
58 "lon": float,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
59 "postalcode": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
60 "region": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
61 "room": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
62 "speed": float,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
63 "street": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
64 "text": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
65 "timestamp": "datetime",
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
66 "tzo": str,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
67 "uri": str
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
68 }
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
69
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
70
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
71 class XEP_0080:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
72
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
73 def __init__(self, host):
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
74 log.info(_("XEP-0080 (User Location) plugin initialization"))
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 3894
diff changeset
75 host.register_namespace("geoloc", NS_GEOLOC)
3894
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
76
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
77 def get_geoloc_elt(
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
78 self,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
79 location_data: Dict[str, Any],
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
80 ) -> domish.Element:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
81 """Generate the element describing the location
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
82
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
83 @param geoloc: metadata description the location
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
84 Keys correspond to ones found at
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
85 https://xmpp.org/extensions/xep-0080.html#format, with following additional
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
86 keys:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
87 - id (str): Identifier for this location
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
88 - language (str): language of the human readable texts
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
89 All keys are optional.
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
90 @return: ``<geoloc/>`` element
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
91 """
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
92 geoloc_elt = domish.Element((NS_GEOLOC, "geoloc"))
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
93 for key, value in location_data.items():
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
94 try:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
95 key_type = KEYS_TYPES[key]
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
96 except KeyError:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
97 if key == "id":
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
98 # "id" attribute is not specified for XEP-0080's <geoloc/> element,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
99 # but it may be used in a parent element (that's the case for events)
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
100 pass
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
101 elif key == "language":
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
102 geoloc_elt["xml:lang"] = value
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
103 else:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
104 log.warning(f"Unknown location key {key}: {location_data}")
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
105 continue
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
106 if key_type == "datetime":
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
107 content = utils.xmpp_date(value)
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
108 else:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
109 content = str(value)
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
110 geoloc_elt.addElement(key, content=content)
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
111
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
112 return geoloc_elt
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
113
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
114 def parse_geoloc_elt(
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
115 self,
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
116 geoloc_elt: domish.Element
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
117 ) -> Dict[str, Any]:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
118 """Parse <geoloc/> element
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
119
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
120 @param geoloc_elt: <geoloc/> element
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
121 a parent element can also be used
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
122 @return: geoloc data. It's a dict whose keys correspond to
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
123 [get_geoloc_elt] parameters
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
124 @raise exceptions.NotFound: no <geoloc/> element has been found
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
125 """
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
126
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
127 if geoloc_elt.name != "geoloc":
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
128 try:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
129 geoloc_elt = next(geoloc_elt.elements(NS_GEOLOC, "geoloc"))
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
130 except StopIteration:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
131 raise exceptions.NotFound
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
132 data: Dict[str, Any] = {}
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
133 for elt in geoloc_elt.elements():
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
134 if elt.uri != NS_GEOLOC:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
135 log.warning(f"unmanaged geoloc element: {elt.toXml()}")
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
136 continue
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
137 try:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
138 data_type = KEYS_TYPES[elt.name]
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
139 except KeyError:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
140 log.warning(f"unknown geoloc element: {elt.toXml()}")
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
141 continue
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
142 try:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
143 if data_type == "datetime":
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
144 data[elt.name] = utils.parse_xmpp_date(str(elt))
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
145 else:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
146 data[elt.name] = data_type(str(elt))
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
147 except Exception as e:
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
148 log.warning(f"can't parse element: {elt.toXml()}")
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
149 continue
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
150
ed470361ea2e plugin XEP-0080: User Location implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
151 return data