Somebody Break This PHP Snippet Down for Me

fm1234

WF Mega Premium Member
Sep 8, 2007
1,405
63
0
Get destination url of a tinyUrl

^^^Looking at the code, it's hard for me as a quasi-programmer to really grasp what it's doing. I've been kicking around some ideas that this code would serve nicely if I could adapt it to other shorteners, but can't seem to get my brain wrapped around even the sample code.

Can anyone offer a concise explanation, or point me to a tutorial online?


Frank


wkmgis.jpg

30b1das.jpg

e8swg2.jpg
 


Usage

If your tinyUrl is PHP Snippets | We publish daily PHP snippets, simply pass 3xutzf3 to the function:
echo untinyUrl('3xutzf3');
function untinyUrl($tinyurl){
The name of the function is untinyurl and takes one parameter.

if($fp = fsockopen ("tinyurl.com", 80, $errno, $errstr, 30)){
Open a socket to tinyurl.com on port 80 and give it 30 seconds before timing out. The if is there to test if it's successful it'll return a value otherwise it will return FALSE and fail. $fp is the socket/file pointer

if ($fp) {
Fucking redundant, you already checked for success in the last if statement.

fputs ($fp, "HEAD /$tinyurl HTTP/1.0\r\nHost: tinyurl.com\r\n\r\n");
Makes an outbound request to the webserver, basically passes a very simple header. HEAD allows you to make a GET request but without the response body.

$headers = '';
Creates an empty $headers variable, you don't have to do this but I understand where he's coming from. If you've ever wrote C or the likes if not declared correctly it could hold random data.

while (!feof($fp)) {
Translates to: while we are not at the end of the file at file pointer $fp.

$headers .= fgets ($fp,128);
Read 128 bytes from the socket pointer $fp and append the data to $headers. Continues until their's nothing left to read because it's in the while loop.

fclose ($fp);
Close our socket.

$arr1=explode("Location:",$headers);
Splits the string on "Location:" so $arr1[0] will be everything before and including Location:, and $arr1[1] will be everything after that. Most importantly the value we are looking for will be sitting at the start of $arr1[1].

$arr=explode("\n",trim($arr1[1]));
Because there is going to be a space in front of our result we want to use trim (it removes all white space on either side of a string) on $arr[1]. We then break up the string on a new line. $arr[0] will now contain the value we need.

echo trim($arr[0]);
Again, a fairly useless trim here, but we echo our value to the screen.
 
Rage9 already nailed it, but I posted this anyway. I'm a C#/C++ dev picking up PHP.

Copy and paste this into NotePad++ or whatever PHP editor you're using:


<?php

// In this example, we'll pretend the call looks like this: untinyUrl('3xutzf3');

function untinyUrl($tinyurl){

// STEP #1.) Open a socket to port 80 (standard Web) with a 30-second timeout
// If an error occurs, store the Error Number in $errno and the Error Message in $errstr
// Notice: there's not error handling done anywhere, as this is the first and last usage
// of the err variables
if($fp = fsockopen ("tinyurl.com", 80, $errno, $errstr, 30)){

// STEP #2.) If socket was opened successfully, it will return a reference to the socket
// which can be used exactly like a filestream (using fputs)
if ($fp) {

// STEP #3.) This issues an HTTP HEAD request by writing to the stream.
// The request will actually look something like this:
//
// HEAD /3xutzf3 HTTP/1.0
// Host: tinyurl.com
//
fputs ($fp, "HEAD /$tinyurl HTTP/1.0\r\nHost: tinyurl.com\r\n\r\n");


// STEP #4.) After an fputs command, the $fp contains the response from the host
// This while loop cycles through the responds and dumps it into the "headers"
// variable in chunks of 128 bytes

$headers = '';
while (!feof($fp)) {
$headers .= fgets ($fp,128);
}

// Close the socket
fclose ($fp);
}

// STEP #5.) Parse the response headers

// This is what the response looks like in raw form:
// HTTP/1.0 301
// Moved Permanently
// X-Powered-By: PHP/5.3.3
// Location: http://phpsnippets.info
// X-tiny: cache 0.00046706199645996
// Content-type: text/html
// Connection: close
// Date: Sat, 16 Oct 2010 20:01:56 GMT
// Server: TinyURL/1.6

// The result of this explode is an array with two elements
// The two halves of the string separated by "Location:"
$arr1=explode("Location:", $headers);

// $arr1[0] contains this:
// HTTP/1.0 301
// Moved Permanently
// X-Powered-By: PHP/5.3.3

// $arr1[1] contains this:
// http://phpsnippets.info
// X-tiny: cache 0.00046706199645996
// Content-type: text/html
// Connection: close
// Date: Sat, 16 Oct 2010 20:01:56 GMT
// Server: TinyURL/1.6


// This explode separates the second half ( $arr1[1] ) by all of the newlines (\n)
$arr=explode("\n",trim($arr1[1]));

// $arr[0] contains this:
// http://phpsnippets.info
echo trim($arr[0]);
}
}

echo untinyUrl('3xutzf3');
?>


If you want to look at it from another angle:

1.) Grab a copy of Fiddler (it's free) ==> Fiddler Web Debugger - Freeware HTTP(S) debugging tool.

2.) Click on the "Request Builder" tab

3.) Choose "HEAD" and enter "http://tinyurl.com/3xutzf3" as the URL and choose "HTTP/1.0" from the last drop down list

4.) Click Execute

5.) If look in the "Raw" tab from the Request Builder, it's the same as the request above

