Exemplo n.º 1
0
 def _checkUserAgent( self, request ):
     
     request.is_hydrus_user_agent = False
     
     if request.requestHeaders.hasHeader( 'User-Agent' ):
         
         user_agent_texts = request.requestHeaders.getRawHeaders( 'User-Agent' )
         
         user_agent_text = user_agent_texts[0]
         
         try:
             
             user_agents = user_agent_text.split( ' ' )
             
         except: return # crazy user agent string, so just assume not a hydrus client
         
         for user_agent in user_agents:
             
             if '/' in user_agent:
                 
                 ( client, network_version ) = user_agent.split( '/', 1 )
                 
                 if client == 'hydrus':
                     
                     request.is_hydrus_user_agent = True
                     
                     network_version = int( network_version )
                     
                     if network_version == HC.NETWORK_VERSION: return
                     else:
                         
                         if network_version < HC.NETWORK_VERSION: message = 'Your client is out of date; please download the latest release.'
                         else: message = 'This server is out of date; please ask its admin to update to the latest release.'
                         
                         raise HydrusExceptions.NetworkVersionException( 'Network version mismatch! This server\'s network version is ' + str( HC.NETWORK_VERSION ) + ', whereas your client\'s is ' + str( network_version ) + '! ' + message )
Exemplo n.º 2
0
def CheckHydrusVersion(service_key, service_type, response_headers):

    service_string = HC.service_string_lookup[service_type]

    if 'server' not in response_headers or service_string not in response_headers[
            'server']:

        HC.app.Write(
            'service_updates', {
                service_key: [
                    HC.ServiceUpdate(HC.SERVICE_UPDATE_ACCOUNT,
                                     HC.GetUnknownAccount())
                ]
            })

        raise HydrusExceptions.WrongServiceTypeException('Target was not a ' +
                                                         service_string + '!')

    server_header = response_headers['server']

    (service_string_gumpf, network_version) = server_header.split('/')

    network_version = int(network_version)

    if network_version != HC.NETWORK_VERSION:

        if network_version > HC.NETWORK_VERSION:
            message = 'Your client is out of date; please download the latest release.'
        else:
            message = 'The server is out of date; please ask its admin to update to the latest release.'

        raise HydrusExceptions.NetworkVersionException(
            'Network version mismatch! The server\'s network version was ' +
            u(network_version) + ', whereas your client\'s is ' +
            u(HC.NETWORK_VERSION) + '! ' + message)
Exemplo n.º 3
0
    def _CheckHydrusVersion(self, service_type, response):

        service_string = HC.service_string_lookup[service_type]

        headers = response.headers

        if 'server' not in headers or service_string not in headers['server']:

            raise HydrusExceptions.WrongServiceTypeException(
                'Target was not a ' + service_string + '!')

        server_header = headers['server']

        (service_string_gumpf, network_version) = server_header.split('/')

        network_version = int(network_version)

        if network_version != HC.NETWORK_VERSION:

            if network_version > HC.NETWORK_VERSION:

                message = 'Your client is out of date; please download the latest release.'

            else:

                message = 'The server is out of date; please ask its admin to update to the latest release.'

            raise HydrusExceptions.NetworkVersionException(
                'Network version mismatch! The server\'s network version was '
                + str(network_version) + ', whereas your client\'s is ' +
                str(HC.NETWORK_VERSION) + '! ' + message)
Exemplo n.º 4
0
 def _check_network_version( self, network_version ):
     
     if network_version != HC.NETWORK_VERSION:
         
         if network_version < HC.NETWORK_VERSION: message = 'Your client is out of date; please download the latest release.'
         else: message = 'This server is out of date; please ask its admin to update to the latest release.'
         
         message = 'Network version mismatch! This server\'s network version is ' + HC.u( HC.NETWORK_VERSION ) + ', whereas your client\'s is ' + HC.u( network_version ) + '! ' + message
         
         raise HydrusExceptions.NetworkVersionException( message )
