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')
예제 #2
0
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']
예제 #3
0
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
예제 #4
0
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']
예제 #5
0
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
예제 #6
0
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
예제 #7
0
    def _GetURLsFromURLsString(self, urls_string):

        urls = HydrusText.DeserialiseNewlinedTexts(urls_string)

        return urls
예제 #8
0
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
예제 #10
0
    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
예제 #11
0
    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
예제 #12
0
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))
예제 #13
0
    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