comparison sat_frontends/jp/cmd_message.py @ 2740:8fd8ce5a5855

jp (message/send, encryption): encryption handling: - encryption algorithm can now be requested when sending a message (using --encrypt option) - new encryption commands to (de)activate encryption session, check available algorithms, or manage trust.
author Goffi <goffi@goffi.org>
date Wed, 02 Jan 2019 18:50:57 +0100
parents 45189c8bd165
children 92af49cde255
comparison
equal deleted inserted replaced
2739:e8dc00f612fb 2740:8fd8ce5a5855
31 31
32 32
33 class Send(base.CommandBase): 33 class Send(base.CommandBase):
34 def __init__(self, host): 34 def __init__(self, host):
35 super(Send, self).__init__(host, "send", help=_("send a message to a contact")) 35 super(Send, self).__init__(host, "send", help=_("send a message to a contact"))
36 self.need_loop=True
36 37
37 def add_parser_options(self): 38 def add_parser_options(self):
38 self.parser.add_argument( 39 self.parser.add_argument(
39 "-l", "--lang", type=str, default="", help=_(u"language of the message") 40 "-l", "--lang", type=str, default="", help=_(u"language of the message")
40 ) 41 )
69 "--type", 70 "--type",
70 choices=C.MESS_TYPE_STANDARD + (C.MESS_TYPE_AUTO,), 71 choices=C.MESS_TYPE_STANDARD + (C.MESS_TYPE_AUTO,),
71 default=C.MESS_TYPE_AUTO, 72 default=C.MESS_TYPE_AUTO,
72 help=_("type of the message"), 73 help=_("type of the message"),
73 ) 74 )
75 self.parser.add_argument("-e", "--encrypt", metavar="ALGORITHM",
76 help=_(u"encrypt message using given algorithm"))
77 self.parser.add_argument(
78 "--encrypt-noreplace",
79 action="store_true",
80 help=_(u"don't replace encryption algorithm if an other one is already used"))
74 syntax = self.parser.add_mutually_exclusive_group() 81 syntax = self.parser.add_mutually_exclusive_group()
75 syntax.add_argument("-x", "--xhtml", action="store_true", help=_(u"XHTML body")) 82 syntax.add_argument("-x", "--xhtml", action="store_true", help=_(u"XHTML body"))
76 syntax.add_argument("-r", "--rich", action="store_true", help=_(u"rich body")) 83 syntax.add_argument("-r", "--rich", action="store_true", help=_(u"rich body"))
77 self.parser.add_argument( 84 self.parser.add_argument(
78 "jid", type=base.unicode_decoder, help=_(u"the destination jid") 85 "jid", type=base.unicode_decoder, help=_(u"the destination jid")
79 ) 86 )
80 87
81 def start(self): 88 def multi_send_cb(self):
82 if self.args.xhtml and self.args.separate: 89 self.sent += 1
83 self.disp( 90 if self.sent == self.to_send:
84 u"argument -s/--separate is not compatible yet with argument -x/--xhtml", 91 self.host.quit(self.errcode)
85 error=True, 92
86 ) 93 def multi_send_eb(self, failure_, msg):
87 self.host.quit(2) 94 self.disp(_(u"Can't send message [{msg}]: {reason}").format(
88 95 msg=msg, reason=failure_))
89 jids = self.host.check_jids([self.args.jid]) 96 self.errcode = C.EXIT_BRIDGE_ERRBACK
90 jid = jids[0] 97 self.multi_send_cb()
91 self.sendStdin(jid)
92 98
93 def sendStdin(self, dest_jid): 99 def sendStdin(self, dest_jid):
94 """Send incomming data on stdin to jabber contact 100 """Send incomming data on stdin to jabber contact
95 101
96 @param dest_jid: destination jid 102 @param dest_jid: destination jid
111 key = u"{}_{}".format(key, self.args.lang) 117 key = u"{}_{}".format(key, self.args.lang)
112 extra[key] = clean_ustr(u"".join(stdin_lines)) 118 extra[key] = clean_ustr(u"".join(stdin_lines))
113 stdin_lines = [] 119 stdin_lines = []
114 120
115 if self.args.separate: # we send stdin in several messages 121 if self.args.separate: # we send stdin in several messages
122 self.to_send = 0
123 self.sent = 0
124 self.errcode = 0
125
116 if header: 126 if header:
127 self.to_send += 1
117 self.host.bridge.messageSend( 128 self.host.bridge.messageSend(
118 dest_jid, 129 dest_jid,
119 {self.args.lang: header}, 130 {self.args.lang: header},
120 subject, 131 subject,
121 self.args.type, 132 self.args.type,
122 profile_key=self.profile, 133 profile_key=self.profile,
123 callback=lambda: None, 134 callback=lambda: None,
124 errback=lambda ignore: ignore, 135 errback=lambda ignore: ignore,
125 ) 136 )
126 137
138 self.to_send += len(stdin_lines)
127 for line in stdin_lines: 139 for line in stdin_lines:
128 self.host.bridge.messageSend( 140 self.host.bridge.messageSend(
129 dest_jid, 141 dest_jid,
130 {self.args.lang: line.replace("\n", "")}, 142 {self.args.lang: line.replace("\n", "")},
131 subject, 143 subject,
132 self.args.type, 144 self.args.type,
133 extra, 145 extra,
134 profile_key=self.host.profile, 146 profile_key=self.host.profile,
135 callback=lambda: None, 147 callback=self.multi_send_cb,
136 errback=lambda ignore: ignore, 148 errback=partial(self.multi_send_eb, msg=line),
137 ) 149 )
138 150
139 else: 151 else:
140 msg = ( 152 msg = (
141 {self.args.lang: header + clean_ustr(u"".join(stdin_lines))} 153 {self.args.lang: header + clean_ustr(u"".join(stdin_lines))}
147 msg, 159 msg,
148 subject, 160 subject,
149 self.args.type, 161 self.args.type,
150 extra, 162 extra,
151 profile_key=self.host.profile, 163 profile_key=self.host.profile,
152 callback=lambda: None, 164 callback=self.host.quit,
153 errback=lambda ignore: ignore, 165 errback=partial(self.errback,
166 msg=_(u"Can't send message: {}")))
167
168 def encryptionNamespaceGetCb(self, namespace, jid_):
169 self.host.bridge.messageEncryptionStart(
170 jid_, namespace, not self.args.encrypt_noreplace,
171 self.profile,
172 callback=lambda: self.sendStdin(jid_),
173 errback=partial(self.errback,
174 msg=_(u"Can't start encryption session: {}"),
175 exit_code=C.EXIT_BRIDGE_ERRBACK,
176 ))
177
178
179 def start(self):
180 if self.args.xhtml and self.args.separate:
181 self.disp(
182 u"argument -s/--separate is not compatible yet with argument -x/--xhtml",
183 error=True,
154 ) 184 )
185 self.host.quit(2)
186
187 jids = self.host.check_jids([self.args.jid])
188 jid_ = jids[0]
189
190 if self.args.encrypt_noreplace and self.args.encrypt is None:
191 self.parser.error("You need to use --encrypt if you use --encrypt-noreplace")
192
193 if self.args.encrypt is not None:
194 self.host.bridge.encryptionNamespaceGet(self.args.encrypt,
195 callback=partial(self.encryptionNamespaceGetCb, jid_=jid_),
196 errback=partial(self.errback,
197 msg=_(u"Can't get encryption namespace: {}"),
198 exit_code=C.EXIT_BRIDGE_ERRBACK,
199 ))
200 else:
201 self.sendStdin(jid_)
155 202
156 203
157 class MAM(base.CommandBase): 204 class MAM(base.CommandBase):
158 205
159 def __init__(self, host): 206 def __init__(self, host):
214 self.host.bridge.MAMGet( 261 self.host.bridge.MAMGet(
215 self.args.service, data_format.serialise(extra), self.profile, 262 self.args.service, data_format.serialise(extra), self.profile,
216 callback=self._MAMGetCb, errback=self.errback) 263 callback=self._MAMGetCb, errback=self.errback)
217 264
218 265
219 class EncryptionAlgorithms(base.CommandBase):
220
221 def __init__(self, host):
222 extra_outputs = {"default": self.default_output}
223 super(EncryptionAlgorithms, self).__init__(
224 host, "algorithms",
225 use_output=C.OUTPUT_LIST_DICT,
226 extra_outputs=extra_outputs,
227 use_profile=False,
228 help=_("show available encryption algorithms"))
229 self.need_loop = True
230
231 def add_parser_options(self):
232 pass
233
234 def encryptionPluginsGetCb(self, plugins):
235 self.output(plugins)
236 self.host.quit()
237
238 def default_output(self, plugins):
239 if not plugins:
240 self.disp(_(u"No encryption plugin registered!"))
241 self.host.quit(C.EXIT_NOT_FOUND)
242 else:
243 self.disp(_(u"Following encryption algorithms are available: {algos}").format(
244 algos=', '.join([p['name'] for p in plugins])))
245 self.host.quit()
246
247 def start(self):
248 self.host.bridge.encryptionPluginsGet(
249 callback=self.encryptionPluginsGetCb,
250 errback=partial(
251 self.errback,
252 msg=_(u"can't retrieve plugins: {}"),
253 exit_code=C.EXIT_BRIDGE_ERRBACK,
254 ),
255 )
256
257
258 class Encryption(base.CommandBase):
259 subcommands = (EncryptionAlgorithms,)
260
261 def __init__(self, host):
262 super(Encryption, self).__init__(
263 host, "encryption", use_profile=False, help=_("encryption sessions handling")
264 )
265
266
267 class Message(base.CommandBase): 266 class Message(base.CommandBase):
268 subcommands = (Send, MAM, Encryption) 267 subcommands = (Send, MAM)
269 268
270 def __init__(self, host): 269 def __init__(self, host):
271 super(Message, self).__init__( 270 super(Message, self).__init__(
272 host, "message", use_profile=False, help=_("messages handling") 271 host, "message", use_profile=False, help=_("messages handling")
273 ) 272 )