示例#1
0
def redirect(http_request, factory_name, encrypted_password, request_id):
    """
    Redirect the browser to the requested URL for the screenshot, and
    save the browser in the database.
    """
    try:
        factory = get_object_or_404(Factory, name=factory_name)
        nonces.verify(http_request, factory, encrypted_password)
        request = get_object_or_404(Request, id=request_id)
        request.check_factory_lock(factory)
        user_agent = http_request.META['HTTP_USER_AGENT']
        try:
            browser = Browser.objects.get(
                factory=factory,
                user_agent=user_agent,
                active=True)
        except Browser.DoesNotExist:
            raise Fault(404, u"Unknown user agent: %s." % user_agent)
        # Check that the browser matches the request
        if (request.browser_group_id is not None and
            request.browser_group_id != browser.browser_group_id):
            raise Fault(409, u"Requested browser %s but got %s." %
                        (request.browser_group.name,
                         browser.browser_group.name))
        if ((request.major is not None and request.major != browser.major) or
            (request.minor is not None and request.minor != browser.minor)):
            raise Fault(409,
                u"Requested browser version %s.%s but got %s.%s." %
                (request.major, request.minor,
                 browser.major, browser.minor))
        # Update request with browser and redirect timestamp
        request.update_fields(browser=browser,
                              redirected=datetime.now())
        return HttpResponseRedirect(request.request_group.website.url)
    except Fault, fault:
        FactoryError.objects.create(factory=factory,
            code=fault.faultCode, message=fault.faultString)
        return error_page(http_request, "redirect error", fault.faultString)
示例#2
0
def redirect(http_request, factory_name, encrypted_password, request_id):
    """
    Redirect the browser to the requested URL for the screenshot, and
    save the browser in the database.
    """
    try:
        factory = get_object_or_404(Factory, name=factory_name)
        nonces.verify(http_request, factory, encrypted_password)
        request = get_object_or_404(Request, id=request_id)
        request.check_factory_lock(factory)
        user_agent = http_request.META['HTTP_USER_AGENT']
        try:
            browser = Browser.objects.get(
                factory=factory,
                user_agent=user_agent,
                active=True)
        except Browser.DoesNotExist:
            raise Fault(404, u"Unknown user agent: %s." % user_agent)
        # Check that the browser matches the request
        if (request.browser_group_id is not None and
            request.browser_group_id != browser.browser_group_id):
            raise Fault(409, u"Requested browser %s but got %s." %
                        (request.browser_group.name,
                         browser.browser_group.name))
        if ((request.major is not None and request.major != browser.major) or
            (request.minor is not None and request.minor != browser.minor)):
            raise Fault(409,
                u"Requested browser version %s.%s but got %s.%s." %
                (request.major, request.minor,
                 browser.major, browser.minor))
        # Update request with browser and redirect timestamp
        request.update_fields(browser=browser,
                              redirected=datetime.now())
        return HttpResponseRedirect(request.request_group.website.url)
    except Fault, fault:
        FactoryError.objects.create(factory=factory,
            code=fault.faultCode, message=fault.faultString)
        return error_page(http_request, "redirect error", fault.faultString)
