SitePoint Sponsor

User Tag List

Page 2 of 3 FirstFirst 123 LastLast
Results 26 to 50 of 63

Thread: Request wrapper

  1. #26
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    It is not clear from the code it self, what is going on -- It presumes some a priori knowledge.
    It is not necessary, and often counter productive, to have the public interface show every little detail of "what is going on"... It quickly leads to code bloat and unnecessarily complex interfaces.

    As for assuming some previous knowledge... all I can say is, "well Duh!"... All libraries require that you know something about them before you can properly use them.
    <.smarter.web.development.>
    PHP Stuff: Plexus | Chocolate (BDD Framework... coming soon)
    Graphite

  2. #27
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dreamscape View Post
    It is not necessary, and often counter productive, to have the public interface show every little detail of "what is going on"... It quickly leads to code bloat and unnecessarily complex interfaces.
    Who said to show every little detail? I meant that $request->foo refers to a parameter value, while $request->sanitize refers to a container, that has various filtering methods. That's two completely different meanings, of something, which appears syntactically the same. That's potential for misunderstanding.

    Quote Originally Posted by dreamscape View Post
    As for assuming some previous knowledge... all I can say is, "well Duh!"... All libraries require that you know something about them before you can properly use them.
    That doesn't justify counter-intuitive design, does it? You wouldn't name your methods method1(), method2(), etc., since people can just refer to the documentation, if they want to know what they mean.

  3. #28
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    That's two completely different meanings, of something, which appears syntactically the same.
    $request->post->foo
    $request->post->sanitize->foo
    $request->post->sanitize->asInt->foo

    Come on kyberfabrikken. The meaning and what is going on is not nearly as mysterious or obscure as you are making it out to be. Any developer with half a brain is going to have a pretty good idea of what is going on. Even if they don't know what precisely the default sanitizer/filter does, they're still going to know that foo is probably being sanitized/filtered in some way.

    I think that you're arguing just to have an argument... Ridiculous.

    I have pondered changing the interface to:

    $request->post->foo
    $request->sanitize->post->foo
    $request->sanitize->asInt->post->foo

    Does that rattle your bones a little less?
    <.smarter.web.development.>
    PHP Stuff: Plexus | Chocolate (BDD Framework... coming soon)
    Graphite

  4. #29
    SitePoint Zealot cholmon's Avatar
    Join Date
    Mar 2004
    Location
    SC
    Posts
    197
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dreamscape View Post
    I have pondered changing the interface to:

    $request->post->foo
    $request->sanitize->post->foo
    $request->sanitize->asInt->post->foo
    Why not have the sanitize come after the parameter is referenced, for instance (with a few changes I'd personally make for my own clarity):

    PHP Code:
    $age $request->param->age;
    $age $request->param->age->sanitize();
    $age $request->param->age->sanitize()->asInt(); 
    That seems to make a little more sense to me, but it still doesn't feel right. What bothers me about sanitize is that it depends entirely on how the data is going to be used. Does sanitize mean escape quotes to protect against SQL injection or does it mean escape HTML to protect against XSS or both? What if you need one but not the other...or something else entirely that is specific to your application?

    If a parameter, like age, is going the be converted to an integer anyway, there really shouldn't be a need to "sanitize" it first. Given that, what is the difference between sanitizing and validating, and why not simply provide a way to hook up custom validation rules to any given parameter?
    Drew C King: PHP Developer
    <?= $short_tags++ ?>

  5. #30
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dreamscape View Post
    I think that you're arguing just to have an argument... Ridiculous.
    No, I'm not. What you're suggesting, is imprecise -- not right out wrong. That's true for a lot of design decisions, which I wouldn't pick. Global variables for example.

    I just don't see the point of doing something wrong, if you can do it right.

  6. #31
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by cholmon View Post
    What bothers me about sanitize is that it depends entirely on how the data is going to be used.
    Exactly what I meant above. "sanitizing" request vars is completely pointless.

  7. #32
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by cholmon View Post
    What bothers me about sanitize is that it depends entirely on how the data is going to be used. Does sanitize mean escape quotes to protect against SQL injection or does it mean escape HTML to protect against XSS or both?
    It is neither... The job of escaping output lies with the relevant domain, i.e, escaping SQL is the responsibility of the database drivers, escaping html is the responsibility of the view or template engine, etc...

    The purpose of "sanitize" is not to escape out, but to filter input, where and when it is necessary to do so.

    It is a very basic security practice, so let's all say it together, filter input, escape output.

    Quote Originally Posted by stereofrog View Post
    "sanitizing" request vars is completely pointless.
    It is precisely that sort of attitude that has led to many a number of exploits in PHP applications.
    <.smarter.web.development.>
    PHP Stuff: Plexus | Chocolate (BDD Framework... coming soon)
    Graphite

  8. #33
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Please provide an example of correct and useful "santizing" code.

  9. #34
    SitePoint Zealot cholmon's Avatar
    Join Date
    Mar 2004
    Location
    SC
    Posts
    197
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dreamscape View Post
    It is neither... The job of escaping output lies with the relevant domain, i.e, escaping SQL is the responsibility of the database drivers, escaping html is the responsibility of the view or template engine, etc...
    Input and output are relative terms. A string from an HTML form (input) will need to be escaped when it is passed on (output) to the database in order to prevent SQL injection. Whether you think of that string as being input or output, it's going to get escaped...hence the name of the function mysqli_real_escape_string. Arguing about the terminology (i.e., what's input and what's output, or the difference between filtering/validating/escaping/sanitizing) is pedantic at best. What's important is making sure that you aren't using or passing along potentially corrupt data.

    My primary concern with the code you provided is that it is unclear how to specify the actual "sanitization" that is necessesary, or if it is even possible to do so. You mention in a previous post that
    Quote Originally Posted by dreamscape View Post
    [...] my default sanitizer attempts to prevent common exploits such as XSS. And other sanitizers can be added for more specific scenarios, such as sanitizing IP addresses, etc...
    but I didn't see any way to add "other sanitizers". Is that something that is done within the Request object itself in a hardcoded manner, or can those additional sanitizers be created and added at runtime? For instance, how would you add a sanitizer that returns an integer value between 13 and 120 (inclusively) for $request->post->age?

    If I had to guess, I would say that your $request->post->sanitize->asInt->param syntax is relying on filter_input or filter_var behind the scenes to handle the dirty work of sanitizing/filtering/escaping/validating. Is that correct? I'm just curious.

    Quote Originally Posted by dreamscape View Post
    It is precisely that sort of attitude that has led to many a number of exploits in PHP applications.
    I'm pretty sure that stereofrog was referring to the apparently rudimentary (thus inflexible and "pointless") nature of your particular sanitize implementation, not the idea of sanitizing/escaping/filtering/validating input data as a whole.
    Drew C King: PHP Developer
    <?= $short_tags++ ?>

  10. #35
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > For instance, how would you add a sanitizer that returns an integer value between 13 and
    > 120 (inclusively) for $request->post->age?

    That isn't the realm of sanitising data, but it is a business rule so belongs in the domain layer. It may be obvious, and I don't want to be the piggy in the middle, but sanitsation should be one of the first things you do before anything else...

    Such as reaching your Page/Front Controller for example; Leave your sanitisation any later than this and your asking for trouble in my view.

  11. #36
    SitePoint Addict rvdavid's Avatar
    Join Date
    Nov 2006
    Location
    Australia
    Posts
    233
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi,

    I have a similar opinion to Dr L.

    I don't think that there really is a need for the request wrapper object to have sanitation responsibilities as there should have been processes to take care of that either before execution the same way that components that will be using the request data will have their own methods of escaping it as you have mentioned (ie mysql_real_escape_string, htmlentities etc).

    Sanitation should be outside the realm of the Request Wrapper. A class should do one thing and one thing well. As such a Request Wrapper should not have sanitation responsibilities - just wrap itself around request data and provide an interface for it's clients.

    To my experience, request data is either sanitised RIGHT at the beginning of execution (ie input filter) before it's even fed into the system, and/or escaped just before output or storage.

    Regards,

  12. #37
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston View Post
    That isn't the realm of sanitising data, but it is a business rule so belongs in the domain layer.
    What's the difference?

    Quote Originally Posted by Dr Livingston View Post
    sanitsation should be one of the first things you do before anything else...

    Such as reaching your Page/Front Controller for example; Leave your sanitisation any later than this and your asking for trouble in my view.
    How can you filter data, without knowing what it's used for? magic-quotes is an attempt to sanitise data up front. It's actually working fairly good, but still loathed by most developers.

  13. #38
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by stereofrog View Post
    Please provide an example of correct and useful "santizing" code.
    Sanitizing data is just cleaning it up to meet certain specs, so that it exists in a known "safe" state or format.

    One example would be a credit card number. There are several ways someone could enter a credit card number into an input field. You would then sanitize or clean up that number on input to force it into a known format, so that the rest of the application can safely use it and not have to worry about checking the format or re-formatting it.

    Quote Originally Posted by cholmon View Post
    but I didn't see any way to add "other sanitizers". Is that something that is done within the Request object itself in a hardcoded manner, or can those additional sanitizers be created and added at runtime?
    No, they're not hard coded. They are added at runtime, in the bootstrap, or at least prior to use.

    Quote Originally Posted by cholmon View Post
    For instance, how would you add a sanitizer that returns an integer value between 13 and 120 (inclusively) for $request->post->age?
    Well now, I think it is important to differentiate between sanitizing/filtering data and validating data. Checking that a value is between 13 and 120 says validation to me.

    Sanitizing and validating are closely related, but to me the main difference is that with sanitizing, you are cleaning up some input data and then going to do something with the "cleaned" data in the application (i.e, filtering input for the application to use). With validating, you are performing a check that input data meets certain criteria (and probably failing if it does not). And just to make the whole picture clear, with escaping output, you are putting the data into a format that is safe to send to a client (database, browser, etc).

    They are all somewhat related, but have very different purposes.
    <.smarter.web.development.>
    PHP Stuff: Plexus | Chocolate (BDD Framework... coming soon)
    Graphite

  14. #39
    SitePoint Enthusiast
    Join Date
    Jan 2006
    Location
    Finland
    Posts
    30
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I don't know if this will help anyone, but I've tried to keep my request wrapper as simple as possible and still maintain arrays such as POST and GET separate. I'm not that experienced with OOP yet, so I'd love some comments/feedback on this. Here's the core of the class:

    Code:
    class Request 
    {
    
        // array to store all request data in
        protected $request = array();		
    		
        public function __construct()
        {
            $this->request['get'] = $_GET;
            $this->request['post'] = $_POST;
            $this->request['request'] = $_REQUEST;
            $this->request['cookie'] = $_COOKIE;
            $this->request['files'] = $_FILES;
        }
    	
        /**
         *	Get a request variable.
         *	@param $key string - key of the var to get.
         *	@param $type string - request type (POST, GET, REQUEST, COOKIE, or FILES)
         */
        public function get($key, $type)
        {
            $type = strtolower($type);
    	 	
            if (isset($this->request[$type][$key])) {
                return $this->request[$type][$key];
            } else {
                return NULL;
            } 
        }
    	
    }
    A typical use scenario would be something as follows - Getting username passed on via POST only.

    Code:
    $request = new Request;
    $username = $request->get('username', 'POST');

  15. #40
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Serberus View Post
    I actually ended up with a class that does this but I wrote it as a wrapper for sessions. I can post the source when I get back from work if you want.
    Please!

    It will be intreasting to see what you have done.

  16. #41
    SitePoint Zealot Serberus's Avatar
    Join Date
    Oct 2005
    Location
    Herts, UK
    Posts
    113
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Arrow

    Sorry about the delay in my response. I've never actually used this, it's more proof of concept to myself that I could actually get it working.

    I've since seen much better ideas in this thread and probably wouldn't use this now. This is session specific but...

    I worked on this last year, there was a bug I found with it but I can't remember what it was now...

    PHP Code:
    class SessionHandler {

        var 
    $session;
        var 
    $glue;

        function 
    SessionHandler($sessionName ''$glue '.') {
        
            
    $sessionId session_id();
            
            if (empty(
    $sessionId)) {
                if (!empty(
    $sessionName))
                    
    session_name($sessionName);
                
                
    session_start();
            }
            
            
    $this->session =& $_SESSION;
            
    $this->glue $glue;
        
        }
        
        function 
    get($path '') {
            
            
    $target $this->session;
            
            if (
    $path != '') {
                foreach (
    $this->_getNodes($path) as $node) {
                    
    // Check the node requested exists
                    
    if (!isset($target[$node])) {
                        
    $target null;
                        break;
                    }
                    
                    
    $target $target[$node];
                }
            }
            
            return 
    $target;
            
        }
        
        function 
    set($path$value) {
            
            
    $this->_addNode($this->session$path$value);
            
        }
        
        function 
    _getNodes($path) {
        
            return (
    strpos($path,$this->glue) !== false) ? explode($this->glue,$path) : array($path);
            
        }
        
        function 
    _bitePath($path) {
        
            
    // bite first node off, return first node and remainder
            
    if ($pos strpos($path,$this->glue))
                return array(
    substr($path,0,$pos), substr($path,($pos+1)) );
            
            return array(
    $path,'');
            
        }
        
        function 
    _addNode(&$session,$path,$value) {

            if (
    $path == '') {
                
    $session $value;
                return 
    $session;
            }
            
            list(
    $node,$path) = $this->_bitePath($path);
            
            if (!isset(
    $session[$node]) || (isset($session[$node]) && !is_array($session[$node])))
                
    $session[$node] = array();

            return 
    $this->_addNode($session[$node],$path,$value);
            
        }

    }

    $session = new SessionHandler('test');

    $_SESSION = array(); // blank for testing - saves clearing cookies all the time
    $session->set('person.forename','joe');
    $session->set('person.surname','bloggs');

    $session->set('some.long.path.for.testing','yay');

    print_r($_SESSION); 
    Flame on

  17. #42
    SitePoint Evangelist
    Join Date
    Apr 2003
    Location
    North Carolina, USA
    Posts
    415
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wow neat class.

  18. #43
    SitePoint Evangelist
    Join Date
    Apr 2003
    Location
    North Carolina, USA
    Posts
    415
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kimmo View Post
    I don't know if this will help anyone, but I've tried to keep my request wrapper as simple as possible and still maintain arrays such as POST and GET separate. I'm not that experienced with OOP yet, so I'd love some comments/feedback on this. Here's the core of the class:

    Code:
    class Request 
    {
    
        // array to store all request data in
        protected $request = array();		
    		
        public function __construct()
        {
            $this->request['get'] = $_GET;
            $this->request['post'] = $_POST;
            $this->request['request'] = $_REQUEST;
            $this->request['cookie'] = $_COOKIE;
            $this->request['files'] = $_FILES;
        }
    	
        /**
         *	Get a request variable.
         *	@param $key string - key of the var to get.
         *	@param $type string - request type (POST, GET, REQUEST, COOKIE, or FILES)
         */
        public function get($key, $type)
        {
            $type = strtolower($type);
    	 	
            if (isset($this->request[$type][$key])) {
                return $this->request[$type][$key];
            } else {
                return NULL;
            } 
        }
    	
    }
    A typical use scenario would be something as follows - Getting username passed on via POST only.

    Code:
    $request = new Request;
    $username = $request->get('username', 'POST');
    I think it's a good start. I really don't have anything to suggest. I agree with whoever said that the Request class should be good at one thing. Classes ought to be as cohesive as possible. Yours seems that way. I guess all of the input filtering is done before the class is made?

  19. #44
    SitePoint Enthusiast
    Join Date
    Jan 2006
    Location
    Finland
    Posts
    30
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm currently using addslashes() before the request wrapper. In short, I run addslashes() on all the arrays such as POST and GET recursively before copying the arrays into the Request wrapper.

    In addition to that, I have validation of all user-inputted data via regexps in all action/command classes launched by the frontcontroller. Everything that gets close to database at any point is escaped using mysql_real_escape_string().

    Have I missed something major in input filtering with the step I've taken?

  20. #45
    SitePoint Enthusiast
    Join Date
    Jul 2006
    Location
    Australia, Victoria
    Posts
    56
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kimmo View Post
    I'm currently using addslashes() before the request wrapper. In short, I run addslashes() on all the arrays such as POST and GET recursively before copying the arrays into the Request wrapper.

    In addition to that, I have validation of all user-inputted data via regexps in all action/command classes launched by the frontcontroller. Everything that gets close to database at any point is escaped using mysql_real_escape_string().

    Have I missed something major in input filtering with the step I've taken?
    OK it may just be me, but i thought that all the validating and filtering would be done after the Request class as in.
    PHP Code:
    $request = new Request;
    $asd $request->get('asd');
    $asd trim$asd );
    $db->query('INSERT ....... :asd',Filter::MySQL($asd)); 
    Although that could just be me

  21. #46
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kimmo View Post
    I'm currently using addslashes() before the request wrapper. In short, I run addslashes() on all the arrays such as POST and GET recursively before copying the arrays into the Request wrapper.
    PHP already does this for you, if you set the value magic_quotes = On in php.ini.
    I take it, that you remember to stripslashes before running data through mysql_real_escape_string, right?

  22. #47
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    what about if i did this:

    PHP Code:
    <?php
    class Request {
        var 
    $get    = array();
        var 
    $post   = array();
        var 
    $cookie = array();
        var 
    $files  = array();
        var 
    $server = array();
        var 
    $env    = array();

          function 
    Request() {
            
    $this->get    =& $this->stripSlashes($_GET);
            
    $this->post   =& $this->stripSlashes($_POST);
            
    $this->cookie =& $this->stripSlashes($_COOKIE);
            
    $this->files  =& $this->stripSlashes($_FILES);
            
    $this->server =& $this->stripSlashes($_SERVER);
            
    $this->env    =& $this->stripSlashes($_ENV);
        }
                    
          function &
    stripSlashes(&$data) {
            if (
    is_array($data)) {
                  foreach (
    $data as $key => $value) {
                    
    $data[$key] =& $this->stripSlashes($value);
                  }
            } else {
                  
    $data stripslashes($data);
            }
        
            return 
    $data;
        }
    }

    $product_id $request->get['product_id'];

    $name $request->post['name'];
    ?>
    Is this good good OOP practise?

  23. #48
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Umm...

    PHP Code:
    // ...
    $asd trim$asd );
    // ... 
    In my veiw, the trim it's self should be done within the accessor; Certainly the client script that makes use of the implementation shouldn't need to do that, nor know of it; It's about responsibilities, and it's not upto the dependent to do so...

    > but i thought that all the validating and filtering would be done after the Request class as
    > in.

    Certainly the sanitisation of the Request should happen immediately after you've created an instance of it, and certainly before you begin to use it at any stage of your architecture.

    > Is this good good OOP practise?

    Nothing wrong with that as such, but I moved the stripslashes method to it's own filter, where in my implementation, there is one or more filters, each doing it's own thing. Once done, all the Request knows about is the parameters and nothing more, so I don't have separate $_GET and $_POST etc...

    But I can still tell if the request was a GET or POST though...

  24. #49
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Direct access to properties is usually considered bad practice, it's better to use specific methods like "param()", "cookie()", "env()" etc. Using methods has additional benefit that you don't have to check if a parameter exists before reading it. $request->post['name'] raises a notice if there's no "name" param, $request->param("name") won't.

  25. #50
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by blueyon View Post
    Is this good good OOP practise?
    I assume, that the reason why you would apply stripslashes, is because you want to counter magic-quotes? In that case, you better first check if magic-quote is on or off.
    Passing parameters by reference, is generally a bad idea, and in this case pointless.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •