def _Paste(self): try: raw_text = HG.client_controller.GetClipboardText() except HydrusExceptions.DataMissing as e: QW.QMessageBox.critical(self, 'Error', str(e)) return try: texts = [ text for text in HydrusText.DeserialiseNewlinedTexts(raw_text) ] if not self._allow_empty_input: texts = [text for text in texts if text != ''] if len(texts) > 0: self._add_callable(texts) except: QW.QMessageBox.critical( self, 'Error', 'I could not understand what was in the clipboard')
def GetExternalIP(): if HydrusData.TimeHasPassed(EXTERNAL_IP['time'] + (3600 * 24)): cmd = [UPNPC_PATH, '-l'] sbp_kwargs = HydrusData.GetSubprocessKWArgs(text=True) HydrusData.CheckProgramIsNotShuttingDown() try: p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **sbp_kwargs) except FileNotFoundError: RaiseMissingUPnPcError('fetch external IP') HydrusData.WaitForProcessToFinish(p, 30) (stdout, stderr) = HydrusThreading.SubprocessCommunicate(p) if stderr is not None and len(stderr) > 0: raise Exception( 'Problem while trying to fetch External IP (if it says No IGD UPnP Device, you are either on a VPN or your router does not seem to support UPnP):' + os.linesep * 2 + str(stderr)) else: try: lines = HydrusText.DeserialiseNewlinedTexts(stdout) i = lines.index( 'i protocol exPort->inAddr:inPort description remoteHost leaseTime' ) # ExternalIPAddress = ip (gumpf, external_ip_address) = lines[i - 1].split(' = ') except ValueError: raise Exception('Could not parse external IP!') if external_ip_address == '0.0.0.0': raise Exception( 'Your UPnP device returned your external IP as 0.0.0.0! Try rebooting it, or overwrite it in options!' ) EXTERNAL_IP['ip'] = external_ip_address EXTERNAL_IP['time'] = HydrusData.GetNow() return EXTERNAL_IP['ip']
def IsAlreadyRunning( db_path, instance ): path = os.path.join( db_path, instance + '_running' ) if os.path.exists( path ): with open( path, 'r', encoding = 'utf-8' ) as f: file_text = f.read() try: ( pid, create_time ) = HydrusText.DeserialiseNewlinedTexts( file_text ) pid = int( pid ) create_time = float( create_time ) except ValueError: return False try: me = psutil.Process() if me.pid == pid and me.create_time() == create_time: # this is me! there is no conflict, lol! # this happens when a linux process restarts with os.execl(), for instance (unlike Windows, it keeps its pid) return False if psutil.pid_exists( pid ): p = psutil.Process( pid ) if p.create_time() == create_time and p.is_running(): return True except psutil.Error: return False return False
def GetExternalIP(): if HydrusData.TimeHasPassed(EXTERNAL_IP['time'] + (3600 * 24)): cmd = [upnpc_path, '-l'] sbp_kwargs = HydrusData.GetSubprocessKWArgs(text=True) p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **sbp_kwargs) HydrusData.WaitForProcessToFinish(p, 30) (stdout, stderr) = p.communicate() if stderr is not None and len(stderr) > 0: raise Exception('Problem while trying to fetch External IP:' + os.linesep * 2 + str(stderr)) else: try: lines = HydrusText.DeserialiseNewlinedTexts(stdout) i = lines.index( 'i protocol exPort->inAddr:inPort description remoteHost leaseTime' ) # ExternalIPAddress = ip (gumpf, external_ip_address) = lines[i - 1].split(' = ') except ValueError: raise Exception('Could not parse external IP!') if external_ip_address == '0.0.0.0': raise Exception( 'Your UPnP device returned your external IP as 0.0.0.0! Try rebooting it, or overwrite it in options!' ) EXTERNAL_IP['ip'] = external_ip_address EXTERNAL_IP['time'] = HydrusData.GetNow() return EXTERNAL_IP['ip']
def GetSiblingProcessPorts( db_path, instance ): path = os.path.join( db_path, instance + '_running' ) if os.path.exists( path ): with open( path, 'r', encoding = 'utf-8' ) as f: file_text = f.read() try: ( pid, create_time ) = HydrusText.DeserialiseNewlinedTexts( file_text ) pid = int( pid ) create_time = float( create_time ) except ValueError: return None try: if psutil.pid_exists( pid ): ports = [] p = psutil.Process( pid ) for conn in p.connections(): if conn.status == 'LISTEN': ports.append( int( conn.laddr[1] ) ) return ports except psutil.Error: return None return None
def ParseHashesFromRawHexText(hash_type, hex_hashes_raw): hash_type_to_hex_length = { 'md5': 32, 'sha1': 40, 'sha256': 64, 'sha512': 128 } hex_hashes = HydrusText.DeserialiseNewlinedTexts(hex_hashes_raw) # convert md5:abcd to abcd hex_hashes = [hex_hash.split(':')[-1] for hex_hash in hex_hashes] hex_hashes = [HydrusText.HexFilter(hex_hash) for hex_hash in hex_hashes] expected_hex_length = hash_type_to_hex_length[hash_type] bad_hex_hashes = [ hex_hash for hex_hash in hex_hashes if len(hex_hash) != expected_hex_length ] if len(bad_hex_hashes): m = 'Sorry, {} hashes should have {} hex characters! These did not:'.format( hash_type, expected_hex_length) m += os.linesep * 2 m += os.linesep.join( ('{} ({} characters)'.format(bad_hex_hash, len(bad_hex_hash)) for bad_hex_hash in bad_hex_hashes)) raise Exception(m) hex_hashes = [ hex_hash for hex_hash in hex_hashes if len(hex_hash) % 2 == 0 ] hex_hashes = DedupeList(hex_hashes) hashes = tuple([bytes.fromhex(hex_hash) for hex_hash in hex_hashes]) return hashes
def _GetURLsFromURLsString(self, urls_string): urls = HydrusText.DeserialiseNewlinedTexts(urls_string) return urls
def GetUPnPMappings(): cmd = [upnpc_path, '-l'] sbp_kwargs = HydrusData.GetSubprocessKWArgs(text=True) HydrusData.CheckProgramIsNotShuttingDown() p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **sbp_kwargs) HydrusData.WaitForProcessToFinish(p, 30) (stdout, stderr) = HydrusThreading.SubprocessCommunicate(p) if stderr is not None and len(stderr) > 0: raise Exception('Problem while trying to fetch UPnP mappings:' + os.linesep * 2 + stderr) else: try: lines = HydrusText.DeserialiseNewlinedTexts(stdout) i = lines.index( 'i protocol exPort->inAddr:inPort description remoteHost leaseTime' ) data_lines = [] i += 1 while i < len(lines): if not lines[i][0] in (' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'): break data_lines.append(lines[i]) i += 1 processed_data = [] for line in data_lines: # 0 UDP 65533->192.168.0.197:65533 'Skype UDP at 192.168.0.197:65533 (2665)' '' 0 while ' ' in line: line = line.replace(' ', ' ') if line.startswith(' '): (empty, number, protocol, mapping_data, rest_of_line) = line.split(' ', 4) else: (number, protocol, mapping_data, rest_of_line) = line.split(' ', 3) (external_port, rest_of_mapping_data) = mapping_data.split('->') external_port = int(external_port) if rest_of_mapping_data.count(':') == 1: (internal_client, internal_port) = rest_of_mapping_data.split(':') else: parts = rest_of_mapping_data.split(':') internal_port = parts.pop(-1) internal_client = ':'.join(parts) internal_port = int(internal_port) (empty, description, space, remote_host, rest_of_line) = rest_of_line.split('\'', 4) lease_time = int(rest_of_line[1:]) processed_data.append( (description, internal_client, internal_port, external_port, protocol, lease_time)) return processed_data except Exception as e: HydrusData.Print('UPnP problem:') HydrusData.Print(traceback.format_exc()) HydrusData.Print('Full response follows:') HydrusData.Print(stdout) raise Exception('Problem while trying to parse UPnP mappings:' + os.linesep * 2 + str(e))
def _GetSourcesFromSourcesString(self, sources_string): sources = HydrusText.DeserialiseNewlinedTexts(sources_string) return sources
def GetTags(self, service_key, path): tags = set() tags.update(self._tags_for_all) if self._load_from_neighbouring_txt_files: txt_path = path + '.txt' if os.path.exists(txt_path): try: with open(txt_path, 'r', encoding='utf-8') as f: txt_tags_string = f.read() except: HydrusData.ShowText('Could not parse the tags from ' + txt_path + '!') tags.add( '___had problem reading .txt file--is it not in utf-8?' ) try: txt_tags = [ tag for tag in HydrusText.DeserialiseNewlinedTexts( txt_tags_string) ] if True in (len(txt_tag) > 1024 for txt_tag in txt_tags): HydrusData.ShowText( 'Tags were too long--I think this was not a regular text file!' ) raise Exception() tags.update(txt_tags) except: HydrusData.ShowText('Could not parse the tags from ' + txt_path + '!') tags.add('___had problem parsing .txt file') (base, filename) = os.path.split(path) (filename, any_ext_gumpf) = os.path.splitext(filename) (filename_boolean, filename_namespace) = self._add_filename if filename_boolean: if filename_namespace != '': tag = filename_namespace + ':' + filename else: tag = filename tags.add(tag) (drive, directories) = os.path.splitdrive(base) while directories.startswith(os.path.sep): directories = directories[1:] directories = directories.split(os.path.sep) for (index, (dir_boolean, dir_namespace)) in list(self._directories_dict.items()): # we are talking -3 through 2 here if not dir_boolean: continue try: directory = directories[index] except IndexError: continue if dir_namespace != '': tag = dir_namespace + ':' + directory else: tag = directory tags.add(tag) # for regex in self._regexes: try: result = re.findall(regex, path) for match in result: if isinstance(match, tuple): for submatch in match: tags.add(submatch) else: tags.add(match) except: pass for (namespace, regex) in self._quick_namespaces: try: result = re.findall(regex, path) for match in result: if isinstance(match, tuple): for submatch in match: tags.add(namespace + ':' + submatch) else: tags.add(namespace + ':' + match) except: pass # tags = HydrusTags.CleanTags(tags) tags = HG.client_controller.tag_display_manager.FilterTags( ClientTags.TAG_DISPLAY_STORAGE, service_key, tags) return tags
def OnData( self, mime_data, result ): media_dnd = isinstance( mime_data, QMimeDataHydrusFiles ) urls_dnd = mime_data.hasUrls() text_dnd = mime_data.hasText() if media_dnd and self._media_callable is not None: result = mime_data.hydrusFiles() if result is not None: ( page_key, hashes ) = result if page_key is not None: QP.CallAfter( self._media_callable, page_key, hashes ) # callafter so we can terminate dnd event now result = QC.Qt.MoveAction # old way of doing it that messed up discord et al ''' elif mime_data.formats().count( 'application/hydrus-media' ) and self._media_callable is not None: mview = mime_data.data( 'application/hydrus-media' ) data_bytes = mview.data() data_str = str( data_bytes, 'utf-8' ) (encoded_page_key, encoded_hashes) = json.loads( data_str ) if encoded_page_key is not None: page_key = bytes.fromhex( encoded_page_key ) hashes = [ bytes.fromhex( encoded_hash ) for encoded_hash in encoded_hashes ] QP.CallAfter( self._media_callable, page_key, hashes ) # callafter so we can terminate dnd event now result = QC.Qt.MoveAction ''' elif urls_dnd or text_dnd: paths = [] urls = [] if urls_dnd: dnd_items = mime_data.urls() for dnd_item in dnd_items: if dnd_item.isLocalFile(): paths.append( os.path.normpath( dnd_item.toLocalFile() ) ) else: urls.append( dnd_item.url() ) else: text = mime_data.text() text_lines = HydrusText.DeserialiseNewlinedTexts( text ) for text_line in text_lines: if text_line.startswith( 'http' ): urls.append( text_line ) # ignore 'paths' if self._filenames_callable is not None: if len( paths ) > 0: QP.CallAfter( self._filenames_callable, paths ) # callafter to terminate dnd event now if self._url_callable is not None: if len( urls ) > 0: for url in urls: # https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs # data:image/png;base64,(data) # so what I prob have to do here is parse the file, decode from base64 or whatever, and then write to a fresh temp location and call self._filenames_callable # but I need to figure out a way to reproduce this on my own. Chrome is supposed to do it on image DnD, but didn't for me if url.startswith( 'data:' ) or len( url ) > 8 * 1024: HydrusData.ShowText( 'This drag and drop was in the unsupported \'Data URL\' format. hydev would like to know more about this so he can fix it.' ) continue QP.CallAfter( self._url_callable, url ) # callafter to terminate dnd event now result = QC.Qt.IgnoreAction else: result = QC.Qt.IgnoreAction return result
def GetUPnPMappingsParseResponse(stdout): try: lines = HydrusText.DeserialiseNewlinedTexts(stdout) i = lines.index( 'i protocol exPort->inAddr:inPort description remoteHost leaseTime' ) data_lines = [] i += 1 while i < len(lines): if not lines[i][0] in (' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'): break data_lines.append(lines[i]) i += 1 processed_data = [] for line in data_lines: # 0 UDP 65533->192.168.0.197:65533 'Skype UDP at 192.168.0.197:65533 (2665)' '' 0 while ' ' in line: line = line.replace(' ', ' ') if line.startswith(' '): (empty, number, protocol, mapping_data, rest_of_line) = line.split(' ', 4) else: (number, protocol, mapping_data, rest_of_line) = line.split(' ', 3) (external_port, rest_of_mapping_data) = mapping_data.split('->') external_port = int(external_port) if rest_of_mapping_data.count(':') == 1: (internal_client, internal_port) = rest_of_mapping_data.split(':') else: parts = rest_of_mapping_data.split(':') internal_port = parts.pop(-1) internal_client = ':'.join(parts) internal_port = int(internal_port) (empty, description, space, remote_host, rest_of_line) = rest_of_line.split('\'', 4) lease_time = int(rest_of_line[1:]) processed_data.append((description, internal_client, internal_port, external_port, protocol, lease_time)) return processed_data except Exception as e: HydrusData.Print('UPnP problem:') HydrusData.Print(traceback.format_exc()) HydrusData.Print('Full response follows:') HydrusData.Print(stdout) raise Exception('Problem while trying to parse UPnP mappings:' + os.linesep * 2 + str(e))
def OnData(self, mime_data, result): media_dnd = isinstance(mime_data, QMimeDataHydrusFiles) urls_dnd = mime_data.hasUrls() text_dnd = mime_data.hasText() if media_dnd and self._media_callable is not None: result = mime_data.hydrusFiles() if result is not None: (page_key, hashes) = result if page_key is not None: QP.CallAfter( self._media_callable, page_key, hashes) # callafter so we can terminate dnd event now result = QC.Qt.MoveAction # old way of doing it that messed up discord et al ''' elif mime_data.formats().count( 'application/hydrus-media' ) and self._media_callable is not None: mview = mime_data.data( 'application/hydrus-media' ) data_bytes = mview.data() data_str = str( data_bytes, 'utf-8' ) (encoded_page_key, encoded_hashes) = json.loads( data_str ) if encoded_page_key is not None: page_key = bytes.fromhex( encoded_page_key ) hashes = [ bytes.fromhex( encoded_hash ) for encoded_hash in encoded_hashes ] QP.CallAfter( self._media_callable, page_key, hashes ) # callafter so we can terminate dnd event now result = QC.Qt.MoveAction ''' elif urls_dnd or text_dnd: paths = [] urls = [] if urls_dnd: dnd_items = mime_data.urls() for dnd_item in dnd_items: if dnd_item.isLocalFile(): paths.append(os.path.normpath(dnd_item.toLocalFile())) else: urls.append(dnd_item.url()) else: text = mime_data.text() text_lines = HydrusText.DeserialiseNewlinedTexts(text) for text_line in text_lines: if text_line.startswith('http'): urls.append(text_line) # ignore 'paths' if self._filenames_callable is not None: if len(paths) > 0: QP.CallAfter(self._filenames_callable, paths) # callafter to terminate dnd event now if self._url_callable is not None: if len(urls) > 0: for url in urls: QP.CallAfter( self._url_callable, url) # callafter to terminate dnd event now result = QC.Qt.IgnoreAction else: result = QC.Qt.IgnoreAction return result