示例#3
0
def poll(http_request, factory, encrypted_password):
    """
    Try to find a matching screenshot request for a given factory.

    Arguments
    ~~~~~~~~~
    * factory_name string (lowercase, normally from hostname)
    * encrypted_password string (lowercase hexadecimal, length 32)

    See nonces.verify for how to encrypt your password.

    Return value
    ~~~~~~~~~~~~
    * options dict (screenshot request configuration)

    If successful, the options dict will have the following keys:

    * request int (for redirect and screenshots.upload)
    * browser string (browser name)
    * version string (browser version)
    * major int (major browser version number)
    * minor int (minor browser version number)
    * command string (browser command to run, empty for default)
    * width int (screen width in pixels)
    * height int (screen height in pixels)
    * bpp int (color depth in bits per pixel)
    * javascript string (javascript version)
    * java string (java version)
    * flash string (flash version)

    Locking
    ~~~~~~~
    The matching screenshot request is locked for five minutes. This
    is to make sure that no requests are processed by two factories at
    the same time. If your factory takes longer to process a request,
    it is possible that somebody else will lock it. In this case, your
    upload will fail.
    """
    # Verify authentication
    nonces.verify(http_request, factory, encrypted_password)
    # Update last_poll timestamp
    factory.update_fields(last_poll=datetime.now(),
                          ip=http_request.META['REMOTE_ADDR'])
    if hasattr(settings, 'FACTORY_THROTTLE_INTERVAL'):
        if factory.name in settings.FACTORY_THROTTLE_INTERVAL:
            interval = settings.FACTORY_THROTTLE_INTERVAL[factory.name]
            if datetime.now() - factory.last_upload < interval:
                raise Fault(
                    205, ' '.join((
                        "Sorry, your screenshot factory is blocked for a few minutes.",
                        "Please check your email for error messages from Browsershots."
                    )))
    # Check server load
    randomized_load = max(os.getloadavg()) * random.random()
    if factory.operating_system.platform_id in PRIORITY_PLATFORMS:
        randomized_load /= 2
    if randomized_load > ACCEPTABLE_SERVER_LOAD:
        raise Fault(
            503,
            "The server is currently overloaded. Please try again in a minute."
        )
    # Get matching request
    request = find_and_lock_request(factory, factory.features_q())
    # Get matching browser
    filters = {
        'factory': factory,
        'browser_group': request.browser_group,
        'active': True
    }
    add_version(filters, request.major, 'major', exact=True)
    add_version(filters, request.minor, 'minor', exact=True)
    add_version(filters, request.request_group.javascript, 'javascript__id')
    add_version(filters, request.request_group.java, 'java__id')
    add_version(filters, request.request_group.flash, 'flash__id')
    try:
        browser = Browser.objects.select_related().get(**filters)
    except Browser.DoesNotExist:
        raise Fault(404, "No matching browser for selected request.")
    # Build result dict
    screen_size = select_screen_size(factory, request)
    color_depth = select_color_depth(factory, request)
    return {
        'request': request.id,
        'browser': browser.browser_group.name,
        'version': browser.version,
        'major': browser.major,
        'minor': browser.minor,
        'command': browser.command,
        'width': screen_size.width,
        'height': screen_size.height,
        'bpp': color_depth.bits_per_pixel,
        'javascript': version_or_empty(request.request_group.javascript),
        'java': version_or_empty(request.request_group.java),
        'flash': version_or_empty(request.request_group.flash),
    }
示例#4
0
def poll(http_request, factory, encrypted_password):
    """
    Try to find a matching screenshot request for a given factory.

    Arguments
    ~~~~~~~~~
    * factory_name string (lowercase, normally from hostname)
    * encrypted_password string (lowercase hexadecimal, length 32)

    See nonces.verify for how to encrypt your password.

    Return value
    ~~~~~~~~~~~~
    * options dict (screenshot request configuration)

    If successful, the options dict will have the following keys:

    * request int (for redirect and screenshots.upload)
    * browser string (browser name)
    * version string (browser version)
    * major int (major browser version number)
    * minor int (minor browser version number)
    * command string (browser command to run, empty for default)
    * width int (screen width in pixels)
    * height int (screen height in pixels)
    * bpp int (color depth in bits per pixel)
    * javascript string (javascript version)
    * java string (java version)
    * flash string (flash version)

    Locking
    ~~~~~~~
    The matching screenshot request is locked for five minutes. This
    is to make sure that no requests are processed by two factories at
    the same time. If your factory takes longer to process a request,
    it is possible that somebody else will lock it. In this case, your
    upload will fail.
    """
    # Verify authentication
    nonces.verify(http_request, factory, encrypted_password)
    # Update last_poll timestamp
    factory.update_fields(last_poll=datetime.now(),
                          ip=http_request.META['REMOTE_ADDR'])
    if hasattr(settings, 'FACTORY_THROTTLE_INTERVAL'):
        if factory.name in settings.FACTORY_THROTTLE_INTERVAL:
            interval = settings.FACTORY_THROTTLE_INTERVAL[factory.name]
            if datetime.now() - factory.last_upload < interval:
                raise Fault(205, ' '.join((
"Sorry, your screenshot factory is blocked for a few minutes.",
"Please check your email for error messages from Browsershots.")))
    # Check server load
    randomized_load = max(os.getloadavg()) * random.random()
    if factory.operating_system.platform_id in PRIORITY_PLATFORMS:
        randomized_load /= 2
    if randomized_load > ACCEPTABLE_SERVER_LOAD:
        raise Fault(503,
"The server is currently overloaded. Please try again in a minute.")
    # Get matching request
    request = find_and_lock_request(factory, factory.features_q())
    # Get matching browser
    filters = {'factory': factory,
               'browser_group': request.browser_group,
               'active': True}
    add_version(filters, request.major, 'major', exact=True)
    add_version(filters, request.minor, 'minor', exact=True)
    add_version(filters, request.request_group.javascript, 'javascript__id')
    add_version(filters, request.request_group.java, 'java__id')
    add_version(filters, request.request_group.flash, 'flash__id')
    try:
        browser = Browser.objects.select_related().get(**filters)
    except Browser.DoesNotExist:
        raise Fault(404, "No matching browser for selected request.")
    # Build result dict
    screen_size = select_screen_size(factory, request)
    color_depth = select_color_depth(factory, request)
    return {
        'request': request.id,
        'browser': browser.browser_group.name,
        'version': browser.version,
        'major': browser.major,
        'minor': browser.minor,
        'command': browser.command,
        'width': screen_size.width,
        'height': screen_size.height,
        'bpp': color_depth.bits_per_pixel,
        'javascript': version_or_empty(request.request_group.javascript),
        'java': version_or_empty(request.request_group.java),
        'flash': version_or_empty(request.request_group.flash),
        }