6.) Double click the Request in the "Web Sessions" -- this will move from the "Request Builder" to the "Inspector". You should see the response with "http://phpsnippets.info"

7.) Click the "Raw" Tab right above "Response Headers" and you'll see:

HTTP/1.0 301 Moved Permanently
X-Powered-By: PHP/5.3.3
Location: http://phpsnippets.info
X-tiny: cache 0.00040102005004883
Content-type: text/html
Connection: close
Date: Sat, 16 Oct 2010 20:31:13 GMT
Server: TinyURL/1.6


Voila: same thing as above.
 
Nice post motivated. Below are the changes I would make. 1) remove the redundant if, 2) there is no point of making two trim calls here, just make one on the final output statement.

Code:
<?php
function untinyUrl($tinyurl) {
    if ($fp = fsockopen("tinyurl.com", 80, $errno, $errstr, 30)) {
        fputs($fp, "HEAD /$tinyurl HTTP/1.0\r\nHost: tinyurl.com\r\n\r\n");
        $headers = '';
        while (!feof($fp)) {
            $headers .= fgets($fp, 128);
        }
        fclose($fp);
        $arr1 = explode("Location:", $headers);
        $arr = explode("\n", $arr1[1]);
        echo trim($arr[0]);
    }
}
?>
 
Guys, thank you very much for the explanations. Some more views of the girl above, in appreciation.


Frank

29bd75h.jpg

rwjwih.jpg

2vdlnbd.jpg
 
Nice post motivated. Below are the changes I would make. 1) remove the redundant if, 2) there is no point of making two trim calls here, just make one on the final output statement.

Code:
<?php
function untinyUrl($tinyurl) {
    if ($fp = fsockopen("tinyurl.com", 80, $errno, $errstr, 30)) {
        fputs($fp, "HEAD /$tinyurl HTTP/1.0\r\nHost: tinyurl.com\r\n\r\n");
        $headers = '';
        while (!feof($fp)) {
            $headers .= fgets($fp, 128);
        }
        fclose($fp);
        $arr1 = explode("Location:", $headers);
        $arr = explode("\n", $arr1[1]);
        echo trim($arr[0]);
    }
}
?>

Indeed. I checked out the docs on fsockopen and it returns FALSE if the attempt to open the socket fails, but an object if it succeeds. Dynamic typing... interesting.
 
Indeed. I checked out the docs on fsockopen and it returns FALSE if the attempt to open the socket fails, but an object if it succeeds. Dynamic typing... interesting.

Exactly which is why the second if statement is totally redundant. if fsockopen fails the statement will return FALSE and fail.

dchuk said:
do it in C now do it in C!

Oh I have a mega surprise coming out in what I hope is only a few months away which feeds my need for C.