Exemple #1
0
 def wrapper(http_request, factory_name, *args, **kwargs):
     """
     Get factory by name and log errors in the database.
     """
     from shotserver04.factories.models import Factory
     # Shortcut for nested calls, e.g. nonces.verify
     if isinstance(factory_name, Factory):
         factory = factory_name
         return func(http_request, factory, *args, **kwargs)
     # Get factory by name and run wrapped function
     factory = get_or_fault(Factory, name=factory_name)
     try:
         return func(http_request, factory, *args, **kwargs)
     except xmlrpclib.Fault, fault:
         fault_class = fault.faultCode / 100
         if fault_class not in (2, 5): # Success or server error
             from shotserver04.messages.models import FactoryError
             # Save error message in the database
             FactoryError.objects.create(factory=factory,
                 code=fault.faultCode, message=fault.faultString,
                 request=getattr(fault, 'request', None),
                 hashkey=getattr(fault, 'hashkey', None))
             browser = getattr(fault, 'browser', None)
             if browser is not None:
                 browser.update_fields(last_error=datetime.now())
         raise
Exemple #2
0
 def wrapper(http_request, factory_name, *args, **kwargs):
     """
     Get factory by name and log errors in the database.
     """
     from shotserver04.factories.models import Factory
     # Shortcut for nested calls, e.g. nonces.verify
     if isinstance(factory_name, Factory):
         factory = factory_name
         return func(http_request, factory, *args, **kwargs)
     # Get factory by name and run wrapped function
     factory = get_or_fault(Factory, name=factory_name)
     try:
         return func(http_request, factory, *args, **kwargs)
     except xmlrpclib.Fault, fault:
         fault_class = fault.faultCode / 100
         if fault_class not in (2, 5):  # Success or server error
             from shotserver04.messages.models import FactoryError
             # Save error message in the database
             FactoryError.objects.create(
                 factory=factory,
                 code=fault.faultCode,
                 message=fault.faultString,
                 request=getattr(fault, 'request', None),
                 hashkey=getattr(fault, 'hashkey', None))
             browser = getattr(fault, 'browser', None)
             if browser is not None:
                 browser.update_fields(last_error=datetime.now())
         raise
def close_request(request_id, factory, screenshot):
    """
    Close a screenshot request after it has been completed.
    """
    # Check again that no other factory has locked the request
    request = get_or_fault(Request, pk=request_id)
    try:
        request.check_factory_lock(factory)
    except Fault:
        screenshot.delete()
        raise
    # Close the request
    request.update_fields(screenshot=screenshot)
Exemple #4
0
def close_request(request_id, factory, screenshot):
    """
    Close a screenshot request after it has been completed.
    """
    # Check again that no other factory has locked the request
    request = get_or_fault(Request, pk=request_id)
    try:
        request.check_factory_lock(factory)
    except Fault:
        screenshot.delete()
        raise
    # Close the request
    request.update_fields(screenshot=screenshot)
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
Exemple #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