示例#5
0
def upload(http_request, factory, encrypted_password, request, screenshot):
    """
    Submit a multi-page screenshot as a lossless PNG file.

    Arguments
    ~~~~~~~~~
    * factory_name string (lowercase, normally from hostname)
    * encrypted_password string (lowercase hexadecimal, length 32)
    * request int (from requests.poll)
    * screenshot binary (BASE64-encoded PNG file)

    See nonces.verify for how to encrypt your password.

    Return value
    ~~~~~~~~~~~~
    * hashkey string (lowercase hexadecimal, length 32)

    Users can see the resulting uploaded screenshot at
    http://browsershots.org/screenshots/hashkey/
    """
    # Verify authentication
    nonces.verify(http_request, factory, encrypted_password)
    request_id = request
    request = get_or_fault(Request, pk=request_id)
    request_group = request.request_group
    # Make sure the request was locked by this factory
    request.check_factory_lock(factory)
    # Store and check screenshot file
    hashkey = storage.save_upload(screenshot)
    bytes = storage.png_filesize(hashkey)
    # Make sure the request was redirected by the browser
    browser = request.browser
    if browser is None or browser.factory_id != factory.id:
        guessed = factory.browser_set.filter(active=True,
            browser_group=request.browser_group,
            major=request.major, minor=request.minor)[:1]
        if not len(guessed):
            guessed = [None]
        raise ExtraFault(406,
            u"The browser has not visited the requested website.",
            request=request, hashkey=hashkey, browser=guessed[0])
    # Unpack PNG file and run more checks
    ppmname = storage.pngtoppm(hashkey)
    try:
        magic, width, height = storage.read_pnm_header(ppmname)
        if request_group.width and request_group.width != width:
            raise ExtraFault(412,
                u"The screenshot is %d pixels wide, not %d as requested." %
                (width, request_group.width),
                request=request, hashkey=hashkey, browser=browser)
        if height > width * 4:
            raise ExtraFault(413,
                u"The screenshot is too tall (more than 4 times the width).",
                request=request, hashkey=hashkey, browser=browser)
        if height < width / 2:
            raise ExtraFault(414,
                u"The screenshot is too short (less than half the width).",
                request=request, hashkey=hashkey, browser=browser)
        if os.path.exists('/usr/local/etc/pbmgrep'):
            check_ppm_problems(ppmname, request, hashkey, browser)
        # Make smaller preview images
        for size in PREVIEW_SIZES:
            storage.scale(ppmname, size, hashkey)
    finally:
        # Delete temporary PPM file
        os.unlink(ppmname)
    # Upload screenshots to Amazon S3 (but not for anonymous users)
    if hasattr(settings, 'S3_BUCKETS') and request_group.user_id is not None:
        storage.s3_upload(hashkey) # size='original'
        for size in PREVIEW_SIZES:
            storage.s3_upload(hashkey, size)
    # Save screenshot in database
    screenshot = Screenshot(hashkey=hashkey,
        user=request_group.user, website=request_group.website,
        factory=factory, browser=browser,
        width=width, height=height, bytes=bytes)
    screenshot.save()
    # Close the request
    close_request(request_id, factory, screenshot)
    # Update timestamps and estimates
    now = datetime.now()
    if request.priority == 0:
        factory.update_fields(last_upload=now,
            queue_estimate=(now - request_group.submitted).seconds)
    else:
        factory.update_fields(last_upload=now)
    browser.update_fields(last_upload=now)
    return hashkey