Exemplo n.º 5
0
 def Request( self, method, path_and_query, request_headers, body, report_hooks = None, temp_path = None ):
     
     if report_hooks is None: report_hooks = []
     
     if method == HC.GET: method_string = 'GET'
     elif method == HC.POST: method_string = 'POST'
     
     if 'User-Agent' not in request_headers:
         
         request_headers[ 'User-Agent' ] = 'hydrus/' + str( HC.NETWORK_VERSION )
         
     
     path_and_query = HydrusData.ToByteString( path_and_query )
     
     request_headers = { str( k ) : str( v ) for ( k, v ) in request_headers.items() }
     
     response = self._GetResponse( method_string, path_and_query, request_headers, body )
     
     ( parsed_response, size_of_response ) = self._ReadResponse( response, report_hooks, temp_path )
     
     response_headers = { k : v for ( k, v ) in response.getheaders() if k != 'set-cookie' }
     
     cookies = self._ParseCookies( response.getheader( 'set-cookie' ) )
     
     self._last_request_time = HydrusData.GetNow()
     
     if response.status == 200:
         
         return ( parsed_response, None, size_of_response, response_headers, cookies )
         
     elif response.status in ( 301, 302, 303, 307 ):
         
         location = response.getheader( 'Location' )
         
         if location is None: raise Exception( 'Received an invalid redirection response.' )
         else:
             
             url = location
             
             if ', ' in url:
                 
                 url = url.split( ', ' )[0]
                 
             elif ' ' in url:
                 
                 # some booru is giving daft redirect responses
                 HydrusData.Print( url )
                 url = urllib.quote( HydrusData.ToByteString( url ), safe = '/?=&' )
                 HydrusData.Print( url )
                 
             
             if not url.startswith( self._scheme ):
                 
                 # assume it is like 'index.php' or '/index.php', rather than 'http://blah.com/index.php'
                 
                 if url.startswith( '/' ): slash_sep = ''
                 else: slash_sep = '/'
                 
                 url = self._scheme + '://' + self._host + slash_sep + url
                 
             
             if response.status in ( 301, 307 ):
                 
                 # 301: moved permanently, repeat request
                 # 307: moved temporarily, repeat request
                 
                 redirect_info = ( method, url )
                 
             elif response.status in ( 302, 303 ):
                 
                 # 302: moved temporarily, repeat request (except everyone treats it like 303 for no good f*****g reason)
                 # 303: thanks, now go here with GET
                 
                 redirect_info = ( HC.GET, url )
                 
             
             return ( parsed_response, redirect_info, size_of_response, response_headers, cookies )
             
         
     elif response.status == 304: raise HydrusExceptions.NotModifiedException()
     else:
         
         if response.status == 401: raise HydrusExceptions.PermissionException( parsed_response )
         elif response.status == 403: raise HydrusExceptions.ForbiddenException( parsed_response )
         elif response.status == 404: raise HydrusExceptions.NotFoundException( parsed_response )
         elif response.status == 419: raise HydrusExceptions.SessionException( parsed_response )
         elif response.status == 426: raise HydrusExceptions.NetworkVersionException( parsed_response )
         elif response.status in ( 500, 501, 502, 503 ):
             
             server_header = response.getheader( 'Server' )
             
             if server_header is not None and 'hydrus' in server_header:
                 
                 hydrus_service = True
                 
             else:
                 
                 hydrus_service = False
                 
             
             if response.status == 503 and hydrus_service:
                 
                 raise HydrusExceptions.ServerBusyException( 'Server is busy, please try again later.' )
                 
             else:
                 
                 raise Exception( parsed_response )
                 
             
         else: raise Exception( parsed_response )
Exemplo n.º 6
0
 def _ParseResponse( self, response, report_hooks ):
     
     server_header = response.getheader( 'Server' )
     
     if server_header is not None and 'hydrus' in server_header:
         
         hydrus_service = True
         
     else:
         
         hydrus_service = False
         
     
     content_length = response.getheader( 'Content-Length' )
     
     if content_length is not None:
         
         content_length = int( content_length )
         
         for hook in report_hooks:
             
             hook( content_length, 0 )
             
         
     
     data = ''
     
     for block in HydrusPaths.ReadFileLikeAsBlocks( response ):
         
         if HydrusGlobals.model_shutdown:
             
             raise HydrusExceptions.ShutdownException( 'Application is shutting down!' )
             
         
         data += block
         
         if content_length is not None:
             
             for hook in report_hooks:
                 
                 hook( content_length, len( data ) )
                 
             
             if len( data ) > content_length:
                 
                 raise Exception( 'Response was longer than suggested!' )
                 
             
         
     
     size_of_response = len( data )
     
     content_type = response.getheader( 'Content-Type' )
     
     if content_type is None: parsed_response = data
     else:
         
         if '; ' in content_type: ( mime_string, additional_info ) = content_type.split( '; ', 1 )
         else: ( mime_string, additional_info ) = ( content_type, '' )
         
         if 'charset=' in additional_info:
     
             # this does utf-8, ISO-8859-4, whatever
             
             ( gumpf, charset ) = additional_info.split( '=' )
             
             try: parsed_response = data.decode( charset )
             except: parsed_response = data
             
         elif content_type == 'application/x-yaml':
             
             try: parsed_response = yaml.safe_load( data )
             except yaml.error.YAMLError as e:
                 
                 raise HydrusExceptions.NetworkVersionException( 'Failed to parse a response object!' + os.linesep + HydrusData.ToUnicode( e ) )
                 
             
         elif content_type == 'application/json':
             
             if hydrus_service:
                 
                 parsed_response = HydrusSerialisable.CreateFromNetworkString( data )
                 
             else:
                 
                 parsed_response = data
                 
             
         elif content_type == 'text/html':
             
             try: parsed_response = data.decode( 'utf-8' )
             except: parsed_response = data
             
         else: parsed_response = data
         
     
     return ( parsed_response, size_of_response )
