def upload_video_photo(self, request):
        """Handle Image file uploads for Video thumbnails.

        We are going to look for a Base64 encoded image if a "photo" file
        doesn't exist in request.FILES and add it onto the request object
        before relegating the request object to the superclass

        Since this method calls a celery task that depends on database changes
        made here, we must ensure that the transaction gets commited first.

        :param request:   HttpRequest object from django
        """
        photo_file = request.FILES.get('photo')
        if photo_file is None:
            # upload_video_photo was called, but without the "photo" file.
            # Let's see if we got a base64 string of the "photo"
            photo_b64 = request.POST.get('photo')
            if photo_b64 is None:
                return upload._render_response_bad_request(
                    request,
                    'Request must include photo file or base64 encoded photo parameter'
                )
            try:
                photo_file = SimpleUploadedFile('photo',
                                                base64.b64decode(photo_b64),
                                                'image/png')
                photo_extension = '.png'
            except TypeError:
                # Thrown by b64decode if handed a non base64 string
                return upload._render_response_bad_request(
                    request, 'Could not decode uploaded photo parameter')
        else:
            photo_extension = os.path.splitext(photo_file.name)[1]
        auth_token = request.POST.get('auth_token', None)
        video_id = int(request.POST.get('video_id', None))
        if not (request.method == 'POST' and auth_token and video_id):
            return upload._render_response_bad_request(
                request,
                msg=(
                    "Your request must include exactly one file, the " +
                    "'video_id' of the video you are uploading the photo for, "
                    + "and a variable named 'auth_token'."))
        try:
            video = self._find_by_id(video_id)
            auth_token = Utils.get_auth_token_object(auth_token)
            facade.subsystems.Authorizer().check_update_permissions(
                auth_token, video, {'photo_url': 'A New Photo!'})
            if getattr(settings, 'VOD_ENABLE_VIDEO_UPLOAD_WORKFLOW', True):
                queue_upload(
                    video, 'photo',
                    'video/%d.thumbnail%s' % (video_id, photo_extension),
                    photo_file)
            return upload._render_response_ok(request,
                                              msg='Image upload successful.')
        except exceptions.PrException, p:
            return upload._render_response_forbidden(request,
                                                     msg=p.get_error_msg())
    def upload_video_photo(self, request):
        """Handle Image file uploads for Video thumbnails.

        We are going to look for a Base64 encoded image if a "photo" file
        doesn't exist in request.FILES and add it onto the request object
        before relegating the request object to the superclass

        Since this method calls a celery task that depends on database changes
        made here, we must ensure that the transaction gets commited first.

        :param request:   HttpRequest object from django
        """
        photo_file = request.FILES.get('photo')
        if photo_file is None:
            # upload_video_photo was called, but without the "photo" file.
            # Let's see if we got a base64 string of the "photo"
            photo_b64 = request.POST.get('photo')
            if photo_b64 is None:
                return upload._render_response_bad_request(request,
                    'Request must include photo file or base64 encoded photo parameter')
            try:
                photo_file = SimpleUploadedFile('photo', base64.b64decode(photo_b64), 'image/png')
                photo_extension = '.png'
            except TypeError:
                # Thrown by b64decode if handed a non base64 string
                return upload._render_response_bad_request(request,
                    'Could not decode uploaded photo parameter')
        else:
            photo_extension = os.path.splitext(photo_file.name)[1]
        auth_token = request.POST.get('auth_token', None)
        video_id = int(request.POST.get('video_id', None))
        if not (request.method == 'POST' and auth_token and video_id):
            return upload._render_response_bad_request(request,
                msg=("Your request must include exactly one file, the "+
                    "'video_id' of the video you are uploading the photo for, "+
                    "and a variable named 'auth_token'."))
        try:
            video = self._find_by_id(video_id)
            auth_token = Utils.get_auth_token_object(auth_token)
            facade.subsystems.Authorizer().check_update_permissions(auth_token,
                video, {'photo_url' : 'A New Photo!'})
            if getattr(settings, 'VOD_ENABLE_VIDEO_UPLOAD_WORKFLOW', True):
                queue_upload(video, 'photo',
                    'video/%d.thumbnail%s' % (video_id, photo_extension),
                    photo_file)
            return upload._render_response_ok(request, msg='Image upload successful.')
        except exceptions.PrException, p:
            return upload._render_response_forbidden(request, msg=p.get_error_msg())
    def upload_video(self, request, auth_token=None):
        """Handle video file uploads

        This method will stick the contents of the uploaded file (of which there
        must be exactly 1) into the database through a Video object.  There is
        currently no validation of the Video.

        :param request: HttpRequest object from Django
        :type request:  HttpRequest
        :param auth_token:  AuthToken from an HTML form upload
        :type auth_token:   string or None

        """
        try:
            if request.method == 'GET':
                transaction.rollback()
                if auth_token is None:
                    return upload._render_response_forbidden(
                        request,
                        msg=
                        'Your request must include an auth token in its URL.')
                return upload._render_response(
                    request, 'vod_upload_video.html', {
                        'title': 'Video Upload',
                        'form': VideoUploadForm(),
                        'auth_token': auth_token
                    })
            elif request.method == 'POST':
                if auth_token is None:
                    if 'auth_token' not in request.POST:
                        transaction.rollback()
                        return upload._render_response_forbidden(
                            request,
                            msg=
                            'Your request must contain a variable named \'auth_token\'.'
                        )
                    else:
                        auth_token = request.POST['auth_token']
                form = VideoUploadForm(data=request.POST, files=request.FILES)
                if form.is_valid():
                    at = Utils.get_auth_token_object(auth_token)
                    at.domain_affiliation.user = at.domain_affiliation.user.downcast_completely(
                    )
                    if 'categories' in request.POST:
                        try:
                            categories = json.loads(request.POST['categories'])
                        except ValueError:  # Will also handle json.JSONDecodeError, depending on simplejson version used.
                            raise exceptions.InvalidDataException, 'invalid JSON data in categories field'
                        if not isinstance(categories, list):
                            raise exceptions.InvalidDataException, 'categories must be a list of dictionaries mapping "id" to an integer category id'
                        for c in categories:
                            if not (isinstance(c, dict) and 'id' in c
                                    and type(c['id']) in (int, long)):
                                raise exceptions.InvalidDataException, 'categories must be a list of dictionaries mapping "id" to an integer category id'
                        categories = [c['id'] for c in categories]
                    new_video = self.create(at, form.cleaned_data['name'],
                                            form.cleaned_data['description'],
                                            form.cleaned_data['author'],
                                            categories)
                    new_video.src_file_size = form.files['video'].size
                    new_video.save()
                    # Commit the transaction before queuing a task to work on
                    # our new Video object.
                    transaction.commit()
                    if getattr(settings, 'VOD_ENABLE_VIDEO_UPLOAD_WORKFLOW',
                               True):
                        ## Queue the task to upload the video to S3.
                        # Let's get the notification URL here because we can do
                        # it accurately while in the web hosting environment
                        # but not in celeryd.
                        notify_url = getattr(settings,
                                             'ENCODING_NOTIFICATION_URL',
                                             False)
                        if not notify_url:
                            request = middleware.get_current_request()
                            site = '%s://%s' % (request.is_secure() and 'https'
                                                or 'http', request.get_host())
                            notify_url = urlparse.urljoin(
                                site, reverse('vod_aws:video_notification'))
                        pending = prepare_upload(new_video,
                                                 'src_file',
                                                 'video/%d.src' % new_video.id,
                                                 form.files['video'],
                                                 callback=subtask(
                                                     queue_encoding,
                                                     video_id=new_video.id,
                                                     notify_url=notify_url))
                        transaction.commit()
                        pending.queue()

                    if 'auth_token' not in request.POST:
                        return upload._render_response_ok(
                            request, msg='Video upload successful.')
                    else:
                        # for plain POST requests (old way), still return the video ID
                        return HttpResponse(
                            str(new_video.id) if new_video else None)
                else:
                    transaction.rollback()
                    logging.info(str(form.errors))
                    return upload._render_response(request,
                                                   'vod_upload_video.html', {
                                                       'title': 'Video Upload',
                                                       'form': form,
                                                       'auth_token': auth_token
                                                   },
                                                   status=400)
        except exceptions.PrException, p:
            transaction.rollback()
            log_message = u'UploadManager.upload_video: pr exception code %d, msg [%s], details [%s]' %\
                (p.get_error_code(), p.get_error_msg(), unicode(p.get_details()))
            logging.info(log_message)
            if p.error_code == 46:  # InternalErrorException
                stack_trace = traceback.format_exc()
                logging.info(stack_trace)
                return upload._render_response_server_error(
                    request, msg=p.get_error_msg())
            elif p.error_code in [17, 23, 49, 114, 115, 128]:
                return upload._render_response_forbidden(request,
                                                         msg=p.get_error_msg())
            else:
                return upload._render_response_bad_request(
                    request, msg=p.get_error_msg())
    def upload_video(self, request, auth_token=None):
        """Handle video file uploads

        This method will stick the contents of the uploaded file (of which there
        must be exactly 1) into the database through a Video object.  There is
        currently no validation of the Video.

        :param request: HttpRequest object from Django
        :type request:  HttpRequest
        :param auth_token:  AuthToken from an HTML form upload
        :type auth_token:   string or None

        """
        try:
            if request.method == 'GET':
                transaction.rollback()
                if auth_token is None:
                    return upload._render_response_forbidden(request,
                        msg='Your request must include an auth token in its URL.')
                return upload._render_response(request, 'vod_upload_video.html',
                    {'title': 'Video Upload', 'form': VideoUploadForm(),
                     'auth_token': auth_token})
            elif request.method == 'POST':
                if auth_token is None:
                    if 'auth_token' not in request.POST:
                        transaction.rollback()
                        return upload._render_response_forbidden(request,
                            msg='Your request must contain a variable named \'auth_token\'.')
                    else:
                        auth_token = request.POST['auth_token']
                form = VideoUploadForm(data=request.POST, files=request.FILES)
                if form.is_valid():
                    at = Utils.get_auth_token_object(auth_token)
                    at.domain_affiliation.user = at.domain_affiliation.user.downcast_completely()
                    if 'categories' in request.POST:
                        try:
                            categories = json.loads(request.POST['categories'])
                        except ValueError: # Will also handle json.JSONDecodeError, depending on simplejson version used.
                            raise exceptions.InvalidDataException, 'invalid JSON data in categories field'
                        if not isinstance(categories, list):
                            raise exceptions.InvalidDataException, 'categories must be a list of dictionaries mapping "id" to an integer category id'
                        for c in categories:
                            if not (isinstance(c, dict) and
                                'id' in c and
                                type(c['id']) in (int, long)):
                                    raise exceptions.InvalidDataException, 'categories must be a list of dictionaries mapping "id" to an integer category id'
                        categories = [c['id'] for c in categories]
                    new_video = self.create(at,
                        form.cleaned_data['name'],
                        form.cleaned_data['description'],
                        form.cleaned_data['author'],
                        categories)
                    new_video.src_file_size = form.files['video'].size
                    new_video.save()
                    # Commit the transaction before queuing a task to work on
                    # our new Video object.
                    transaction.commit()
                    if getattr(settings, 'VOD_ENABLE_VIDEO_UPLOAD_WORKFLOW', True):
                        ## Queue the task to upload the video to S3.
                        # Let's get the notification URL here because we can do
                        # it accurately while in the web hosting environment
                        # but not in celeryd.
                        notify_url = getattr(settings, 'ENCODING_NOTIFICATION_URL', False)
                        if not notify_url:
                            request = middleware.get_current_request()
                            site = '%s://%s' % (
                                request.is_secure() and 'https' or 'http',
                                request.get_host())
                            notify_url = urlparse.urljoin(site, reverse('vod_aws:video_notification'))
                        pending = prepare_upload(new_video, 'src_file',
                            'video/%d.src' % new_video.id,
                            form.files['video'],
                            callback=subtask(queue_encoding,
                                video_id=new_video.id, notify_url=notify_url))
                        transaction.commit()
                        pending.queue()

                    if 'auth_token' not in request.POST:
                        return upload._render_response_ok(request,
                            msg='Video upload successful.')
                    else:
                        # for plain POST requests (old way), still return the video ID
                        return HttpResponse(str(new_video.id) if new_video else None)
                else:
                    transaction.rollback()
                    logging.info(str(form.errors))
                    return upload._render_response(request, 'vod_upload_video.html',
                        {'title': 'Video Upload', 'form': form,
                         'auth_token': auth_token}, status=400)
        except exceptions.PrException, p:
            transaction.rollback()
            log_message = u'UploadManager.upload_video: pr exception code %d, msg [%s], details [%s]' %\
                (p.get_error_code(), p.get_error_msg(), unicode(p.get_details()))
            logging.info(log_message)
            if p.error_code == 46: # InternalErrorException
                stack_trace = traceback.format_exc()
                logging.info(stack_trace)
                return upload._render_response_server_error(request, msg=p.get_error_msg())
            elif p.error_code in [17, 23, 49, 114, 115, 128]:
                return upload._render_response_forbidden(request, msg=p.get_error_msg())
            else:
                return upload._render_response_bad_request(request, msg=p.get_error_msg())