def download_collection(self, id, register_name): """Download a collection given its ID. For zip collection, we will download the zip, and extract the collection to collections dir. :param id: The ID of the collection. :type id: str :param register_name: The register name of the collection (the section name of the collection) :type register_name: unicode """ # Download the zip first collection_path = 'collections/%s.zip' % register_name network_manager = NetworkManager(self.file_url(collection_path)) status, description = network_manager.fetch() if not status: return False, description # Create the zip file zip_file = QTemporaryFile() if zip_file.open(): zip_file.write(network_manager.content) zip_file.close() zf = ZipFile(zip_file.fileName()) zf.extractall(path=local_collection_path(id)) return True, None
def fetch_online_directories(self): """Fetch online directory of repositories.""" downloader = NetworkManager(self.DIRECTORY_URL) status, _ = downloader.fetch() if status: directory_file = QTemporaryFile() if directory_file.open(): directory_file.write(downloader.content) directory_file.close() with open(directory_file.fileName()) as csv_file: reader = csv.DictReader(csv_file, fieldnames=('name', 'url')) for row in reader: self._online_directories[row['name']] = row['url'].strip() # Save it to cache settings = QSettings() settings.beginGroup(repo_settings_group()) settings.setValue('online_directories', self._online_directories) settings.endGroup() else: # Just use cache from previous use settings = QSettings() settings.beginGroup(repo_settings_group()) self._online_directories = settings.value('online_directories', {}) settings.endGroup()
def display_downloaded_content(self): """ Called when an unsupported content type is finished downloading. """ file_path = QDir.toNativeSeparators(QDir.tempPath() + "/XXXXXX_" + self.content_filename) myfile = QTemporaryFile(file_path) myfile.setAutoRemove(False) if (myfile.open()): myfile.write(self.reply.readAll()) myfile.close() subprocess.Popen([self.content_handlers.get(str(self.content_type)), myfile.fileName()]) #Sometimes downloading files opens an empty window. #So if the current window has no URL, close it. if(str(self.url().toString()) in ('', 'about:blank')): self.close()
def parse_metadata(self): """Parse str metadata to collection dict.""" if not self.metadata: msg = 'The metadata content is None' LOGGER.error(msg) raise MetadataError(msg) collections = [] metadata_file = QTemporaryFile() if metadata_file.open(): metadata_file.write(self.metadata) metadata_file.close() try: parser = SafeConfigParser() metadata_path = metadata_file.fileName() with codecs.open(metadata_path, 'r', encoding='utf-8') as f: parser.readfp(f) collections_str = parser.get('general', 'collections') except Exception as e: raise MetadataError('Error parsing metadata: %s' % e) collection_list = [ collection.strip() for collection in collections_str.split(',') ] # Read all the collections for collection in collection_list: # Parse the version qgis_min_version = parser.has_option( collection, 'qgis_minimum_version') and parser.get( collection, 'qgis_minimum_version') or None qgis_max_version = parser.has_option( collection, 'qgis_maximum_version') and parser.get( collection, 'qgis_maximum_version') or None if not qgis_min_version: qgis_min_version = '2.0' if not qgis_max_version: qgis_max_version = '3.99' if not isCompatible(QGis.QGIS_VERSION, qgis_min_version, qgis_max_version): LOGGER.info( 'Collection %s is not compatible with current QGIS ' 'version. QGIS ver:%s, QGIS min ver:%s, QGIS max ver: ' '%s' % (collection, QGis.QGIS_VERSION, qgis_min_version, qgis_max_version)) break # Collection is compatible, continue parsing try: # Parse general information author = parser.get(collection, 'author') email = parser.get(collection, 'email') name = parser.get(collection, 'name') tags = parser.get(collection, 'tags') description = parser.get(collection, 'description') # Parse licensing stuffs license_str = parser.has_option( collection, 'license') and parser.get( collection, 'license') or None license_path = parser.has_option( collection, 'license_file') and parser.get( collection, 'license_file') or None license_url = None if license_path: license_url = self.collection_file_url( collection, license_path.strip()) # Parse the preview urls preview_str = parser.has_option(collection, 'preview') and \ parser.get(collection, 'preview') or '' preview_list = [] for preview in preview_str.split(','): if preview.strip() != '': preview_url = self.collection_file_url( collection, preview.strip()) preview_list.append(preview_url) except Exception as e: raise MetadataError('Error parsing metadata: %s' % e) collection_dict = { 'register_name': collection, 'author': author, 'author_email': email, 'repository_url': self.url, 'status': COLLECTION_NOT_INSTALLED_STATUS, 'name': name, 'tags': tags, 'description': description, 'qgis_min_version': qgis_min_version, 'qgis_max_version': qgis_max_version, 'preview': preview_list, 'license': license_str, 'license_url': license_url } collections.append(collection_dict) return collections
class DocumentSharingStream(MSRPStreamBase): type = 'document-sharing' priority = 1 msrp_session_class = MSRPSession media_type = 'application' accept_types = ['application/x-webodf-documentsharing', 'application/x-webodf-genesisdocument'] accept_wrapped_types = None def __init__(self, filename = None, document_title = None, session_uuid = None, continue_session = None): super(DocumentSharingStream, self).__init__() self.notification_center = NotificationCenter() self.mode = continue_session if continue_session is not None else 'guest' if filename is None else 'host' self.filename = filename if session_uuid is None: session_uuid = str(uuid.uuid4()) self.session_uuid = session_uuid self.continue_session = continue_session self.document_title = document_title if document_title is not None else os.path.basename(filename) if filename is not None else None self.receivedGenesisFile = None self.genesisFileSender = None print "NEW DocumentSharingStream - filename: ", self.filename, "session_uuid: ", self.session_uuid, "continue_session: ", self.continue_session @classmethod def new_from_sdp(cls, session, remote_sdp, stream_index): remote_stream = remote_sdp.media[stream_index] if remote_stream.media != 'application': raise UnknownStreamError remote_accept_types = remote_stream.attributes.getfirst('accept-types', None) if remote_accept_types is None: raise InvalidStreamError("remote SDP media does not have 'accept-types' attribute") if 'application/x-webodf-documentsharing' not in remote_accept_types.split(): # TODO: check both needed mimetypes raise InvalidStreamError("no compatible media types found") expected_transport = 'TCP/TLS/MSRP' if session.account.msrp.transport=='tls' else 'TCP/MSRP' if remote_stream.transport != expected_transport: raise InvalidStreamError("expected %s transport in chat stream, got %s" % (expected_transport, remote_stream.transport)) if remote_stream.formats != ['*']: raise InvalidStreamError("wrong format list specified") document_title = remote_stream.attributes.getfirst('document-title', None) session_uuid = remote_stream.attributes.getfirst('docsession-uuid', None) continue_session = remote_stream.attributes.getfirst('docsession-continue', None) # revert on reception side if continue_session == "host": continue_session = "guest" elif continue_session == "guest": continue_session = "host" return cls(filename = None, document_title = document_title, session_uuid = session_uuid, continue_session = continue_session) def _create_local_media(self, uri_path): local_media = super(DocumentSharingStream, self)._create_local_media(uri_path) # TODO: .encode('utf8') only works with filenames with latin1 chars, investigate proper fix local_media.attributes.append(SDPAttribute('document-title', self.document_title.encode('utf8'))) local_media.attributes.append(SDPAttribute('docsession-uuid', self.session_uuid)) if self.continue_session is not None: local_media.attributes.append(SDPAttribute('docsession-continue', self.continue_session)) return local_media def _handle_SEND(self, chunk): if chunk.size == 0: # keep-alive self.msrp_session.send_report(chunk, 200, 'OK') return if chunk.content_type not in self.accept_types: self.msrp_session.send_report(chunk, 415, 'Invalid content-type') return if chunk.content_type == 'application/x-webodf-genesisdocument': if self.receivedGenesisFile is None: print "------- creating file for genesis" self.receivedGenesisFile = QTemporaryFile() self.receivedGenesisFile.open() fro, to, total = chunk.byte_range print "------- got x-webodf-genesisdocument - fro, to, total:", fro, to, total self.receivedGenesisFile.seek(fro-1) self.receivedGenesisFile.write(chunk.data) if fro+chunk.size-1 == total: print "------- got x-webodf-genesisdocument - complete, size:", fro+chunk.size-1 self.receivedGenesisFile.flush() ndata = NotificationData(filename = self.receivedGenesisFile.fileName()) self.notification_center.post_notification('DocumentSharingStreamGenesisDocument', sender = self, data = ndata) return self.msrp_session.send_report(chunk, 200, 'OK') message = cjson.decode(chunk.data) messageType = message['type'] messageBody = message['body'] print "------- got x-webodf-documentsharing:", messageType if messageType == 'InitRequest': ndata = NotificationData(content = messageBody) self.notification_center.post_notification('DocumentSharingStreamInitRequest', sender = self, data = ndata) return if messageType == 'InitRequestReply': ndata = NotificationData(content = messageBody) self.notification_center.post_notification('DocumentSharingStreamInitRequestReply', sender = self, data = ndata) return if messageType == 'ReplayRequest': ndata = NotificationData(content = messageBody) self.notification_center.post_notification('DocumentSharingStreamReplayRequest', sender = self, data = ndata) return if messageType == 'ReplayRequestReply': ndata = NotificationData(content = messageBody) self.notification_center.post_notification('DocumentSharingStreamReplayRequestReply', sender = self, data = ndata) return if messageType == 'error': ndata = NotificationData(content = messageBody['error']) self.notification_center.post_notification('DocumentSharingStreamError', sender = self, data = ndata) return if messageType == 'NewOps': ndata = NotificationData(content = messageBody, content_type = chunk.content_type) self.notification_center.post_notification('DocumentSharingStreamNewOps', sender = self, data = ndata) if messageType == 'NewOpsReply': ndata = NotificationData(content = messageBody) self.notification_center.post_notification('DocumentSharingStreamNewOpsReply', sender = self, data = ndata) def _handle_REPORT(self, chunk): if self.genesisFileSender: self.genesisFileSender.handleReportChunk(chunk) def _dropGenesisFileSender(self): # thanks for all the file, and bye self.notification_center.remove_observer(self, sender=self.genesisFileSender) self.genesisFileSender = None @run_in_green_thread def sendMessage(self, messageType, messageBody): print "------- sendMessage:", messageType if self.msrp_session: message = { 'type': messageType, 'body': messageBody } message = cjson.encode(message) self.msrp_session.send_message(message, 'application/x-webodf-documentsharing') @run_in_green_thread def sendGenesisFile(self, filename): print "------- sendGenesisFile:", filename if self.msrp_session: self.genesisFileSender = GenesisFileSender(filename, self.msrp_session, self.msrp) self.notification_center.add_observer(self, sender=self.genesisFileSender) self.genesisFileSender.startFileSending() def _NH_MediaStreamDidStart(self, notification): self.notification_center.post_notification('DocumentSharingStreamConnected', sender = self) def _NH_MediaStreamDidFail(self, notification): if self.genesisFileSender: self.genesisFileSender.end() self._dropGenesisFileSender() self.notification_center.post_notification('DocumentSharingStreamDisconnected', sender = self) def _NH_MediaStreamDidEnd(self, notification): if self.genesisFileSender: self.genesisFileSender.end() self._dropGenesisFileSender() self.notification_center.post_notification('DocumentSharingStreamDisconnected', sender = self) @run_in_twisted_thread def _NH_FileTransferHandlerDidEnd(self, notification): self._dropGenesisFileSender() @run_in_twisted_thread def _NH_FileTransferHandlerError(self, notification): self._failure_reason = notification.data.error notification.center.post_notification('MediaStreamDidFail', sender=self, data=NotificationData(context='transferring', reason=self._failure_reason))