示例#6
0
def upload(http_request, factory, encrypted_password, request, screenshot):
    """
    Submit a multi-page screenshot as a lossless PNG file.

    Arguments
    ~~~~~~~~~
    * factory_name string (lowercase, normally from hostname)
    * encrypted_password string (lowercase hexadecimal, length 32)
    * request int (from requests.poll)
    * screenshot binary (BASE64-encoded PNG file)

    See nonces.verify for how to encrypt your password.

    Return value
    ~~~~~~~~~~~~
    * hashkey string (lowercase hexadecimal, length 32)

    Users can see the resulting uploaded screenshot at
    http://browsershots.org/screenshots/hashkey/
    """
    # Verify authentication
    nonces.verify(http_request, factory, encrypted_password)
    request_id = request
    request = get_or_fault(Request, pk=request_id)
    request_group = request.request_group
    # Make sure the request was locked by this factory
    request.check_factory_lock(factory)
    # Store and check screenshot file
    hashkey = storage.save_upload(screenshot)
    bytes = storage.png_filesize(hashkey)
    # Make sure the request was redirected by the browser
    browser = request.browser
    if browser is None or browser.factory_id != factory.id:
        guessed = factory.browser_set.filter(
            active=True,
            browser_group=request.browser_group,
            major=request.major,
            minor=request.minor)[:1]
        if not len(guessed):
            guessed = [None]
        raise ExtraFault(406,
                         u"The browser has not visited the requested website.",
                         request=request,
                         hashkey=hashkey,
                         browser=guessed[0])
    # Unpack PNG file and run more checks
    ppmname = storage.pngtoppm(hashkey)
    try:
        magic, width, height = storage.read_pnm_header(ppmname)
        if request_group.width and request_group.width != width:
            raise ExtraFault(
                412,
                u"The screenshot is %d pixels wide, not %d as requested." %
                (width, request_group.width),
                request=request,
                hashkey=hashkey,
                browser=browser)
        if height > width * 4:
            raise ExtraFault(
                413,
                u"The screenshot is too tall (more than 4 times the width).",
                request=request,
                hashkey=hashkey,
                browser=browser)
        if height < width / 2:
            raise ExtraFault(
                414,
                u"The screenshot is too short (less than half the width).",
                request=request,
                hashkey=hashkey,
                browser=browser)
        if os.path.exists('/usr/local/etc/pbmgrep'):
            check_ppm_problems(ppmname, request, hashkey, browser)
        # Make smaller preview images
        for size in PREVIEW_SIZES:
            storage.scale(ppmname, size, hashkey)
    finally:
        # Delete temporary PPM file
        os.unlink(ppmname)
    # Upload screenshots to Amazon S3 (but not for anonymous users)
    if hasattr(settings, 'S3_BUCKETS') and request_group.user_id is not None:
        storage.s3_upload(hashkey)  # size='original'
        for size in PREVIEW_SIZES:
            storage.s3_upload(hashkey, size)
    # Save screenshot in database
    screenshot = Screenshot(hashkey=hashkey,
                            user=request_group.user,
                            website=request_group.website,
                            factory=factory,
                            browser=browser,
                            width=width,
                            height=height,
                            bytes=bytes)
    screenshot.save()
    # Close the request
    close_request(request_id, factory, screenshot)
    # Update timestamps and estimates
    now = datetime.now()
    if request.priority == 0:
        factory.update_fields(last_upload=now,
                              queue_estimate=(now -
                                              request_group.submitted).seconds)
    else:
        factory.update_fields(last_upload=now)
    browser.update_fields(last_upload=now)
    return hashkey