Exemplo n.º 7
0
    def Request(self,
                method,
                path_and_query,
                request_headers,
                body,
                report_hooks=[],
                response_to_path=False):

        if method == HC.GET: method_string = 'GET'
        elif method == HC.POST: method_string = 'POST'

        if 'User-Agent' not in request_headers:
            request_headers['User-Agent'] = 'hydrus/' + HC.u(
                HC.NETWORK_VERSION)

        # it is important to only send str, not unicode, to httplib
        # it uses += to extend the message body, which propagates the unicode (and thus fails) when
        # you try to push non-ascii bytes as the body (e.g. during a file upload!)

        method_string = str(method_string)
        path_and_query = str(path_and_query)

        request_headers = {
            str(k): str(v)
            for (k, v) in request_headers.items()
        }

        try:

            self._connection.request(method_string,
                                     path_and_query,
                                     headers=request_headers,
                                     body=body)

            response = self._connection.getresponse()

        except (httplib.CannotSendRequest, httplib.BadStatusLine):

            # for some reason, we can't send a request on the current connection, so let's make a new one and try again!

            self._RefreshConnection()

            self._connection.request(method_string,
                                     path_and_query,
                                     headers=request_headers,
                                     body=body)

            response = self._connection.getresponse()

        if response.status == 200 and response_to_path:

            (temp_path, size_of_response) = self._WriteResponseToPath(
                response, report_hooks)

            parsed_response = temp_path

        else:

            (parsed_response,
             size_of_response) = self._ParseResponse(response, report_hooks)

        response_headers = {
            k: v
            for (k, v) in response.getheaders() if k != 'set-cookie'
        }

        cookies = self._ParseCookies(response.getheader('set-cookie'))

        self._last_request_time = HC.GetNow()

        if response.status == 200:
            return (parsed_response, None, size_of_response, response_headers,
                    cookies)
        elif response.status in (301, 302, 303, 307):

            location = response.getheader('Location')

            if location is None: raise Exception(parsed_response)
            else:

                url = location

                if ' ' in url:

                    # some booru is giving daft redirect responses
                    print(url)
                    url = urllib.quote(url, safe='/?=&')
                    print(url)

                if not url.startswith(self._scheme):

                    # assume it is like 'index.php' or '/index.php', rather than 'http://blah.com/index.php'

                    if url.startswith('/'): slash_sep = ''
                    else: slash_sep = '/'

                    url = self._scheme + '://' + self._host + slash_sep + url

                if response.status in (301, 307):

                    # 301: moved permanently, repeat request
                    # 307: moved temporarily, repeat request

                    redirect_info = (method, url)

                elif response.status in (302, 303):

                    # 302: moved temporarily, repeat request (except everyone treats it like 303 for no good f*****g reason)
                    # 303: thanks, now go here with GET

                    redirect_info = (HC.GET, url)

                return (parsed_response, redirect_info, size_of_response,
                        response_headers, cookies)

        elif response.status == 304:
            raise HydrusExceptions.NotModifiedException()
        else:

            if response.status == 401:
                raise HydrusExceptions.PermissionException(parsed_response)
            elif response.status == 403:
                raise HydrusExceptions.ForbiddenException(parsed_response)
            elif response.status == 404:
                raise HydrusExceptions.NotFoundException(parsed_response)
            elif response.status == 426:
                raise HydrusExceptions.NetworkVersionException(parsed_response)
            elif response.status in (500, 501, 502, 503):
                raise Exception(parsed_response)
            else:
                raise Exception(parsed_response)
Exemplo n.º 8
0
    def _ParseResponse(self, response, report_hooks):

        content_length = response.getheader('Content-Length')

        if content_length is not None: content_length = int(content_length)

        data = ''

        for block in HC.ReadFileLikeAsBlocks(response, self.read_block_size):

            if HC.shutdown: raise Exception('Application is shutting down!')

            data += block

            if content_length is not None and len(data) > content_length:

                raise Exception('Response was longer than suggested!')

            for hook in report_hooks:

                hook(content_length, len(data))

        size_of_response = len(data)

        content_type = response.getheader('Content-Type')

        if content_type is None: parsed_response = data
        else:

            if '; ' in content_type:
                (mime_string, additional_info) = content_type.split('; ', 1)
            else:
                (mime_string, additional_info) = (content_type, '')

            if 'charset=' in additional_info:

                # this does utf-8, ISO-8859-4, whatever

                (gumpf, charset) = additional_info.split('=')

                try:
                    parsed_response = data.decode(charset)
                except:
                    parsed_response = data

            elif content_type in HC.mime_enum_lookup and HC.mime_enum_lookup[
                    content_type] == HC.APPLICATION_YAML:

                try:
                    parsed_response = yaml.safe_load(data)
                except Exception as e:
                    raise HydrusExceptions.NetworkVersionException(
                        'Failed to parse a response object!' + os.linesep +
                        u(e))

            elif content_type == 'text/html':

                try:
                    parsed_response = data.decode('utf-8')
                except:
                    parsed_response = data

            else:
                parsed_response = data

        return (parsed_response, size_of_response)