Example #1
0
 def validate_delete_request(self, web, section):
     h = HttpHeaders()
     
     # map the headers to standard http
     mapped_headers = self._map_webpy_headers(web.ctx.environ)
     ssslog.debug("Validating on header dictionary: " + str(mapped_headers))
     
     try:
         # now validate the http headers
         h.validate(mapped_headers, section)
     except ValidationError as e:
         raise SwordError(error_uri=Errors.bad_request, msg=e.message)
Example #2
0
    def validate_deposit_request(self, web, entry_section=None, binary_section=None, multipart_section=None, empty_section=None, allow_multipart=True, allow_empty=False):
        h = HttpHeaders()

        # map the headers to standard http
        mapped_headers = self._map_webpy_headers(web.ctx.environ)
        ssslog.debug("Validating on header dictionary: " + str(mapped_headers))
  
        # run the validation
        try:
            # there must be both an "atom" and "payload" input or data in web.data()
            webin = web.input()
            if len(webin) != 2 and len(webin) > 0:
                raise ValidationException("Multipart request does not contain exactly 2 parts")
            if len(webin) >= 2 and not webin.has_key("atom") and not webin.has_key("payload"):
                raise ValidationException("Multipart request must contain Content-Dispositions with names 'atom' and 'payload'")
            if len(webin) > 0 and not allow_multipart:
                raise ValidationException("Multipart request not permitted in this context")

            # if we get to here then we have a valid multipart or no multipart
            is_multipart = False
            is_empty = False
            if len(webin) != 2: # if it is not multipart
                if web.data() is None or web.data().strip() == "": # FIXME: this does not look safe to scale
                    if allow_empty:
                        ssslog.info("Validating an empty deposit (could be a control operation)")
                        is_empty = True
                    else:
                        raise ValidationException("No content sent to the server")
            else:
                ssslog.info("Validating a multipart deposit")
                is_multipart = True
            
            is_entry = False
            content_type = mapped_headers.get("CONTENT-TYPE")
            if content_type is not None and content_type.startswith("application/atom+xml"):
                ssslog.info("Validating an atom-only deposit")
                is_entry = True
            
            if not is_entry and not is_multipart and not is_empty:
                ssslog.info("Validating a binary deposit")
            
            section = entry_section if is_entry else multipart_section if is_multipart else empty_section if is_empty else binary_section
            
            # now validate the http headers
            h.validate(mapped_headers, section)
            
        except ValidationException as e:
            raise SwordError(error_uri=Errors.bad_request, msg=e.message)
Example #3
0
    def get_delete(self, web, auth=None):
        """
        Take a web.py web object and extract from it the parameters and content required for a SWORD delete request.
        It mainly extracts the HTTP headers which are relevant to delete, and for those not supplied provides thier
        defaults in the returned DeleteRequest object
        """
        d = DeleteRequest()
        
        # map the webpy headers to something more standard
        mapped_headers = self._map_webpy_headers(web.ctx.environ)
        
        h = HttpHeaders()
        d.set_from_headers(h.get_sword_headers(mapped_headers))

        # now just attach the authentication data and return
        d.auth = auth
        return d
