PHP Case WTF



  • So ran across this today.

    $json = json_decode($HTTP_RAW_POST_DATA);
    switch(true){
    	case is_null($json):
    		$app_id = "invalid_json";
    		break;
    	case is_object($json):
    		$app_id = $json->app_id;
    		break;
    	case is_array($json) && is_object(current($json)):
    		$object = current($json);
    		$app_id = $object->app_id;
    		break;
    	default:
    		$app_id = "unacceptable_json";
    }
    

    First WTF, switch (true). OK, I've never done that before, but it does let you avoid writing a ton of if/else if clauses. Maybe if PHP didn't have mixed return types everywhere, this wouldn't be necessary in the first place.

    Then I saw the case statements. Apparently, PHP allows you to put expressions in the case statements. I was horrified. I'm mainly a .NET programmer where case statements must be constants.



  • Writing PHP for 5 years.. I've never ever been tempted to use a method call in a switch case.

    The more you learn about the insanity of PHP.



  • Impressive, I did not even know you could do that.  Once I think I have seen the level of crazy stuff people can do with PHP, someone comes along and one ups it.



  • @twilsonxpert said:

    I'm mainly a .NET programmer where case statements must be constants.


    I feel your pain man. I'm a .net dev that took over a PHP project a few months ago... I would have just quit, but it's a really high profile project so I'm doing my best to deal with it...

    Just so you know, you can't do threading and there is no equivlent for Server.Redirect !!! The biggest wtf I'm trying to get over is OO in a loose typed language! The only freaking web devs with a good working knowlege of OO decided to apply it in a PHP app that I am now working on... the universe hates me.



     



  • Doesn't this construction just approximate the functionality of the SQL CASE statement?



  • @this_code_sucks said:

    Just so you know, you can't do threading and there is no equivlent for Server.Redirect !!!
    Do you mean Response.Redirect? If so, you're wanting PHP's header() function.



  • @twilsonxpert said:

    I'm mainly a .NET programmer where case statements must be constants.

    You're not a VB.Net programmer, then. http://stackoverflow.com/questions/794036/select-case-true



  • @Frigax said:

    @this_code_sucks said:

    Just so you know, you can't do threading and there is no equivlent for Server.Redirect !!!
    Do you mean Response.Redirect? If so, you're wanting PHP's header() function.

    No, I meant Server.Transfer

    Sorry for the confusion.



  • This pattern is pretty common in ruby. You can even leave off the true and it turns into pure syntactic sugar for if/elsif.



  • @this_code_sucks said:

    @Frigax said:

    @this_code_sucks said:

    Just so you know, you can't do threading and there is no equivlent for Server.Redirect !!!
    Do you mean Response.Redirect? If so, you're wanting PHP's header() function.

    No, I meant Server.Transfer

    Sorry for the confusion.




    well, you could do something like

      ob_clean();
      echo(file_get_contents($urlToTransferTo));
    

    in a true to PHP wtfy fashion.


    or maybe just directly call the function/method that generates the page you want?



  • @SEMI-HYBRID code said:

    or maybe just directly call the function/method that generates the page you want?

    This. I feel obliged to defend PHP. Server.Transfer looks like it is just syntactic sugar for calling your whole framework/website again. There is no reason why you couldn't do that in PHP, but somehow it strikes me as slightly undesirable (for no specific reason).



  • @twilsonxpert said:

    First WTF, switch (true). OK, I've never done that before, but it does let you avoid writing a ton of if/else if clauses. ... Then I saw the case statements. Apparently, PHP allows you to put expressions in the case statements. I was horrified.

    If there were no expressions allowed there, what exactly would you expect switch (true) to do? Matching a boolean constant against a bunch of other constants doesn't strike me as a useful construct.

    @twilsonxpert said:

    I'm mainly a .NET programmer where case statements must be constants.

    Perhaps you meant to say "C# programmer". And perhaps you also missed the fact that language constructs bundling an arbitrary number of arbitrary tests have been in use for quite some time.



  • @twilsonxpert said:

    Then I saw the case statements. Apparently, PHP allows you to put expressions in the case statements.
     

     The 'best' thing being that you can put variable assigning and other state-changing expression is the statement. Like "case ($json = $whatever) == false".

    PHP is choke full of thing that are allowed, but that nobody sane should even consider. I don't think this one is the worse one ; casting string as anything else take the cake for me.

     



  • @flabdablet said:

    @twilsonxpert said:
    First WTF, switch (true). OK, I've never done that before, but it does let you avoid writing a ton of if/else if clauses. ... Then I saw the case statements. Apparently, PHP allows you to put expressions in the case statements. I was horrified.

    If there were no expressions allowed there, what exactly would you expect switch (true) to do? Matching a boolean constant against a bunch of other constants doesn't strike me as a useful construct.

    At first I thought: flabdablet, stop trolling. But he's got a good point. How can you be surprised at expressions in case statements labels, and at the same time not be surprised at a literal in the switch statement?



  • You know, this construct is a little surprising but I'm rather cool with it.

     

    The rest of the code is still WTFish though.

    Using current() to get to the first element of $json*... assuming the returned object always has an app_id attribute... What is app_id, even, to be used like this?

    * That's assuming that's where json_decode() + is_array() leaves the internal pointer. I guess they use it has a shortcut for a more proper is_array($json) && (count($json) > 0) && is_object($json[0])



  • @toon said:

    How can you be surprised at expressions in case statements labels, and at the same time not be surprised at a literal in the switch statement?

    Personally I would have expected one case label and ten break statements.



  • I don't see anything too bad about this. It is a little unconventional and there are small issues that could be debated besides the case statement. However this is a readable way to handle data that might come as more than on type. It should not be an issue until you start to look at things like performance.



  • @SEMI-HYBRID code said:


      ob_clean();
      echo(file_get_contents($urlToTransferTo));
    

    in a true to PHP wtfy fashion.

     Serious question:

    Will this work if you point it at another server? Say, a java instance running 3rd party software inside my cluster?



  • @this_code_sucks said:

    @SEMI-HYBRID code said:

      ob_clean();
      echo(file_get_contents($urlToTransferTo));
    

    in a true to PHP wtfy fashion.

     Serious question:

    Will this work if you point it at another server? Say, a java instance running 3rd party software inside my cluster?

    Yep. As long as you have file wrappers compiled in.

    You can simplify it further by removing the parens around the echo statement.

    echo file_get_contents($url); 

    (side php wtf: echo is a language statement, print is a function whose parens are optional.

    echo (echo 1);
    is a syntax error but
    print print 1;
    prints out '11')

    Of course if you want to do it in true php wtf way you ignore all possibilities of handling errors and reduce your call to:

    @readfile($url);

  • Trolleybus Mechanic

    @this_code_sucks said:

    @Meh said:

    Will this work if you point it at another server? Say, a java instance running 3rd party software inside my cluster?

    Yep. As long as you have file wrappers compiled in.

    You can simplify it further by removing the parens around the echo statement.

    echo file_get_contents($url); 

     

    With a caveat.  Server.Transfer will transfer control to the other server. Obvious enough.

    This one will just read the contents of another file and execute it in the same instance of the original server.  IE:

    Server A has: c:\temp\hi.txt
    Server B has: c:\temp\bye.txt

    Do your file_get_contents, and get a program that lists all files in c:\temp

    Result: hi.txt

    So the answer is "yes, as long as the OP asked a completely different question"

     



  • @Lorne Kates said:

    @this_code_sucks said:

    @Meh said:

    Will this work if you point it at another server? Say, a java instance running 3rd party software inside my cluster?

    Yep. As long as you have file wrappers compiled in.

    You can simplify it further by removing the parens around the echo statement.

    echo file_get_contents($url); 

     

    With a caveat.  Server.Transfer will transfer control to the other server. Obvious enough.

    This one will just read the contents of another file and execute it in the same instance of the original server.  IE:

    Server A has: c:\temp\hi.txt
    Server B has: c:\temp\bye.txt

    Do your file_get_contents, and get a program that lists all files in c:\temp

    Result: hi.txt

    So the answer is "yes, as long as the OP asked a completely different question"

    I need something that will behave exactly like Server.Transfer :/



  • @this_code_sucks said:

    I need something that will behave exactly like Server.Transfer :/
     

    It's what you want, but I get the feeling it's not what you need.



  • This code is worse in every way than a simple if/elsif/else block.  But far easier to understand than a series of nested ternary operators (?:), which is about what I'd expect to encounter.

    Given the typical expertise level of PHP hackers, and the inability of even experienced coders in other languages to use it correctly, I'm glad there's no support for threading in PHP.  I'm sure they're planning to tack it on in the next version, though.


  • ♿ (Parody)

    @dhromed said:

    @this_code_sucks said:
    I need something that will behave exactly like Server.Transfer :/

    It's what you want, but I get the feeling it's not what you need.

    But that's just throwing away an easy Internet-argument-win!



  • @Lorne Kates said:

    @this_code_sucks said:

    @Meh said:

    Will this work if you point it at another server? Say, a java instance running 3rd party software inside my cluster?

    Yep. As long as you have file wrappers compiled in.

    You can simplify it further by removing the parens around the echo statement.

    echo file_get_contents($url); 

     

    With a caveat.  Server.Transfer will transfer control to the other server. Obvious enough.

    This one will just read the contents of another file and execute it in the same instance of the original server.  IE:

    Server A has: c:\temp\hi.txt
    Server B has: c:\temp\bye.txt

    Do your file_get_contents, and get a program that lists all files in c:\temp

    Result: hi.txt

    So the answer is "yes, as long as the OP asked a completely different question"

     

     

     

    What? Are you saying it downloads code from another server and runs it on your server? How would that even be possible?

     



  • include 'http://domain.com/afilecontainingphpcode'; Basically the same as eval(file_get_contents('http://domain.com/afilecontainingphpcode')); For fun and profit you can make a script remotely include its self using mega globals. I turn this feature

    include 'http://domain.com/afilecontainingphpcode';


    Basically the same as



    eval(file_get_contents('http://domain.com/afilecontainingphpcode'));





    For fun and profit you can make a script remotely include its self using mega globals.




    I turn this feature off on any servers I manage.

    b fucking r wtf edit

    The Daily WTF: Curious Perversions in Information Technology

  • Trolleybus Mechanic

    @briverymouse said:

    What? Are you saying it downloads code from another server and runs it on your server? How would that even be possible?
     

    I don't know. I'm probably making shit up.

    I mean-- magic.

    Wait, it's PHP.  I mean-- real_magic_escape



  • From a Lisp background, this isn't so unusual.



  • @briverymouse said:

    What? Are you saying it downloads code from another server and runs it on your server? How would that even be possible?
    It would be possible if you were eval'ing code returned by a server that serves code.

    As it is, echo file_get_contents($url); simply outputs back whatever output the code behind URL output (including HTTP envelope, I think).



  • @briverymouse said:

    What? Are you saying it downloads code from another server and runs it on your server? How would that even be possible?
     

    It's not possible; the script HTTP-calls external domain X and the server for X just parses the call and returns whatever the hell it would normally return if you made that HTTP call regardless if it's a browser, a script, or wget.



  • @boomzilla said:

    @dhromed said:
    @this_code_sucks said:
    I need something that will behave exactly like Server.Transfer :/
    It's what you want, but I get the feeling it's not what you need.

    But that's just throwing away an easy Internet-argument-win!

     

    I am really dull, actually.



  • @Rootbeer said:

    I'm glad there's no support for threading in PHP.

     

     

    You could fork. Or, when running as apache module, execute an instance of PHP running your script in CGI mode, and fork.

     





  • @dhromed said:

    @briverymouse said:

    What? Are you saying it downloads code from another server and runs it on your server? How would that even be possible?
     

    It's not possible; the script HTTP-calls external domain X and the server for X just parses the call and returns whatever the hell it would normally return if you made that HTTP call regardless if it's a browser, a script, or wget.





    +2 internets for you, for the only correct and at the same time clearly written answer



  • Re: include 'http://domain.com/afilecontainingphpcode'; Basically the same as eval(file_get_contents('http://domain.com/afilecontainingphpcode')); For fun and profit you can make a script remotely include its self using mega globals. I turn this fea

    @TheEgg said:

    include 'http://domain.com/afilecontainingphpcode';


    Basically the same as



    eval(file_get_contents('http://domain.com/afilecontainingphpcode'));




    you either have no idea what you're talking about, or you have no idea how to really say what you want to say.

    regardless of which it is, i hope you are not a server admin.



  • @SEMI-HYBRID code said:

    +2 internets for you, for the only correct and at the same time clearly written answer
    I feel offended by your implication!

    Oh wait, no I don't.



  • @dhromed said:

    I am really dull, actually.
     

    Your forehead looks shiny, though.

    @SEMI-HYBRID code said:

    i hope you are not a server admin.

    That. I couldn't understand the title/post/tags either. I just presumed it was some in joke that I wasn't privvy to.

    @dhromed said:

    It's not possible

    <pedant time>It is possible - but the target webserver would have to be configured to parse a .php file as text/plain and deliver the source, and the fetching server would need allow_url_fopen = On (or allow_url_include) in php.ini which should be disabled</edge case>[1].

    Essentially it's a glaring security hole - later versions of PHP have tightened up some of these directives, causing popular open-source packages to break or throw warnings due to their reliance upon relaxed security. Many hosting companies disable these PHP settings to prevent remote code execution.

    [1] which allowed a (friend's) wordpress installation running on one of my vhosts to be trojaned twice.



  • @Cassidy said:

    Your forehead looks shiny, though.
     

    It's rather big yeah, and there's the whole receding hairline thing. 



  • Except that this is wrong. One of two things happens. "parses the call and returns whatever the hell it would normally return" this. Or you don't have a PHP handler (or echo '<?php php code';). If you have a handler you can make a nice long distance infinite loop. If you don't the same is possible but it is hard to initiate it unless you have echo (one of the various for php ways to get its own code) but that is really a double infinite loop where the echo will never be reached. My messages are fucked up because when I go into edit them and fix something the daily wtf goes all screwy with the HTML escaping/preservation. I reckon it parses on insertion rather than on display. Hence I did not get to fix this lack of distinction previously because I was to distracted by the state of WTF over this screwy edit feature. The reason I turn it off is because of these dangers and because a lack of filtering into commands that handle file paths can cause consequences that wouldn't normally be expected. I always for the use of a lib such as curl. This can be nasty to set up but you can set it up once for most of your needs and put it in one function to the same effect but convenience except that it become explicit what you want, local FS or web, in future.



  • @TheEgg said:

    Except that this is wrong.

    No, it's not. You're actually making dhromed's point right back at him, except that the echo statement has nothing whatsoever to do with it, and neither do double infinite loops, which don't exist. Putting my facepalming at having to make the next point aside for a moment, you always have echo in PHP. Finally, more than one paragraph would be nice.


  • Infinite loops I never said you could do double infinite loops, that was kind of the point. Since you're so clever try include('http://'.$_SERVER['HTTP_HOST'].PHP_SELF);

    You can also get something like this indirectly depending what's in the evaluated code. The original statement was something like this guy couldn't believe it possible to download and execute remote code. You can. Go into your apache settings on your remote target and turn of the PHP handler. Then see what happens when you include a php url from that server. These things can have all kinds of weird unexpected outcomes like the possibility for infinite loops that bipass many of the normal checks and safeguards against those kinds of thing.

    "more than one paragraph would be nice."

    Paragraphs don't work for me unless I manually insert the br tag. If you have a problem, take it up with the site maintainer.

    Let's go back...
    "What? Are you saying it downloads code from another server and runs it on your server? How would that even be possible?

    It's not possible; the script HTTP-calls external domain X and the server for X just parses the call and returns whatever the hell it would normally return if you made that HTTP call regardless if it's a browser, a script, or wget."

    He may be wrong about the middle part but it is entirely possible, his question does not depend on the middle part being true, it is asking how would it be possible if it is true. Just eval file_get_contents or include. So he doesn't understand the difference between compiled (although this doesn't strictly make it entirely impossible) and interpreted.



  • @TheEgg said:

    but that is really a double infinite loop
     

    @toon said:

    neither do double infinite loops, which don't exist.

    @TheEgg said:

    Infinite loops I never said you could do double infinite loops

    I just stopped at that point.

     

     



  • @TheEgg said:

    but that is really a double infinite loop

    @TheEgg said:

    I never said you could do double infinite loops
     

    Yes, you did. Let's not confuse what you said with what you meant. As a developer, you should be able to say what you mean.

    Dhromed said:

    @dhromed said:

    It's not possible; the script HTTP-calls external domain X and the server for X just parses the call and returns whatever the hell it would normally return if you made that HTTP call regardless if it's a browser, a script, or wget.

    What the other person was asking was, can you include a PHP code file that resides on another server on the web. Dhromed's point was: "You can only get whatever the server decides to serve you. If that happens to be PHP code then that's what you can get. But normally PHP code would be executed instead of served up, so basically the answer to what you probably meant by your question is no." You were disagreeing with him by saying the exact same thing, except you're talking about apache handlers and eval() and double infinite loops. I think we all know it's possible if you really try to make it happen, but you're the only one trying to teach people how. For any noobs reading along: don't do this. It's a bad idea. Read a good book on PHP development instead.

    Also, I believe there are only two aspects to this discussion: including files from another server on one hand, and executing that code on the other hand. That means there is in fact no middle part.

    I'm using Firefox on a Linux box; it keeps hanging on my Flash plugin but I have no issues with the editor whatsoever. Also, if you can't write paragraphs without inserting <br> tags, why not just insert a couple?



  • @TheEgg said:

    Just eval file_get_contents or include.

    Now that I'm thinking about this, it seems to me like you don't understand the difference between eval(file_get_contents($phpfile)) and include($phpfile).

    Mods reading along, can we get a WYSIWYGy button for <code> or <pre> or something? That would be pretty sweet.



  • eval and include have some subtle differences but they are really underneath they are the same. Take this code and interpret it using the same parser and so much other stuff that is normally used. You will probably find they are more the same than they are different and to prove this if you look around you will find lists of differences not similarities.

    Sure one might want a start tag but it's not a big difference. He wanted to know how it was possible to execute remote php script. On the PHP side both will work. Yes one starts in PHP scope and the other starts in output scope. It's not a major difference. I believe he was curious about the abstract concept. Not PHP specifics. I guess if you want them to work on the same URL prepend ?> to the eval string. Not a big deal.

    "really a double infinite loop where the echo will never be reached"

    The but and this end part are critical. The point was that it doesn't work. Yes, I was thinking it through as I wrote it, not pulling it from memory hence it the progression might be confusing however, you're making a fuss over nothing. I guess you people are as bored as I am.


  • Discourse touched me in a no-no place

    @toon said:

    Mods reading along, can we get a WYSIWYGy button for <code> or <pre> or something?
    Unlikely.



  • @PJH said:

    Unlikely.
     

    Can the admins do it, then?

    s'not like they're.. erm.. not programmers, you know.

    DailyWTF fork of TinyMCE!  They should use GIT to version code and release it as TinyWTF!



  • @Cassidy said:

    @PJH said:

    Unlikely.
     

    Can the admins do it, then?

    s'not like they're.. erm.. not programmers, you know.

    DailyWTF fork of TinyMCE!  They should use GIT to version code and release it as TinyWTF!

    Or they could fork CKEditor's predecessor FCKEditor, and call it WTFCKEditor.


Log in to reply