Mercurial > libervia-backend
comparison libervia/backend/plugins/plugin_xep_0329.py @ 4270:0d7bb4df2343
Reformatted code base using black.
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 19 Jun 2024 18:44:57 +0200 |
parents | 4b842c1fb686 |
children |
comparison
equal
deleted
inserted
replaced
4269:64a85ce8be70 | 4270:0d7bb4df2343 |
---|---|
207 @raise NotFound: path lead to a non existing file/directory | 207 @raise NotFound: path lead to a non existing file/directory |
208 """ | 208 """ |
209 path_elts = [_f for _f in path.split("/") if _f] | 209 path_elts = [_f for _f in path.split("/") if _f] |
210 | 210 |
211 if ".." in path_elts: | 211 if ".." in path_elts: |
212 log.warning(_( | 212 log.warning( |
213 'parent dir ("..") found in path, hack attempt? path is {path} ' | 213 _( |
214 '[{profile}]').format(path=path, profile=client.profile)) | 214 'parent dir ("..") found in path, hack attempt? path is {path} ' |
215 "[{profile}]" | |
216 ).format(path=path, profile=client.profile) | |
217 ) | |
215 raise exceptions.PermissionError("illegal path elements") | 218 raise exceptions.PermissionError("illegal path elements") |
216 | 219 |
217 node = client._XEP_0329_root_node | 220 node = client._XEP_0329_root_node |
218 | 221 |
219 while path_elts: | 222 while path_elts: |
345 method=self._create_dir, | 348 method=self._create_dir, |
346 async_=True, | 349 async_=True, |
347 ) | 350 ) |
348 host.bridge.add_signal("fis_shared_path_new", ".plugin", signature="sss") | 351 host.bridge.add_signal("fis_shared_path_new", ".plugin", signature="sss") |
349 host.bridge.add_signal("fis_shared_path_removed", ".plugin", signature="ss") | 352 host.bridge.add_signal("fis_shared_path_removed", ".plugin", signature="ss") |
350 host.trigger.add("XEP-0234_fileSendingRequest", self._file_sending_request_trigger) | 353 host.trigger.add( |
354 "XEP-0234_fileSendingRequest", self._file_sending_request_trigger | |
355 ) | |
351 host.register_namespace("fis", NS_FIS) | 356 host.register_namespace("fis", NS_FIS) |
352 | 357 |
353 def get_handler(self, client): | 358 def get_handler(self, client): |
354 return XEP_0329_handler(self) | 359 return XEP_0329_handler(self) |
355 | 360 |
356 def profile_connected(self, client): | 361 def profile_connected(self, client): |
357 if client.is_component: | 362 if client.is_component: |
358 client._file_sharing_allowed_hosts = self.host.memory.config_get( | 363 client._file_sharing_allowed_hosts = self.host.memory.config_get( |
359 'component file_sharing', | 364 "component file_sharing", "http_upload_allowed_hosts_list" |
360 'http_upload_allowed_hosts_list') or [client.host] | 365 ) or [client.host] |
361 else: | 366 else: |
362 client._XEP_0329_root_node = ShareNode( | 367 client._XEP_0329_root_node = ShareNode( |
363 None, | 368 None, |
364 None, | 369 None, |
365 TYPE_VIRTUAL, | 370 TYPE_VIRTUAL, |
475 name = os.path.basename(path) | 480 name = os.path.basename(path) |
476 if os.path.isfile(path): | 481 if os.path.isfile(path): |
477 size = os.path.getsize(path) | 482 size = os.path.getsize(path) |
478 mime_type = mimetypes.guess_type(path, strict=False)[0] | 483 mime_type = mimetypes.guess_type(path, strict=False)[0] |
479 file_elt = self._jf.build_file_element( | 484 file_elt = self._jf.build_file_element( |
480 client=client, name=name, size=size, mime_type=mime_type, | 485 client=client, |
481 modified=os.path.getmtime(path) | 486 name=name, |
487 size=size, | |
488 mime_type=mime_type, | |
489 modified=os.path.getmtime(path), | |
482 ) | 490 ) |
483 | 491 |
484 query_elt.addChild(file_elt) | 492 query_elt.addChild(file_elt) |
485 # we don't specify hash as it would be too resource intensive to calculate | 493 # we don't specify hash as it would be too resource intensive to calculate |
486 # it for all files. | 494 # it for all files. |
623 ) | 631 ) |
624 except exceptions.NotFound: | 632 except exceptions.NotFound: |
625 self._iq_error(client, iq_elt) | 633 self._iq_error(client, iq_elt) |
626 return | 634 return |
627 except exceptions.PermissionError: | 635 except exceptions.PermissionError: |
628 self._iq_error(client, iq_elt, condition='not-allowed') | 636 self._iq_error(client, iq_elt, condition="not-allowed") |
629 return | 637 return |
630 except Exception as e: | 638 except Exception as e: |
631 tb = traceback.format_tb(e.__traceback__) | 639 tb = traceback.format_tb(e.__traceback__) |
632 log.error(f"internal server error: {e}\n{''.join(tb)}") | 640 log.error(f"internal server error: {e}\n{''.join(tb)}") |
633 self._iq_error(client, iq_elt, condition='internal-server-error') | 641 self._iq_error(client, iq_elt, condition="internal-server-error") |
634 return | 642 return |
635 iq_result_elt = xmlstream.toResponse(iq_elt, "result") | 643 iq_result_elt = xmlstream.toResponse(iq_elt, "result") |
636 query_elt = iq_result_elt.addElement((NS_FIS, "query")) | 644 query_elt = iq_result_elt.addElement((NS_FIS, "query")) |
637 query_elt["node"] = node_path | 645 query_elt["node"] = node_path |
638 if not self.host.trigger.point( | 646 if not self.host.trigger.point( |
640 client, | 648 client, |
641 iq_elt, | 649 iq_elt, |
642 iq_result_elt, | 650 iq_result_elt, |
643 owner, | 651 owner, |
644 node_path, | 652 node_path, |
645 files_data | 653 files_data, |
646 ): | 654 ): |
647 return | 655 return |
648 for file_data in files_data: | 656 for file_data in files_data: |
649 if file_data['type'] == C.FILE_TYPE_DIRECTORY: | 657 if file_data["type"] == C.FILE_TYPE_DIRECTORY: |
650 directory_elt = query_elt.addElement("directory") | 658 directory_elt = query_elt.addElement("directory") |
651 directory_elt['name'] = file_data['name'] | 659 directory_elt["name"] = file_data["name"] |
652 self.host.trigger.point( | 660 self.host.trigger.point( |
653 "XEP-0329_compGetFilesFromNode_build_directory", | 661 "XEP-0329_compGetFilesFromNode_build_directory", |
654 client, | 662 client, |
655 file_data, | 663 file_data, |
656 directory_elt, | 664 directory_elt, |
659 ) | 667 ) |
660 else: | 668 else: |
661 file_elt = self._jf.build_file_element_from_dict( | 669 file_elt = self._jf.build_file_element_from_dict( |
662 client, | 670 client, |
663 file_data, | 671 file_data, |
664 modified=file_data.get("modified", file_data["created"]) | 672 modified=file_data.get("modified", file_data["created"]), |
665 ) | 673 ) |
666 query_elt.addChild(file_elt) | 674 query_elt.addChild(file_elt) |
667 client.send(iq_result_elt) | 675 client.send(iq_result_elt) |
668 | 676 |
669 def on_component_request(self, iq_elt, client): | 677 def on_component_request(self, iq_elt, client): |
670 return self._request_handler( | 678 return self._request_handler( |
671 client, iq_elt, self._comp_get_root_nodes_cb, self._comp_get_files_from_node_cb | 679 client, |
680 iq_elt, | |
681 self._comp_get_root_nodes_cb, | |
682 self._comp_get_files_from_node_cb, | |
672 ) | 683 ) |
673 | 684 |
674 async def _parse_result(self, client, peer_jid, iq_elt): | 685 async def _parse_result(self, client, peer_jid, iq_elt): |
675 query_elt = next(iq_elt.elements(NS_FIS, "query")) | 686 query_elt = next(iq_elt.elements(NS_FIS, "query")) |
676 files = [] | 687 files = [] |
682 file_data = await self._jf.parse_file_element(client, elt) | 693 file_data = await self._jf.parse_file_element(client, elt) |
683 except exceptions.DataError: | 694 except exceptions.DataError: |
684 continue | 695 continue |
685 file_data["type"] = C.FILE_TYPE_FILE | 696 file_data["type"] = C.FILE_TYPE_FILE |
686 try: | 697 try: |
687 thumbs = file_data['extra'][C.KEY_THUMBNAILS] | 698 thumbs = file_data["extra"][C.KEY_THUMBNAILS] |
688 except KeyError: | 699 except KeyError: |
689 log.debug(f"No thumbnail found for {file_data}") | 700 log.debug(f"No thumbnail found for {file_data}") |
690 else: | 701 else: |
691 for thumb in thumbs: | 702 for thumb in thumbs: |
692 if 'url' not in thumb and "id" in thumb: | 703 if "url" not in thumb and "id" in thumb: |
693 try: | 704 try: |
694 file_path = await self._b.get_file(client, peer_jid, thumb['id']) | 705 file_path = await self._b.get_file( |
706 client, peer_jid, thumb["id"] | |
707 ) | |
695 except Exception as e: | 708 except Exception as e: |
696 log.warning(f"Can't get thumbnail {thumb['id']!r} for {file_data}: {e}") | 709 log.warning( |
710 f"Can't get thumbnail {thumb['id']!r} for {file_data}: {e}" | |
711 ) | |
697 else: | 712 else: |
698 thumb['filename'] = file_path.name | 713 thumb["filename"] = file_path.name |
699 | 714 |
700 elif elt.name == "directory" and elt.uri == NS_FIS: | 715 elif elt.name == "directory" and elt.uri == NS_FIS: |
701 # we have a directory | 716 # we have a directory |
702 | 717 |
703 file_data = {"name": elt["name"], "type": C.FILE_TYPE_DIRECTORY} | 718 file_data = {"name": elt["name"], "type": C.FILE_TYPE_DIRECTORY} |
707 elt, | 722 elt, |
708 file_data, | 723 file_data, |
709 ) | 724 ) |
710 else: | 725 else: |
711 log.warning( | 726 log.warning( |
712 _("unexpected element, ignoring: {elt}") | 727 _("unexpected element, ignoring: {elt}").format(elt=elt.toXml()) |
713 .format(elt=elt.toXml()) | |
714 ) | 728 ) |
715 continue | 729 continue |
716 files.append(file_data) | 730 files.append(file_data) |
717 return files | 731 return files |
718 | 732 |
719 # affiliations # | 733 # affiliations # |
720 | 734 |
721 async def _parse_element(self, client, iq_elt, element, namespace): | 735 async def _parse_element(self, client, iq_elt, element, namespace): |
722 peer_jid, owner = client.get_owner_and_peer(iq_elt) | 736 peer_jid, owner = client.get_owner_and_peer(iq_elt) |
723 elt = next(iq_elt.elements(namespace, element)) | 737 elt = next(iq_elt.elements(namespace, element)) |
724 path = Path("/", elt['path']) | 738 path = Path("/", elt["path"]) |
725 if len(path.parts) < 2: | 739 if len(path.parts) < 2: |
726 raise RootPathException | 740 raise RootPathException |
727 namespace = elt.getAttribute('namespace') | 741 namespace = elt.getAttribute("namespace") |
728 files_data = await self.host.memory.get_files( | 742 files_data = await self.host.memory.get_files( |
729 client, | 743 client, |
730 peer_jid=peer_jid, | 744 peer_jid=peer_jid, |
731 path=str(path.parent), | 745 path=str(path.parent), |
732 name=path.name, | 746 name=path.name, |
733 namespace=namespace, | 747 namespace=namespace, |
734 owner=owner, | 748 owner=owner, |
735 ) | 749 ) |
736 if len(files_data) != 1: | 750 if len(files_data) != 1: |
737 client.sendError(iq_elt, 'item-not-found') | 751 client.sendError(iq_elt, "item-not-found") |
738 raise exceptions.CancelError | 752 raise exceptions.CancelError |
739 file_data = files_data[0] | 753 file_data = files_data[0] |
740 return peer_jid, elt, path, namespace, file_data | 754 return peer_jid, elt, path, namespace, file_data |
741 | 755 |
742 def _affiliations_get(self, service_jid_s, namespace, path, profile): | 756 def _affiliations_get(self, service_jid_s, namespace, path, profile): |
743 client = self.host.get_client(profile) | 757 client = self.host.get_client(profile) |
744 service = jid.JID(service_jid_s) | 758 service = jid.JID(service_jid_s) |
745 d = defer.ensureDeferred(self.affiliationsGet( | 759 d = defer.ensureDeferred( |
746 client, service, namespace or None, path)) | 760 self.affiliationsGet(client, service, namespace or None, path) |
761 ) | |
747 d.addCallback( | 762 d.addCallback( |
748 lambda affiliations: { | 763 lambda affiliations: { |
749 str(entity): affiliation for entity, affiliation in affiliations.items() | 764 str(entity): affiliation for entity, affiliation in affiliations.items() |
750 } | 765 } |
751 ) | 766 ) |
752 return d | 767 return d |
753 | 768 |
754 async def affiliationsGet( | 769 async def affiliationsGet( |
755 self, | 770 self, client: SatXMPPEntity, service: jid.JID, namespace: Optional[str], path: str |
756 client: SatXMPPEntity, | |
757 service: jid.JID, | |
758 namespace: Optional[str], | |
759 path: str | |
760 ) -> Dict[jid.JID, str]: | 771 ) -> Dict[jid.JID, str]: |
761 if not path: | 772 if not path: |
762 raise ValueError(f"invalid path: {path!r}") | 773 raise ValueError(f"invalid path: {path!r}") |
763 iq_elt = client.IQ("get") | 774 iq_elt = client.IQ("get") |
764 iq_elt['to'] = service.full() | 775 iq_elt["to"] = service.full() |
765 affiliations_elt = iq_elt.addElement((NS_FIS_AFFILIATION, "affiliations")) | 776 affiliations_elt = iq_elt.addElement((NS_FIS_AFFILIATION, "affiliations")) |
766 if namespace: | 777 if namespace: |
767 affiliations_elt["namespace"] = namespace | 778 affiliations_elt["namespace"] = namespace |
768 affiliations_elt["path"] = path | 779 affiliations_elt["path"] = path |
769 iq_result_elt = await iq_elt.send() | 780 iq_result_elt = await iq_elt.send() |
770 try: | 781 try: |
771 affiliations_elt = next(iq_result_elt.elements(NS_FIS_AFFILIATION, "affiliations")) | 782 affiliations_elt = next( |
783 iq_result_elt.elements(NS_FIS_AFFILIATION, "affiliations") | |
784 ) | |
772 except StopIteration: | 785 except StopIteration: |
773 raise exceptions.DataError(f"Invalid result to affiliations request: {iq_result_elt.toXml()}") | 786 raise exceptions.DataError( |
787 f"Invalid result to affiliations request: {iq_result_elt.toXml()}" | |
788 ) | |
774 | 789 |
775 affiliations = {} | 790 affiliations = {} |
776 for affiliation_elt in affiliations_elt.elements(NS_FIS_AFFILIATION, 'affiliation'): | 791 for affiliation_elt in affiliations_elt.elements( |
792 NS_FIS_AFFILIATION, "affiliation" | |
793 ): | |
777 try: | 794 try: |
778 affiliations[jid.JID(affiliation_elt['jid'])] = affiliation_elt['affiliation'] | 795 affiliations[jid.JID(affiliation_elt["jid"])] = affiliation_elt[ |
796 "affiliation" | |
797 ] | |
779 except (KeyError, RuntimeError): | 798 except (KeyError, RuntimeError): |
780 raise exceptions.DataError( | 799 raise exceptions.DataError( |
781 f"invalid affiliation element: {affiliation_elt.toXml()}") | 800 f"invalid affiliation element: {affiliation_elt.toXml()}" |
801 ) | |
782 | 802 |
783 return affiliations | 803 return affiliations |
784 | 804 |
785 def _affiliations_set(self, service_jid_s, namespace, path, affiliations, profile): | 805 def _affiliations_set(self, service_jid_s, namespace, path, affiliations, profile): |
786 client = self.host.get_client(profile) | 806 client = self.host.get_client(profile) |
787 service = jid.JID(service_jid_s) | 807 service = jid.JID(service_jid_s) |
788 affiliations = {jid.JID(e): a for e, a in affiliations.items()} | 808 affiliations = {jid.JID(e): a for e, a in affiliations.items()} |
789 return defer.ensureDeferred(self.affiliationsSet( | 809 return defer.ensureDeferred( |
790 client, service, namespace or None, path, affiliations)) | 810 self.affiliationsSet(client, service, namespace or None, path, affiliations) |
811 ) | |
791 | 812 |
792 async def affiliationsSet( | 813 async def affiliationsSet( |
793 self, | 814 self, |
794 client: SatXMPPEntity, | 815 client: SatXMPPEntity, |
795 service: jid.JID, | 816 service: jid.JID, |
798 affiliations: Dict[jid.JID, str], | 819 affiliations: Dict[jid.JID, str], |
799 ): | 820 ): |
800 if not path: | 821 if not path: |
801 raise ValueError(f"invalid path: {path!r}") | 822 raise ValueError(f"invalid path: {path!r}") |
802 iq_elt = client.IQ("set") | 823 iq_elt = client.IQ("set") |
803 iq_elt['to'] = service.full() | 824 iq_elt["to"] = service.full() |
804 affiliations_elt = iq_elt.addElement((NS_FIS_AFFILIATION, "affiliations")) | 825 affiliations_elt = iq_elt.addElement((NS_FIS_AFFILIATION, "affiliations")) |
805 if namespace: | 826 if namespace: |
806 affiliations_elt["namespace"] = namespace | 827 affiliations_elt["namespace"] = namespace |
807 affiliations_elt["path"] = path | 828 affiliations_elt["path"] = path |
808 for entity_jid, affiliation in affiliations.items(): | 829 for entity_jid, affiliation in affiliations.items(): |
809 affiliation_elt = affiliations_elt.addElement('affiliation') | 830 affiliation_elt = affiliations_elt.addElement("affiliation") |
810 affiliation_elt['jid'] = entity_jid.full() | 831 affiliation_elt["jid"] = entity_jid.full() |
811 affiliation_elt['affiliation'] = affiliation | 832 affiliation_elt["affiliation"] = affiliation |
812 await iq_elt.send() | 833 await iq_elt.send() |
813 | 834 |
814 def _on_component_affiliations_get(self, iq_elt, client): | 835 def _on_component_affiliations_get(self, iq_elt, client): |
815 iq_elt.handled = True | 836 iq_elt.handled = True |
816 defer.ensureDeferred(self.on_component_affiliations_get(client, iq_elt)) | 837 defer.ensureDeferred(self.on_component_affiliations_get(client, iq_elt)) |
817 | 838 |
818 async def on_component_affiliations_get(self, client, iq_elt): | 839 async def on_component_affiliations_get(self, client, iq_elt): |
819 try: | 840 try: |
820 ( | 841 (from_jid, affiliations_elt, path, namespace, file_data) = ( |
821 from_jid, affiliations_elt, path, namespace, file_data | 842 await self._parse_element( |
822 ) = await self._parse_element(client, iq_elt, "affiliations", NS_FIS_AFFILIATION) | 843 client, iq_elt, "affiliations", NS_FIS_AFFILIATION |
844 ) | |
845 ) | |
823 except exceptions.CancelError: | 846 except exceptions.CancelError: |
824 return | 847 return |
825 except RootPathException: | 848 except RootPathException: |
826 # if root path is requested, we only get owner affiliation | 849 # if root path is requested, we only get owner affiliation |
827 peer_jid, owner = client.get_owner_and_peer(iq_elt) | 850 peer_jid, owner = client.get_owner_and_peer(iq_elt) |
828 is_owner = peer_jid.userhostJID() == owner | 851 is_owner = peer_jid.userhostJID() == owner |
829 affiliations = {owner: 'owner'} | 852 affiliations = {owner: "owner"} |
830 except exceptions.NotFound: | 853 except exceptions.NotFound: |
831 client.sendError(iq_elt, "item-not-found") | 854 client.sendError(iq_elt, "item-not-found") |
832 return | 855 return |
833 except Exception as e: | 856 except Exception as e: |
834 client.sendError(iq_elt, "internal-server-error", str(e)) | 857 client.sendError(iq_elt, "internal-server-error", str(e)) |
835 return | 858 return |
836 else: | 859 else: |
837 from_jid_bare = from_jid.userhostJID() | 860 from_jid_bare = from_jid.userhostJID() |
838 is_owner = from_jid_bare == file_data.get('owner') | 861 is_owner = from_jid_bare == file_data.get("owner") |
839 affiliations = self.host.memory.get_file_affiliations(file_data) | 862 affiliations = self.host.memory.get_file_affiliations(file_data) |
840 iq_result_elt = xmlstream.toResponse(iq_elt, "result") | 863 iq_result_elt = xmlstream.toResponse(iq_elt, "result") |
841 affiliations_elt = iq_result_elt.addElement((NS_FIS_AFFILIATION, 'affiliations')) | 864 affiliations_elt = iq_result_elt.addElement((NS_FIS_AFFILIATION, "affiliations")) |
842 for entity_jid, affiliation in affiliations.items(): | 865 for entity_jid, affiliation in affiliations.items(): |
843 if not is_owner and entity_jid.userhostJID() != from_jid_bare: | 866 if not is_owner and entity_jid.userhostJID() != from_jid_bare: |
844 # only onwer can get all affiliations | 867 # only onwer can get all affiliations |
845 continue | 868 continue |
846 affiliation_elt = affiliations_elt.addElement('affiliation') | 869 affiliation_elt = affiliations_elt.addElement("affiliation") |
847 affiliation_elt['jid'] = entity_jid.userhost() | 870 affiliation_elt["jid"] = entity_jid.userhost() |
848 affiliation_elt['affiliation'] = affiliation | 871 affiliation_elt["affiliation"] = affiliation |
849 client.send(iq_result_elt) | 872 client.send(iq_result_elt) |
850 | 873 |
851 def _on_component_affiliations_set(self, iq_elt, client): | 874 def _on_component_affiliations_set(self, iq_elt, client): |
852 iq_elt.handled = True | 875 iq_elt.handled = True |
853 defer.ensureDeferred(self.on_component_affiliations_set(client, iq_elt)) | 876 defer.ensureDeferred(self.on_component_affiliations_set(client, iq_elt)) |
854 | 877 |
855 async def on_component_affiliations_set(self, client, iq_elt): | 878 async def on_component_affiliations_set(self, client, iq_elt): |
856 try: | 879 try: |
857 ( | 880 (from_jid, affiliations_elt, path, namespace, file_data) = ( |
858 from_jid, affiliations_elt, path, namespace, file_data | 881 await self._parse_element( |
859 ) = await self._parse_element(client, iq_elt, "affiliations", NS_FIS_AFFILIATION) | 882 client, iq_elt, "affiliations", NS_FIS_AFFILIATION |
883 ) | |
884 ) | |
860 except exceptions.CancelError: | 885 except exceptions.CancelError: |
861 return | 886 return |
862 except RootPathException: | 887 except RootPathException: |
863 client.sendError(iq_elt, 'bad-request', "Root path can't be used") | 888 client.sendError(iq_elt, "bad-request", "Root path can't be used") |
864 return | 889 return |
865 | 890 |
866 if from_jid.userhostJID() != file_data['owner']: | 891 if from_jid.userhostJID() != file_data["owner"]: |
867 log.warning( | 892 log.warning( |
868 f"{from_jid} tried to modify {path} affiliations while the owner is " | 893 f"{from_jid} tried to modify {path} affiliations while the owner is " |
869 f"{file_data['owner']}" | 894 f"{file_data['owner']}" |
870 ) | 895 ) |
871 client.sendError(iq_elt, 'forbidden') | 896 client.sendError(iq_elt, "forbidden") |
872 return | 897 return |
873 | 898 |
874 try: | 899 try: |
875 affiliations = { | 900 affiliations = { |
876 jid.JID(e['jid']): e['affiliation'] | 901 jid.JID(e["jid"]): e["affiliation"] |
877 for e in affiliations_elt.elements(NS_FIS_AFFILIATION, 'affiliation') | 902 for e in affiliations_elt.elements(NS_FIS_AFFILIATION, "affiliation") |
878 } | 903 } |
879 except (KeyError, RuntimeError): | 904 except (KeyError, RuntimeError): |
880 log.warning( | 905 log.warning(f"invalid affiliation element: {affiliations_elt.toXml()}") |
881 f"invalid affiliation element: {affiliations_elt.toXml()}" | 906 client.sendError(iq_elt, "bad-request", "invalid affiliation element") |
882 ) | 907 return |
883 client.sendError(iq_elt, 'bad-request', "invalid affiliation element") | |
884 return | |
885 except Exception as e: | 908 except Exception as e: |
886 log.error( | 909 log.error( |
887 f"unexepected exception while setting affiliation element: {e}\n" | 910 f"unexepected exception while setting affiliation element: {e}\n" |
888 f"{affiliations_elt.toXml()}" | 911 f"{affiliations_elt.toXml()}" |
889 ) | 912 ) |
890 client.sendError(iq_elt, 'internal-server-error', f"{e}") | 913 client.sendError(iq_elt, "internal-server-error", f"{e}") |
891 return | 914 return |
892 | 915 |
893 await self.host.memory.set_file_affiliations(client, file_data, affiliations) | 916 await self.host.memory.set_file_affiliations(client, file_data, affiliations) |
894 | 917 |
895 iq_result_elt = xmlstream.toResponse(iq_elt, "result") | 918 iq_result_elt = xmlstream.toResponse(iq_elt, "result") |
896 client.send(iq_result_elt) | 919 client.send(iq_result_elt) |
898 # configuration | 921 # configuration |
899 | 922 |
900 def _configuration_get(self, service_jid_s, namespace, path, profile): | 923 def _configuration_get(self, service_jid_s, namespace, path, profile): |
901 client = self.host.get_client(profile) | 924 client = self.host.get_client(profile) |
902 service = jid.JID(service_jid_s) | 925 service = jid.JID(service_jid_s) |
903 d = defer.ensureDeferred(self.configuration_get( | 926 d = defer.ensureDeferred( |
904 client, service, namespace or None, path)) | 927 self.configuration_get(client, service, namespace or None, path) |
928 ) | |
905 d.addCallback( | 929 d.addCallback( |
906 lambda configuration: { | 930 lambda configuration: { |
907 str(entity): affiliation for entity, affiliation in configuration.items() | 931 str(entity): affiliation for entity, affiliation in configuration.items() |
908 } | 932 } |
909 ) | 933 ) |
910 return d | 934 return d |
911 | 935 |
912 async def configuration_get( | 936 async def configuration_get( |
913 self, | 937 self, client: SatXMPPEntity, service: jid.JID, namespace: Optional[str], path: str |
914 client: SatXMPPEntity, | |
915 service: jid.JID, | |
916 namespace: Optional[str], | |
917 path: str | |
918 ) -> Dict[str, str]: | 938 ) -> Dict[str, str]: |
919 if not path: | 939 if not path: |
920 raise ValueError(f"invalid path: {path!r}") | 940 raise ValueError(f"invalid path: {path!r}") |
921 iq_elt = client.IQ("get") | 941 iq_elt = client.IQ("get") |
922 iq_elt['to'] = service.full() | 942 iq_elt["to"] = service.full() |
923 configuration_elt = iq_elt.addElement((NS_FIS_CONFIGURATION, "configuration")) | 943 configuration_elt = iq_elt.addElement((NS_FIS_CONFIGURATION, "configuration")) |
924 if namespace: | 944 if namespace: |
925 configuration_elt["namespace"] = namespace | 945 configuration_elt["namespace"] = namespace |
926 configuration_elt["path"] = path | 946 configuration_elt["path"] = path |
927 iq_result_elt = await iq_elt.send() | 947 iq_result_elt = await iq_elt.send() |
928 try: | 948 try: |
929 configuration_elt = next(iq_result_elt.elements(NS_FIS_CONFIGURATION, "configuration")) | 949 configuration_elt = next( |
950 iq_result_elt.elements(NS_FIS_CONFIGURATION, "configuration") | |
951 ) | |
930 except StopIteration: | 952 except StopIteration: |
931 raise exceptions.DataError(f"Invalid result to configuration request: {iq_result_elt.toXml()}") | 953 raise exceptions.DataError( |
954 f"Invalid result to configuration request: {iq_result_elt.toXml()}" | |
955 ) | |
932 | 956 |
933 form = data_form.findForm(configuration_elt, NS_FIS_CONFIGURATION) | 957 form = data_form.findForm(configuration_elt, NS_FIS_CONFIGURATION) |
934 configuration = {f.var: f.value for f in form.fields.values()} | 958 configuration = {f.var: f.value for f in form.fields.values()} |
935 | 959 |
936 return configuration | 960 return configuration |
937 | 961 |
938 def _configuration_set(self, service_jid_s, namespace, path, configuration, profile): | 962 def _configuration_set(self, service_jid_s, namespace, path, configuration, profile): |
939 client = self.host.get_client(profile) | 963 client = self.host.get_client(profile) |
940 service = jid.JID(service_jid_s) | 964 service = jid.JID(service_jid_s) |
941 return defer.ensureDeferred(self.configuration_set( | 965 return defer.ensureDeferred( |
942 client, service, namespace or None, path, configuration)) | 966 self.configuration_set( |
967 client, service, namespace or None, path, configuration | |
968 ) | |
969 ) | |
943 | 970 |
944 async def configuration_set( | 971 async def configuration_set( |
945 self, | 972 self, |
946 client: SatXMPPEntity, | 973 client: SatXMPPEntity, |
947 service: jid.JID, | 974 service: jid.JID, |
950 configuration: Dict[str, str], | 977 configuration: Dict[str, str], |
951 ): | 978 ): |
952 if not path: | 979 if not path: |
953 raise ValueError(f"invalid path: {path!r}") | 980 raise ValueError(f"invalid path: {path!r}") |
954 iq_elt = client.IQ("set") | 981 iq_elt = client.IQ("set") |
955 iq_elt['to'] = service.full() | 982 iq_elt["to"] = service.full() |
956 configuration_elt = iq_elt.addElement((NS_FIS_CONFIGURATION, "configuration")) | 983 configuration_elt = iq_elt.addElement((NS_FIS_CONFIGURATION, "configuration")) |
957 if namespace: | 984 if namespace: |
958 configuration_elt["namespace"] = namespace | 985 configuration_elt["namespace"] = namespace |
959 configuration_elt["path"] = path | 986 configuration_elt["path"] = path |
960 form = data_form.Form(formType="submit", formNamespace=NS_FIS_CONFIGURATION) | 987 form = data_form.Form(formType="submit", formNamespace=NS_FIS_CONFIGURATION) |
966 iq_elt.handled = True | 993 iq_elt.handled = True |
967 defer.ensureDeferred(self.on_component_configuration_get(client, iq_elt)) | 994 defer.ensureDeferred(self.on_component_configuration_get(client, iq_elt)) |
968 | 995 |
969 async def on_component_configuration_get(self, client, iq_elt): | 996 async def on_component_configuration_get(self, client, iq_elt): |
970 try: | 997 try: |
971 ( | 998 (from_jid, configuration_elt, path, namespace, file_data) = ( |
972 from_jid, configuration_elt, path, namespace, file_data | 999 await self._parse_element( |
973 ) = await self._parse_element(client, iq_elt, "configuration", NS_FIS_CONFIGURATION) | 1000 client, iq_elt, "configuration", NS_FIS_CONFIGURATION |
1001 ) | |
1002 ) | |
974 except exceptions.CancelError: | 1003 except exceptions.CancelError: |
975 return | 1004 return |
976 except RootPathException: | 1005 except RootPathException: |
977 client.sendError(iq_elt, 'bad-request', "Root path can't be used") | 1006 client.sendError(iq_elt, "bad-request", "Root path can't be used") |
978 return | 1007 return |
979 try: | 1008 try: |
980 access_type = file_data['access'][C.ACCESS_PERM_READ]['type'] | 1009 access_type = file_data["access"][C.ACCESS_PERM_READ]["type"] |
981 except KeyError: | 1010 except KeyError: |
982 access_model = 'whitelist' | 1011 access_model = "whitelist" |
983 else: | 1012 else: |
984 access_model = 'open' if access_type == C.ACCESS_TYPE_PUBLIC else 'whitelist' | 1013 access_model = "open" if access_type == C.ACCESS_TYPE_PUBLIC else "whitelist" |
985 | 1014 |
986 iq_result_elt = xmlstream.toResponse(iq_elt, "result") | 1015 iq_result_elt = xmlstream.toResponse(iq_elt, "result") |
987 configuration_elt = iq_result_elt.addElement((NS_FIS_CONFIGURATION, 'configuration')) | 1016 configuration_elt = iq_result_elt.addElement( |
1017 (NS_FIS_CONFIGURATION, "configuration") | |
1018 ) | |
988 form = data_form.Form(formType="form", formNamespace=NS_FIS_CONFIGURATION) | 1019 form = data_form.Form(formType="form", formNamespace=NS_FIS_CONFIGURATION) |
989 form.makeFields({'access_model': access_model}) | 1020 form.makeFields({"access_model": access_model}) |
990 configuration_elt.addChild(form.toElement()) | 1021 configuration_elt.addChild(form.toElement()) |
991 client.send(iq_result_elt) | 1022 client.send(iq_result_elt) |
992 | 1023 |
993 async def _set_configuration(self, client, configuration_elt, file_data): | 1024 async def _set_configuration(self, client, configuration_elt, file_data): |
994 form = data_form.findForm(configuration_elt, NS_FIS_CONFIGURATION) | 1025 form = data_form.findForm(configuration_elt, NS_FIS_CONFIGURATION) |
995 for name, value in form.items(): | 1026 for name, value in form.items(): |
996 if name == 'access_model': | 1027 if name == "access_model": |
997 await self.host.memory.set_file_access_model(client, file_data, value) | 1028 await self.host.memory.set_file_access_model(client, file_data, value) |
998 else: | 1029 else: |
999 # TODO: send a IQ error? | 1030 # TODO: send a IQ error? |
1000 log.warning( | 1031 log.warning( |
1001 f"Trying to set a not implemented configuration option: {name}") | 1032 f"Trying to set a not implemented configuration option: {name}" |
1033 ) | |
1002 | 1034 |
1003 def _on_component_configuration_set(self, iq_elt, client): | 1035 def _on_component_configuration_set(self, iq_elt, client): |
1004 iq_elt.handled = True | 1036 iq_elt.handled = True |
1005 defer.ensureDeferred(self.on_component_configuration_set(client, iq_elt)) | 1037 defer.ensureDeferred(self.on_component_configuration_set(client, iq_elt)) |
1006 | 1038 |
1007 async def on_component_configuration_set(self, client, iq_elt): | 1039 async def on_component_configuration_set(self, client, iq_elt): |
1008 try: | 1040 try: |
1009 ( | 1041 (from_jid, configuration_elt, path, namespace, file_data) = ( |
1010 from_jid, configuration_elt, path, namespace, file_data | 1042 await self._parse_element( |
1011 ) = await self._parse_element(client, iq_elt, "configuration", NS_FIS_CONFIGURATION) | 1043 client, iq_elt, "configuration", NS_FIS_CONFIGURATION |
1044 ) | |
1045 ) | |
1012 except exceptions.CancelError: | 1046 except exceptions.CancelError: |
1013 return | 1047 return |
1014 except RootPathException: | 1048 except RootPathException: |
1015 client.sendError(iq_elt, 'bad-request', "Root path can't be used") | 1049 client.sendError(iq_elt, "bad-request", "Root path can't be used") |
1016 return | 1050 return |
1017 | 1051 |
1018 from_jid_bare = from_jid.userhostJID() | 1052 from_jid_bare = from_jid.userhostJID() |
1019 is_owner = from_jid_bare == file_data.get('owner') | 1053 is_owner = from_jid_bare == file_data.get("owner") |
1020 if not is_owner: | 1054 if not is_owner: |
1021 log.warning( | 1055 log.warning( |
1022 f"{from_jid} tried to modify {path} configuration while the owner is " | 1056 f"{from_jid} tried to modify {path} configuration while the owner is " |
1023 f"{file_data['owner']}" | 1057 f"{file_data['owner']}" |
1024 ) | 1058 ) |
1025 client.sendError(iq_elt, 'forbidden') | 1059 client.sendError(iq_elt, "forbidden") |
1026 return | 1060 return |
1027 | 1061 |
1028 await self._set_configuration(client, configuration_elt, file_data) | 1062 await self._set_configuration(client, configuration_elt, file_data) |
1029 | 1063 |
1030 iq_result_elt = xmlstream.toResponse(iq_elt, "result") | 1064 iq_result_elt = xmlstream.toResponse(iq_elt, "result") |
1033 # directory creation | 1067 # directory creation |
1034 | 1068 |
1035 def _create_dir(self, service_jid_s, namespace, path, configuration, profile): | 1069 def _create_dir(self, service_jid_s, namespace, path, configuration, profile): |
1036 client = self.host.get_client(profile) | 1070 client = self.host.get_client(profile) |
1037 service = jid.JID(service_jid_s) | 1071 service = jid.JID(service_jid_s) |
1038 return defer.ensureDeferred(self.create_dir( | 1072 return defer.ensureDeferred( |
1039 client, service, namespace or None, path, configuration or None)) | 1073 self.create_dir( |
1074 client, service, namespace or None, path, configuration or None | |
1075 ) | |
1076 ) | |
1040 | 1077 |
1041 async def create_dir( | 1078 async def create_dir( |
1042 self, | 1079 self, |
1043 client: SatXMPPEntity, | 1080 client: SatXMPPEntity, |
1044 service: jid.JID, | 1081 service: jid.JID, |
1047 configuration: Optional[Dict[str, str]], | 1084 configuration: Optional[Dict[str, str]], |
1048 ): | 1085 ): |
1049 if not path: | 1086 if not path: |
1050 raise ValueError(f"invalid path: {path!r}") | 1087 raise ValueError(f"invalid path: {path!r}") |
1051 iq_elt = client.IQ("set") | 1088 iq_elt = client.IQ("set") |
1052 iq_elt['to'] = service.full() | 1089 iq_elt["to"] = service.full() |
1053 create_dir_elt = iq_elt.addElement((NS_FIS_CREATE, "dir")) | 1090 create_dir_elt = iq_elt.addElement((NS_FIS_CREATE, "dir")) |
1054 if namespace: | 1091 if namespace: |
1055 create_dir_elt["namespace"] = namespace | 1092 create_dir_elt["namespace"] = namespace |
1056 create_dir_elt["path"] = path | 1093 create_dir_elt["path"] = path |
1057 if configuration: | 1094 if configuration: |
1058 configuration_elt = create_dir_elt.addElement((NS_FIS_CONFIGURATION, "configuration")) | 1095 configuration_elt = create_dir_elt.addElement( |
1096 (NS_FIS_CONFIGURATION, "configuration") | |
1097 ) | |
1059 form = data_form.Form(formType="submit", formNamespace=NS_FIS_CONFIGURATION) | 1098 form = data_form.Form(formType="submit", formNamespace=NS_FIS_CONFIGURATION) |
1060 form.makeFields(configuration) | 1099 form.makeFields(configuration) |
1061 configuration_elt.addChild(form.toElement()) | 1100 configuration_elt.addChild(form.toElement()) |
1062 await iq_elt.send() | 1101 await iq_elt.send() |
1063 | 1102 |
1066 defer.ensureDeferred(self.on_component_create_dir(client, iq_elt)) | 1105 defer.ensureDeferred(self.on_component_create_dir(client, iq_elt)) |
1067 | 1106 |
1068 async def on_component_create_dir(self, client, iq_elt): | 1107 async def on_component_create_dir(self, client, iq_elt): |
1069 peer_jid, owner = client.get_owner_and_peer(iq_elt) | 1108 peer_jid, owner = client.get_owner_and_peer(iq_elt) |
1070 if peer_jid.host not in client._file_sharing_allowed_hosts: | 1109 if peer_jid.host not in client._file_sharing_allowed_hosts: |
1071 client.sendError(iq_elt, 'forbidden') | 1110 client.sendError(iq_elt, "forbidden") |
1072 return | 1111 return |
1073 create_dir_elt = next(iq_elt.elements(NS_FIS_CREATE, "dir")) | 1112 create_dir_elt = next(iq_elt.elements(NS_FIS_CREATE, "dir")) |
1074 namespace = create_dir_elt.getAttribute('namespace') | 1113 namespace = create_dir_elt.getAttribute("namespace") |
1075 path = Path("/", create_dir_elt['path']) | 1114 path = Path("/", create_dir_elt["path"]) |
1076 if len(path.parts) < 2: | 1115 if len(path.parts) < 2: |
1077 client.sendError(iq_elt, 'bad-request', "Root path can't be used") | 1116 client.sendError(iq_elt, "bad-request", "Root path can't be used") |
1078 return | 1117 return |
1079 # for root directories, we check permission here | 1118 # for root directories, we check permission here |
1080 if len(path.parts) == 2 and owner != peer_jid.userhostJID(): | 1119 if len(path.parts) == 2 and owner != peer_jid.userhostJID(): |
1081 log.warning( | 1120 log.warning( |
1082 f"{peer_jid} is trying to create a dir at {owner}'s repository:\n" | 1121 f"{peer_jid} is trying to create a dir at {owner}'s repository:\n" |
1083 f"path: {path}\nnamespace: {namespace!r}" | 1122 f"path: {path}\nnamespace: {namespace!r}" |
1084 ) | 1123 ) |
1085 client.sendError(iq_elt, 'forbidden', "You can't create a directory there") | 1124 client.sendError(iq_elt, "forbidden", "You can't create a directory there") |
1086 return | 1125 return |
1087 # when going further into the path, the permissions will be checked by get_files | 1126 # when going further into the path, the permissions will be checked by get_files |
1088 files_data = await self.host.memory.get_files( | 1127 files_data = await self.host.memory.get_files( |
1089 client, | 1128 client, |
1090 peer_jid=peer_jid, | 1129 peer_jid=peer_jid, |
1091 path=path.parent, | 1130 path=path.parent, |
1092 namespace=namespace, | 1131 namespace=namespace, |
1093 owner=owner, | 1132 owner=owner, |
1094 ) | 1133 ) |
1095 if path.name in [d['name'] for d in files_data]: | 1134 if path.name in [d["name"] for d in files_data]: |
1096 log.warning( | 1135 log.warning( |
1097 f"Conflict when trying to create a directory (from: {peer_jid} " | 1136 f"Conflict when trying to create a directory (from: {peer_jid} " |
1098 f"namespace: {namespace!r} path: {path!r})" | 1137 f"namespace: {namespace!r} path: {path!r})" |
1099 ) | 1138 ) |
1100 client.sendError( | 1139 client.sendError( |
1101 iq_elt, 'conflict', "there is already a file or dir at this path") | 1140 iq_elt, "conflict", "there is already a file or dir at this path" |
1141 ) | |
1102 return | 1142 return |
1103 | 1143 |
1104 try: | 1144 try: |
1105 configuration_elt = next( | 1145 configuration_elt = next( |
1106 create_dir_elt.elements(NS_FIS_CONFIGURATION, 'configuration')) | 1146 create_dir_elt.elements(NS_FIS_CONFIGURATION, "configuration") |
1147 ) | |
1107 except StopIteration: | 1148 except StopIteration: |
1108 configuration_elt = None | 1149 configuration_elt = None |
1109 | 1150 |
1110 await self.host.memory.set_file( | 1151 await self.host.memory.set_file( |
1111 client, | 1152 client, |
1112 path.name, | 1153 path.name, |
1113 path=path.parent, | 1154 path=path.parent, |
1114 type_=C.FILE_TYPE_DIRECTORY, | 1155 type_=C.FILE_TYPE_DIRECTORY, |
1115 namespace=namespace, | 1156 namespace=namespace, |
1116 owner=owner, | 1157 owner=owner, |
1117 peer_jid=peer_jid | 1158 peer_jid=peer_jid, |
1118 ) | 1159 ) |
1119 | 1160 |
1120 if configuration_elt is not None: | 1161 if configuration_elt is not None: |
1121 file_data = (await self.host.memory.get_files( | 1162 file_data = ( |
1122 client, | 1163 await self.host.memory.get_files( |
1123 peer_jid=peer_jid, | 1164 client, |
1124 path=path.parent, | 1165 peer_jid=peer_jid, |
1125 name=path.name, | 1166 path=path.parent, |
1126 namespace=namespace, | 1167 name=path.name, |
1127 owner=owner, | 1168 namespace=namespace, |
1128 ))[0] | 1169 owner=owner, |
1170 ) | |
1171 )[0] | |
1129 | 1172 |
1130 await self._set_configuration(client, configuration_elt, file_data) | 1173 await self._set_configuration(client, configuration_elt, file_data) |
1131 | 1174 |
1132 iq_result_elt = xmlstream.toResponse(iq_elt, "result") | 1175 iq_result_elt = xmlstream.toResponse(iq_elt, "result") |
1133 client.send(iq_result_elt) | 1176 client.send(iq_result_elt) |
1135 # file methods # | 1178 # file methods # |
1136 | 1179 |
1137 def _serialize_data(self, files_data): | 1180 def _serialize_data(self, files_data): |
1138 for file_data in files_data: | 1181 for file_data in files_data: |
1139 for key, value in file_data.items(): | 1182 for key, value in file_data.items(): |
1140 file_data[key] = ( | 1183 file_data[key] = json.dumps(value) if key in ("extra",) else str(value) |
1141 json.dumps(value) if key in ("extra",) else str(value) | |
1142 ) | |
1143 return files_data | 1184 return files_data |
1144 | 1185 |
1145 def _list_files(self, target_jid, path, extra, profile): | 1186 def _list_files(self, target_jid, path, extra, profile): |
1146 client = self.host.get_client(profile) | 1187 client = self.host.get_client(profile) |
1147 target_jid = client.jid if not target_jid else jid.JID(target_jid) | 1188 target_jid = client.jid if not target_jid else jid.JID(target_jid) |
1205 new_name = name + "_" + str(idx) | 1246 new_name = name + "_" + str(idx) |
1206 while new_name in node: | 1247 while new_name in node: |
1207 idx += 1 | 1248 idx += 1 |
1208 new_name = name + "_" + str(idx) | 1249 new_name = name + "_" + str(idx) |
1209 name = new_name | 1250 name = new_name |
1210 log.info(_( | 1251 log.info( |
1211 "A directory with this name is already shared, renamed to {new_name} " | 1252 _( |
1212 "[{profile}]".format( new_name=new_name, profile=client.profile))) | 1253 "A directory with this name is already shared, renamed to {new_name} " |
1254 "[{profile}]".format(new_name=new_name, profile=client.profile) | |
1255 ) | |
1256 ) | |
1213 | 1257 |
1214 ShareNode(name=name, parent=node, type_=node_type, access=access, path=path) | 1258 ShareNode(name=name, parent=node, type_=node_type, access=access, path=path) |
1215 self.host.bridge.fis_shared_path_new(path, name, client.profile) | 1259 self.host.bridge.fis_shared_path_new(path, name, client.profile) |
1216 return name | 1260 return name |
1217 | 1261 |
1234 self.host = plugin_parent.host | 1278 self.host = plugin_parent.host |
1235 | 1279 |
1236 def connectionInitialized(self): | 1280 def connectionInitialized(self): |
1237 if self.parent.is_component: | 1281 if self.parent.is_component: |
1238 self.xmlstream.addObserver( | 1282 self.xmlstream.addObserver( |
1239 IQ_FIS_REQUEST, self.plugin_parent.on_component_request, client=self.parent | 1283 IQ_FIS_REQUEST, |
1284 self.plugin_parent.on_component_request, | |
1285 client=self.parent, | |
1240 ) | 1286 ) |
1241 self.xmlstream.addObserver( | 1287 self.xmlstream.addObserver( |
1242 IQ_FIS_AFFILIATION_GET, | 1288 IQ_FIS_AFFILIATION_GET, |
1243 self.plugin_parent._on_component_affiliations_get, | 1289 self.plugin_parent._on_component_affiliations_get, |
1244 client=self.parent | 1290 client=self.parent, |
1245 ) | 1291 ) |
1246 self.xmlstream.addObserver( | 1292 self.xmlstream.addObserver( |
1247 IQ_FIS_AFFILIATION_SET, | 1293 IQ_FIS_AFFILIATION_SET, |
1248 self.plugin_parent._on_component_affiliations_set, | 1294 self.plugin_parent._on_component_affiliations_set, |
1249 client=self.parent | 1295 client=self.parent, |
1250 ) | 1296 ) |
1251 self.xmlstream.addObserver( | 1297 self.xmlstream.addObserver( |
1252 IQ_FIS_CONFIGURATION_GET, | 1298 IQ_FIS_CONFIGURATION_GET, |
1253 self.plugin_parent._on_component_configuration_get, | 1299 self.plugin_parent._on_component_configuration_get, |
1254 client=self.parent | 1300 client=self.parent, |
1255 ) | 1301 ) |
1256 self.xmlstream.addObserver( | 1302 self.xmlstream.addObserver( |
1257 IQ_FIS_CONFIGURATION_SET, | 1303 IQ_FIS_CONFIGURATION_SET, |
1258 self.plugin_parent._on_component_configuration_set, | 1304 self.plugin_parent._on_component_configuration_set, |
1259 client=self.parent | 1305 client=self.parent, |
1260 ) | 1306 ) |
1261 self.xmlstream.addObserver( | 1307 self.xmlstream.addObserver( |
1262 IQ_FIS_CREATE_DIR, | 1308 IQ_FIS_CREATE_DIR, |
1263 self.plugin_parent._on_component_create_dir, | 1309 self.plugin_parent._on_component_create_dir, |
1264 client=self.parent | 1310 client=self.parent, |
1265 ) | 1311 ) |
1266 else: | 1312 else: |
1267 self.xmlstream.addObserver( | 1313 self.xmlstream.addObserver( |
1268 IQ_FIS_REQUEST, self.plugin_parent.on_request, client=self.parent | 1314 IQ_FIS_REQUEST, self.plugin_parent.on_request, client=self.parent |
1269 ) | 1315 ) |