Mercurial > libervia-backend
diff frontends/src/jp/jp @ 401:b2caa2615c4c
jp roster name manegement + Pipe transfer
- added experimental pipe transfer protocol (based on xep-0096)
- jp now manage roster name to jid conversion (if an argument correspond to a roster name, it replace it with the corresponding jid)
- jp now add last known resource of when a resource is needed but we have a bare jid (e.g. for file or pipe transfer)
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 07 Oct 2011 00:25:15 +0200 |
parents | 393b35aa86d2 |
children | f03688bdb858 |
line wrap: on
line diff
--- a/frontends/src/jp/jp Thu Oct 06 21:21:53 2011 +0200 +++ b/frontends/src/jp/jp Fri Oct 07 00:25:15 2011 +0200 @@ -56,6 +56,8 @@ import gobject from sat_frontends.bridge.DBus import DBusBridgeFrontend,BridgeExceptionNoService import tarfile +import tempfile +import shutil try: from progressbar import ProgressBar, Percentage, Bar, ETA, FileTransferSpeed except ImportError, e: @@ -105,28 +107,29 @@ help=_("Add a new line at the beginning of the input (usefull for ascii art ;))")) parser.add_option("--connect", action="store_true", default=False, help=_("Connect the profile before doing anything else")) + parser.add_option("--pipe-in", action="store_true", default=False, + help=_("Wait for the reception of a pipe stream")) + parser.add_option("--pipe-out", action="store_true", default=False, + help=_("Pipe a stream out ")) (self.options, args) = parser.parse_args() if len(args) < 1 and not self.options.wait_file: parser.error(_("You must specify the destination JID (Jabber ID)").encode('utf-8')) - if self.options.wait_file: + if self.options.wait_file or self.options.pipe_in: #several jid - self.dest_jids = args + self.dest_jids = [arg.decode('utf-8') for arg in args] else: #one dest_jid, other args are files - self.dest_jid = JID(args[-1]) - if not self.dest_jid.is_valid: - error (_("%s is not a valid JID !"), self.dest_jid) - exit(1) + self.dest_jid = JID(args[-1].decode('utf-8')) self.files = args[:-1] if not pbar_available and self.options.progress: self.options.progress = False error (_("Option progress is not available, deactivated.")) - if self.options.progress or self.options.wait_file or self.options.connect: + if self.options.progress or self.options.wait_file or self.options.connect or self.options.pipe_in: self.start_loop = True #We have to use loop for these options else: self.start_loop = False @@ -155,7 +158,35 @@ self.connected() + def check_jids(self): + """Check jids validity, transform roster name to corresponding jids""" + names2jid = {} + for contact in self.bridge.getContacts(self.options.profile): + _jid, attr, groups = contact + if attr.has_key("name"): + names2jid[attr["name"].lower()] = _jid + + def expandJid(jid): + _jid = jid.lower() + return unicode(names2jid[_jid] if _jid in names2jid else jid) + + def check(jid): + if not jid.is_valid: + error (_("%s is not a valid JID !"), self.dest_jid) + exit(1) + + try: + self.dest_jid = expandJid(self.dest_jid) + check(self.dest_jid) + except AttributeError: + pass + try: + for i in range(len(self.dest_jids)): + self.dest_jids[i] = expandJid(self.dest_jids[i]) + check(self.dest_jids[i]) + except AttributeError: + pass def send_stdin(self): """Send incomming data on stdin to jabber contact""" @@ -172,6 +203,19 @@ else: self.bridge.sendMessage(self.dest_jid, header + "".join(sys.stdin.readlines()), profile_key=self.profile) + + def pipe_out(self): + """Create named pipe, and send stdin to it""" + tmp_dir = tempfile.mkdtemp() + fifopath = os.path.join(tmp_dir,"pipe_out") + os.mkfifo(fifopath) + self.bridge.pipeOut(self._getFullJid(self.dest_jid), fifopath, {}, profile_key=self.profile) + f = open(fifopath, 'w+') + shutil.copyfileobj(sys.stdin, f) + f.close() + shutil.rmtree(tmp_dir) + + def send_files(self): """Send files to jabber contact""" @@ -183,6 +227,7 @@ error (_("[%s] is a dir ! Please send files inside or use compression") % file) exit(1) + full_dest_jid = self._getFullJid(self.dest_jid) if self.options.bz2: tmpfile = (basename(self.files[0]) or basename(dirname(self.files[0])) ) + '.tar.bz2' #FIXME: tmp, need an algorithm to find a good name/path if os.path.exists(tmpfile): @@ -199,19 +244,31 @@ bz2.close() info(_("OK !")) path = abspath(tmpfile) - self.transfer_id = self.bridge.sendFile(self.dest_jid, path, {}, profile_key=self.profile) + self.transfer_id = self.bridge.sendFile(full_dest_jid, path, {}, profile_key=self.profile) else: for file in self.files: path = abspath(file) - self.transfer_id = self.bridge.sendFile(self.dest_jid, path, {}, profile_key=self.profile) #FIXME: show progress only for last transfer_id + self.transfer_id = self.bridge.sendFile(full_dest_jid, path, {}, profile_key=self.profile) #FIXME: show progress only for last transfer_id + - #TODO: manage ProgressBar + def _getFullJid(self, param_jid): + """Return the full jid if possible (add last resource when find a bare jid""" + _jid = JID(param_jid) + if not _jid.resource: + #if the resource is not given, we try to add the last known resource + last_resource = self.bridge.getLastResource(param_jid, self.options.profile) + if last_resource: + return "%s/%s" % (_jid.short, last_resource) + return param_jid + def askConfirmation(self, type, id, data): """CB used for file transfer, accept files depending on parameters""" answer_data={} if type == "FILE_TRANSFER": - if self.dest_jids and not data['from'] in self.dest_jids: + if not self.options.wait_file: + return + if self.dest_jids and not JID(data['from']).short in [JID(_jid).short for _jid in self.dest_jids]: return #file is not sent by a filtered jid answer_data["dest_path"] = os.getcwd()+'/'+data['filename'] @@ -228,13 +285,30 @@ if not self.options.multiple and not self.options.progress: #we just accept one file self.loop.quit() + elif type == "PIPE_TRANSFER": + if not self.options.pipe_in: + return + if self.dest_jids and not JID(data['from']).short in [JID(_jid).short for _jid in self.dest_jids]: + return #pipe stream is not sent by a filtered jid + + tmp_dir = tempfile.mkdtemp() + fifopath = os.path.join(tmp_dir,"pipe_in") + answer_data["dest_path"] = fifopath + os.mkfifo(fifopath) + self.bridge.confirmationAnswer(id, True, answer_data) + f = open(fifopath, 'r') + shutil.copyfileobj(f, sys.stdout) + f.close() + shutil.rmtree(tmp_dir) + self.loop.quit() + def actionResult(self, type, id, data): #FIXME info (_("FIXME: actionResult not implemented")) - def wait_file(self): - """Wait for a file and write it on local dir""" + def confirmation_reply(self): + """Auto reply to confirmations requests""" self.bridge.register("askConfirmation", self.askConfirmation) def progressCB(self): @@ -269,19 +343,22 @@ def connected(self): """This is called when the profile is connected""" - if self.options.wait_file: - self.wait_file() + self.check_jids() + if self.options.wait_file or self.options.pipe_in: + self.confirmation_reply() else: - if not self.files: #we send message only if there are no files to send + if self.files: + self.send_files() + elif self.options.pipe_out: + self.pipe_out() + else: self.send_stdin() - else: - self.send_files() if self.options.progress: self.pbar = None gobject.timeout_add(10, self.progressCB) - if not self.options.progress and not self.options.wait_file: + if self.start_loop and not self.options.progress and not self.options.wait_file and not self.options.pipe_in: self.loop.quit()