Example #4
0
 def get_deposit(self, web, auth=None, atom_only=False):
     # FIXME: this reads files into memory, and therefore does not scale
     # FIXME: this does not deal with the Media Part headers on a multipart deposit
     """
     Take a web.py web object and extract from it the parameters and content required for a SWORD deposit.  This
     includes determining whether this is an Atom Multipart request or not, and extracting the atom/payload where
     appropriate.  It also includes extracting the HTTP headers which are relevant to deposit, and for those not
     supplied providing their defaults in the returned DepositRequest object
     """
     d = DepositRequest()
     
     # map the webpy headers to something more standard
     mapped_headers = self._map_webpy_headers(web.ctx.environ)
     
     # get the headers that have been provided.  Any headers which have not been provided will
     # will have default values applied
     h = HttpHeaders()
     d.set_from_headers(h.get_sword_headers(mapped_headers))
     
     if d.content_type.startswith("application/atom+xml"):
         atom_only=True
     
     empty_request = False
     if d.content_length == 0:
         ssslog.info("Received empty deposit request")
         empty_request = True
     if d.content_length > config.max_upload_size:
         raise SwordError(error_uri=Errors.max_upload_size_exceeded, 
                         msg="Max upload size is " + str(config.max_upload_size) + 
                         "; incoming content length was " + str(d.content_length))
     
     # find out if this is a multipart or not
     is_multipart = False
     
     # FIXME: these headers aren't populated yet, because the webpy api doesn't
     # appear to have a mechanism to retrieve them.  urgh.
     entry_part_headers = {}
     media_part_headers = {}
     webin = web.input()
     if len(webin) == 2:
         ssslog.info("Received multipart deposit request")
         d.atom = webin['atom']
         # FIXME: this reads the payload into memory, we need to sort that out
         # read the zip file from the base64 encoded string
         d.content = base64.decodestring(webin['payload'])
         is_multipart = True
     elif not empty_request:
         # if this wasn't a multipart, and isn't an empty request, then the data is in web.data().  This could be a binary deposit or
         # an atom entry deposit - reply on the passed/determined argument to determine which
         if atom_only:
             ssslog.info("Received Entry deposit request")
             d.atom = web.data()
         else:
             ssslog.info("Received Binary deposit request")
             d.content = web.data()
     
     if is_multipart:
         d.filename = h.extract_filename(media_part_headers)
     else:
         d.filename = h.extract_filename(mapped_headers)
     
     # now just attach the authentication data and return
     d.auth = auth
     return d
    def get_deposit(self, auth=None, atom_only=False):
        # FIXME: this does not deal with the Media Part headers on a multipart deposit
        """
        Take a request object and extract from it the parameters and content required for a SWORD deposit.  This
        includes determining whether this is an Atom Multipart request or not, and extracting the atom/payload where
        appropriate.  It also includes extracting the HTTP headers which are relevant to deposit, and for those not
        supplied providing their defaults in the returned DepositRequest object
        """
        d = DepositRequest()

        # map the webpy headers to something more standard
        mapped_headers = self._map_webpy_headers(request.environ)

        # get the headers that have been provided.  Any headers which have not been provided will
        # will have default values applied
        h = HttpHeaders()
        d.set_from_headers(h.get_sword_headers(mapped_headers))

        if d.content_type.startswith("application/atom+xml"):
            atom_only = True

        empty_request = False
        if d.content_length == 0:
            ssslog.info("Received empty deposit request")
            empty_request = True
        if config.max_upload_size is not None and d.content_length > config.max_upload_size:
            raise SwordError(
                error_uri=Errors.max_upload_size_exceeded,
                msg="Max upload size is " + str(config.max_upload_size) +
                "; incoming content length was " + str(d.content_length))

        # FIXME: this method does NOT support multipart
        # find out if this is a multipart or not
        is_multipart = False

        # FIXME: these headers aren't populated yet, because the webpy api doesn't
        # appear to have a mechanism to retrieve them.  urgh.
        #entry_part_headers = {}
        #media_part_headers = {}
        #webin = request.POST
        #ssslog.debug(webin)
        #if len(webin) == 2:
        #    ssslog.info("Received multipart deposit request")
        #    d.atom = webin['atom']
        # FIXME: this reads the payload into memory, we need to sort that out
        # read the zip file from the base64 encoded string
        #    d.content = base64.decodestring(webin['payload'])
        #    is_multipart = True
        #elif not empty_request:
        if not empty_request:
            # for this section, we have to reset the file pointer in the body_file
            # part of the request back to the start, since it may have
            # already been read once
            f = request.body_file
            f.seek(0, 0)

            # if this wasn't a multipart, and isn't an empty request, then read the
            # data from the body_file
            if atom_only:
                # we don't worry about scalability here - the entries should be
                # generally small
                ssslog.info("Received Entry deposit request")
                d.atom = f.read()
            else:
                ssslog.info("Received Binary deposit request")
                # FIXME: this is reading everything in, and should be re-evaluated for performance/scalability
                d.content_file = f

        if is_multipart:
            d.filename = h.extract_filename(media_part_headers)
        else:
            d.filename = h.extract_filename(mapped_headers)

        # now just attach the authentication data and return
        d.auth = auth
        return d
    def validate_deposit_request(self,
                                 entry_section=None,
                                 binary_section=None,
                                 multipart_section=None,
                                 empty_section=None,
                                 allow_multipart=True,
                                 allow_empty=False):
        h = HttpHeaders()

        # map the headers to standard http
        mapped_headers = self._map_webpy_headers(request.environ)
        ssslog.debug("Validating on header dictionary: " + str(mapped_headers))

        # run the validation
        try:
            # there must be both an "atom" and "payload" input or data in web.data()

            # FIXME: deposit does NOT support multipart
            if request.environ["CONTENT_TYPE"].startswith("multipart"):
                raise SwordError(
                    error_uri=Errors.method_not_allowed,
                    msg=
                    "Pylons implementation does not currently support multipart/related requests"
                )
            """
            # leave this out until we can get multipart sorted (at a later date)
            webin = request.POST
            if len(webin) != 2 and len(webin) > 0:
                raise ValidationException("Multipart request does not contain exactly 2 parts")
            if len(webin) >= 2 and not webin.has_key("atom") and not webin.has_key("payload"):
                raise ValidationException("Multipart request must contain Content-Dispositions with names 'atom' and 'payload'")
            if len(webin) > 0 and not allow_multipart:
                raise ValidationException("Multipart request not permitted in this context")
            """

            # if we get to here then we have a valid multipart or no multipart
            is_multipart = False
            is_empty = False
            #if len(webin) != 2: # if it is not multipart
            # FIXME: this is reading everything in, and should be re-evaluated for performance/scalability
            # wsgi_input = request.environ['wsgi.input']
            f = request.body_file
            f.seek(0, 0)

            # FIXME: can't we just look at the Content-Type header????

            # read a byte in, to see if the body is empty
            if f is not None:
                byte = f.read(1)
                if byte == "" and allow_empty:
                    ssslog.debug(
                        "first byte of deposit request is the empty string")
                    is_empty = True
                else:
                    ssslog.debug("first byte of deposit request is \"" +
                                 str(byte) + "\" ... not an empty request")
                f.seek(0, 0)
            else:
                is_empty = True

            # validate whether we allow an empty deposit
            if is_empty and not allow_empty:
                raise ValidationException("No content sent to the server")
            elif is_empty and allow_empty:
                ssslog.info(
                    "Validating an empty deposit (could be a control operation)"
                )

            #else:
            #    ssslog.info("Validating a multipart deposit")
            #    is_multipart = True

            is_entry = False
            content_type = mapped_headers.get("CONTENT-TYPE")
            if content_type is not None and content_type.startswith(
                    "application/atom+xml"):
                ssslog.info("Validating an atom-only deposit")
                is_entry = True

            if not is_entry and not is_multipart and not is_empty:
                ssslog.info("Validating a binary deposit")

            section = entry_section if is_entry else multipart_section if is_multipart else empty_section if is_empty else binary_section

            # now validate the http headers
            h.validate(mapped_headers, section)

        except ValidationException as e:
            raise SwordError(error_uri=Errors.bad_request, msg=e.message)
 def get_deposit(self, auth=None, atom_only=False):
     # FIXME: this does not deal with the Media Part headers on a multipart deposit
     """
     Take a request object and extract from it the parameters and content required for a SWORD deposit.  This
     includes determining whether this is an Atom Multipart request or not, and extracting the atom/payload where
     appropriate.  It also includes extracting the HTTP headers which are relevant to deposit, and for those not
     supplied providing their defaults in the returned DepositRequest object
     """
     d = DepositRequest()
     
     # map the webpy headers to something more standard
     mapped_headers = self._map_webpy_headers(request.environ)
     
     # get the headers that have been provided.  Any headers which have not been provided will
     # will have default values applied
     h = HttpHeaders()
     d.set_from_headers(h.get_sword_headers(mapped_headers))
     
     if d.content_type.startswith("application/atom+xml"):
         atom_only=True
     
     empty_request = False
     if d.content_length == 0:
         ssslog.info("Received empty deposit request")
         empty_request = True
     if config.max_upload_size is not None and d.content_length > config.max_upload_size:
         raise SwordError(error_uri=Errors.max_upload_size_exceeded, 
                         msg="Max upload size is " + str(config.max_upload_size) + 
                         "; incoming content length was " + str(d.content_length))
     
     # FIXME: this method does NOT support multipart
     # find out if this is a multipart or not
     is_multipart = False
     
     # FIXME: these headers aren't populated yet, because the webpy api doesn't
     # appear to have a mechanism to retrieve them.  urgh.
     #entry_part_headers = {}
     #media_part_headers = {}
     #webin = request.POST
     #ssslog.debug(webin)
     #if len(webin) == 2:
     #    ssslog.info("Received multipart deposit request")
     #    d.atom = webin['atom']
         # FIXME: this reads the payload into memory, we need to sort that out
         # read the zip file from the base64 encoded string
     #    d.content = base64.decodestring(webin['payload'])
     #    is_multipart = True
     #elif not empty_request:
     if not empty_request:
         # for this section, we have to reset the file pointer in the body_file
         # part of the request back to the start, since it may have 
         # already been read once
         f = request.body_file
         f.seek(0, 0)
         
         # if this wasn't a multipart, and isn't an empty request, then read the 
         # data from the body_file
         if atom_only:
             # we don't worry about scalability here - the entries should be
             # generally small
             ssslog.info("Received Entry deposit request")
             d.atom = f.read()
         else:
             ssslog.info("Received Binary deposit request")
             # FIXME: this is reading everything in, and should be re-evaluated for performance/scalability
             d.content_file = f
     
     if is_multipart:
         d.filename = h.extract_filename(media_part_headers)
     else:
         d.filename = h.extract_filename(mapped_headers)
     
     # now just attach the authentication data and return
     d.auth = auth
     return d
    def validate_deposit_request(self, entry_section=None, binary_section=None, multipart_section=None, empty_section=None, allow_multipart=True, allow_empty=False):
        h = HttpHeaders()

        # map the headers to standard http
        mapped_headers = self._map_webpy_headers(request.environ)
        ssslog.debug("Validating on header dictionary: " + str(mapped_headers))
  
        # run the validation
        try:
            # there must be both an "atom" and "payload" input or data in web.data()
            
            # FIXME: deposit does NOT support multipart
            if request.environ["CONTENT_TYPE"].startswith("multipart"):
                raise SwordError(error_uri=Errors.method_not_allowed, msg="Pylons implementation does not currently support multipart/related requests")
            """
            # leave this out until we can get multipart sorted (at a later date)
            webin = request.POST
            if len(webin) != 2 and len(webin) > 0:
                raise ValidationException("Multipart request does not contain exactly 2 parts")
            if len(webin) >= 2 and not webin.has_key("atom") and not webin.has_key("payload"):
                raise ValidationException("Multipart request must contain Content-Dispositions with names 'atom' and 'payload'")
            if len(webin) > 0 and not allow_multipart:
                raise ValidationException("Multipart request not permitted in this context")
            """
            
            # if we get to here then we have a valid multipart or no multipart
            is_multipart = False
            is_empty = False
            #if len(webin) != 2: # if it is not multipart
                # FIXME: this is reading everything in, and should be re-evaluated for performance/scalability
            # wsgi_input = request.environ['wsgi.input']
            f = request.body_file
            f.seek(0, 0)
            
            # FIXME: can't we just look at the Content-Type header????
            
            # read a byte in, to see if the body is empty
            if f is not None:
                byte = f.read(1)
                if byte == "" and allow_empty:
                    ssslog.debug("first byte of deposit request is the empty string")
                    is_empty = True
                else:
                    ssslog.debug("first byte of deposit request is \"" + str(byte) + "\" ... not an empty request")
                f.seek(0, 0)
            else:
                is_empty = True
                
            # validate whether we allow an empty deposit
            if is_empty and not allow_empty:
                raise ValidationException("No content sent to the server")
            elif is_empty and allow_empty:
                ssslog.info("Validating an empty deposit (could be a control operation)")
            
            #else:
            #    ssslog.info("Validating a multipart deposit")
            #    is_multipart = True
            
            is_entry = False
            content_type = mapped_headers.get("CONTENT-TYPE")
            if content_type is not None and content_type.startswith("application/atom+xml"):
                ssslog.info("Validating an atom-only deposit")
                is_entry = True
            
            if not is_entry and not is_multipart and not is_empty:
                ssslog.info("Validating a binary deposit")
            
            section = entry_section if is_entry else multipart_section if is_multipart else empty_section if is_empty else binary_section
            
            # now validate the http headers
            h.validate(mapped_headers, section)
            
        except ValidationException as e:
            raise SwordError(error_uri=Errors.bad_request, msg=e.message)