annotate sat_frontends/jp/cmd_message.py @ 2646:712cb4ff3e13

core: new EncryptionHandler class which manage encrypted session as a core feature: Plugin handling encryption can now register using host.registerEncryptionPlugin, and an encryption session can now be started using messageEncryptionStart bridge method. This will make encryption handling more easy, as we now know if a session is clear or e2e encrypted, and which plugin handle it.
author Goffi <goffi@goffi.org>
date Sun, 29 Jul 2018 19:22:56 +0200
parents 56f94936df1e
children 32b5f68a23b4
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1960
3e168cde7a7d jp: fixed shebang python call
Goffi <goffi@goffi.org>
parents: 1864
diff changeset
1 #!/usr/bin/env python2
815
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
2 # -*- coding: utf-8 -*-
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
3
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
4 # jp: a SAT command line tool
2483
0046283a285d dates update
Goffi <goffi@goffi.org>
parents: 2414
diff changeset
5 # Copyright (C) 2009-2018 Jérôme Poisson (goffi@goffi.org)
815
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
6
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
7 # This program is free software: you can redistribute it and/or modify
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
8 # it under the terms of the GNU Affero General Public License as published by
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
9 # the Free Software Foundation, either version 3 of the License, or
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
10 # (at your option) any later version.
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
11
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
12 # This program is distributed in the hope that it will be useful,
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
15 # GNU Affero General Public License for more details.
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
16
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
17 # You should have received a copy of the GNU Affero General Public License
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
f8d534ed1d1e jp: added missing license headers
Goffi <goffi@goffi.org>
parents: 814
diff changeset
19
817
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
20 from sat_frontends.jp import base
814
59c7bc51c323 jp: refactoring using ArgParse
Dal <kedals0@gmail.com>
parents: 811
diff changeset
21 import sys
771
bfabeedbf32e core: i18n refactoring:
Goffi <goffi@goffi.org>
parents: 721
diff changeset
22 from sat.core.i18n import _
1963
a2bc5089c2eb backend, frontends: message refactoring (huge commit):
Goffi <goffi@goffi.org>
parents: 1960
diff changeset
23 from sat.core.constants import Const as C
817
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
24 from sat.tools.utils import clean_ustr
0
goffi@necton2
parents:
diff changeset
25
817
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
26 __commands__ = ["Message"]
393
393b35aa86d2 jp: added --connect option
Goffi <goffi@goffi.org>
parents: 391
diff changeset
27
587
952322b1d490 Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 572
diff changeset
28
1828
cb4be663a4a7 jp (message): message is now a subcommand, and the sending command is moved to message/send
Goffi <goffi@goffi.org>
parents: 1766
diff changeset
29 class Send(base.CommandBase):
817
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
30 def __init__(self, host):
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
31 super(Send, self).__init__(host, "send", help=_("send a message to a contact"))
817
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
32
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
33 def add_parser_options(self):
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
34 self.parser.add_argument(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
35 "-l", "--lang", type=str, default="", help=_(u"language of the message")
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
36 )
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
37 self.parser.add_argument(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
38 "-s",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
39 "--separate",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
40 action="store_true",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
41 help=_(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
42 u"separate xmpp messages: send one message per line instead of one message alone."
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
43 ),
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
44 )
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
45 self.parser.add_argument(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
46 "-n",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
47 "--new-line",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
48 action="store_true",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
49 help=_(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
50 u"add a new line at the beginning of the input (usefull for ascii art ;))"
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
51 ),
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
52 )
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
53 self.parser.add_argument(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
54 "-S",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
55 "--subject",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
56 type=base.unicode_decoder,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
57 help=_(u"subject of the message"),
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
58 )
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
59 self.parser.add_argument(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
60 "-L", "--subject_lang", type=str, default="", help=_(u"language of subject")
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
61 )
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
62 self.parser.add_argument(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
63 "-t",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
64 "--type",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
65 choices=C.MESS_TYPE_STANDARD + (C.MESS_TYPE_AUTO,),
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
66 default=C.MESS_TYPE_AUTO,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
67 help=_("type of the message"),
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
68 )
2081
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
69 syntax = self.parser.add_mutually_exclusive_group()
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
70 syntax.add_argument("-x", "--xhtml", action="store_true", help=_(u"XHTML body"))
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
71 syntax.add_argument("-r", "--rich", action="store_true", help=_(u"rich body"))
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
72 self.parser.add_argument(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
73 "jid", type=base.unicode_decoder, help=_(u"the destination jid")
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
74 )
401
b2caa2615c4c jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents: 393
diff changeset
75
1864
96ba685162f6 jp: all commands now use the new start method and set need_loop in __init__ when needed
Goffi <goffi@goffi.org>
parents: 1828
diff changeset
76 def start(self):
2081
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
77 if self.args.xhtml and self.args.separate:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
78 self.disp(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
79 u"argument -s/--separate is not compatible yet with argument -x/--xhtml",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
80 error=True,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
81 )
2081
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
82 self.host.quit(2)
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
83
817
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
84 jids = self.host.check_jids([self.args.jid])
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
85 jid = jids[0]
1828
cb4be663a4a7 jp (message): message is now a subcommand, and the sending command is moved to message/send
Goffi <goffi@goffi.org>
parents: 1766
diff changeset
86 self.sendStdin(jid)
817
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
87
1828
cb4be663a4a7 jp (message): message is now a subcommand, and the sending command is moved to message/send
Goffi <goffi@goffi.org>
parents: 1766
diff changeset
88 def sendStdin(self, dest_jid):
817
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
89 """Send incomming data on stdin to jabber contact
1828
cb4be663a4a7 jp (message): message is now a subcommand, and the sending command is moved to message/send
Goffi <goffi@goffi.org>
parents: 1766
diff changeset
90
cb4be663a4a7 jp (message): message is now a subcommand, and the sending command is moved to message/send
Goffi <goffi@goffi.org>
parents: 1766
diff changeset
91 @param dest_jid: destination jid
cb4be663a4a7 jp (message): message is now a subcommand, and the sending command is moved to message/send
Goffi <goffi@goffi.org>
parents: 1766
diff changeset
92 """
817
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
93 header = "\n" if self.args.new_line else ""
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
94 stdin_lines = [
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
95 stream.decode("utf-8", "ignore") for stream in sys.stdin.readlines()
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
96 ]
2081
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
97 extra = {}
1963
a2bc5089c2eb backend, frontends: message refactoring (huge commit):
Goffi <goffi@goffi.org>
parents: 1960
diff changeset
98 if self.args.subject is None:
a2bc5089c2eb backend, frontends: message refactoring (huge commit):
Goffi <goffi@goffi.org>
parents: 1960
diff changeset
99 subject = {}
a2bc5089c2eb backend, frontends: message refactoring (huge commit):
Goffi <goffi@goffi.org>
parents: 1960
diff changeset
100 else:
a2bc5089c2eb backend, frontends: message refactoring (huge commit):
Goffi <goffi@goffi.org>
parents: 1960
diff changeset
101 subject = {self.args.subject_lang: self.args.subject}
817
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
102
2081
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
103 if self.args.xhtml or self.args.rich:
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
104 key = u"xhtml" if self.args.xhtml else u"rich"
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
105 if self.args.lang:
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
106 key = u"{}_{}".format(key, self.args.lang)
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
107 extra[key] = clean_ustr(u"".join(stdin_lines))
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
108 stdin_lines = []
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
109
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
110 if self.args.separate: # we send stdin in several messages
0
goffi@necton2
parents:
diff changeset
111 if header:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
112 self.host.bridge.messageSend(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
113 dest_jid,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
114 {self.args.lang: header},
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
115 subject,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
116 self.args.type,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
117 profile_key=self.profile,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
118 callback=lambda: None,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
119 errback=lambda ignore: ignore,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
120 )
817
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
121
2081
2265d9df4cfb jp (message/send): message/send can now send XHTML (-x) or rich (-r) messages
Goffi <goffi@goffi.org>
parents: 1963
diff changeset
122 for line in stdin_lines:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
123 self.host.bridge.messageSend(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
124 dest_jid,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
125 {self.args.lang: line.replace("\n", "")},
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
126 subject,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
127 self.args.type,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
128 extra,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
129 profile_key=self.host.profile,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
130 callback=lambda: None,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
131 errback=lambda ignore: ignore,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
132 )
0
goffi@necton2
parents:
diff changeset
133
817
c39117d00f35 jp: refactoring:
Goffi <goffi@goffi.org>
parents: 815
diff changeset
134 else:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
135 msg = (
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
136 {self.args.lang: header + clean_ustr(u"".join(stdin_lines))}
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
137 if not (self.args.xhtml or self.args.rich)
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
138 else {}
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
139 )
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
140 self.host.bridge.messageSend(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
141 dest_jid,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
142 msg,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
143 subject,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
144 self.args.type,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
145 extra,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
146 profile_key=self.host.profile,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
147 callback=lambda: None,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
148 errback=lambda ignore: ignore,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
149 )
1828
cb4be663a4a7 jp (message): message is now a subcommand, and the sending command is moved to message/send
Goffi <goffi@goffi.org>
parents: 1766
diff changeset
150
cb4be663a4a7 jp (message): message is now a subcommand, and the sending command is moved to message/send
Goffi <goffi@goffi.org>
parents: 1766
diff changeset
151
cb4be663a4a7 jp (message): message is now a subcommand, and the sending command is moved to message/send
Goffi <goffi@goffi.org>
parents: 1766
diff changeset
152 class Message(base.CommandBase):
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
153 subcommands = (Send,)
1828
cb4be663a4a7 jp (message): message is now a subcommand, and the sending command is moved to message/send
Goffi <goffi@goffi.org>
parents: 1766
diff changeset
154
cb4be663a4a7 jp (message): message is now a subcommand, and the sending command is moved to message/send
Goffi <goffi@goffi.org>
parents: 1766
diff changeset
155 def __init__(self, host):
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
156 super(Message, self).__init__(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
157 host, "message", use_profile=False, help=_("messages handling")
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
158 )