tags:

views:

709

answers:

6

I made this function to verify a user's twitter credentials. Its running on two different webservers.

<?
function twitauth($username, $password){
if(@file_get_contents("http://".$username.":".$password."@twitter.com//account/verify_credentials.xml")){
    return "1";}
else {
    return "0";}

}

?>

On my webserver, it works fine. On the other one, it ALWAYS returns 1! Even when password is intentionally wrong.

What in the world would cause one server to do one thing, and the other to do something else?

+1  A: 

Remove the '@' sign from the function to see the error message (if there is one).

Some PHP configurations don't allow opening files over the HTTP protocol, so look into cURL, or try looking up the official Twitter API to see if they have authentication functions for you to use.

mbelos
+2  A: 

When I visit that url with any combination of username/password it always returns something, whether it's auth successful or failure. file_get_contents() only returns FALSE when it fails to open the requested url.

It seems to me for your function to be successful you would have to parse the return value to determine whether or not the auth was successful.

Mike B
Maybe through the browser, but I just tried his code and `file_get_contents` returns FALSE when authentication fails (along with a warning when you unsupress the errors).
jimyi
What's the warning?
Mike B
so what would be different about the second server that would cause my issue?
Patrick
The warning: `Warning: file_get_contents(http://[email protected]//account/verify_credentials.xml) [function.file-get-contents]: failed to open stream: HTTP request failed! HTTP/1.1 401 Unauthorized`
jimyi
@Patrick: remove the @ sign and let us know if there are any warnings/errors.
jimyi
A: 

The @ symbol (error suppression) in front of file_get_contents might be suppressing an error. Try removing it and see what error you get. Also, you might be seeing different behavior on different servers due to php configuration. Specifically, the allow_url_fopen setting changes file_get_contents ability to work with URLs. Check this setting on both servers (maybe with ini_get() or find the setting in the output of phpinfo().

Asaph
If it was a problem with allow_url_fopen, file_get_contents would always return false - which is not the case here.
jimyi
Not true. file_get_contents would not even have the chance to return anything at all if there was a problem with file_get_contents. It would break out of the function with an error. The @ symbol is what would always be returning true.
Asaph
Did you try it? I actually tried this, and it returns boolean false on errors, with or without suppression, and with or without allow_url_fopen.
jimyi
Why did you downvote this when you give the same suggestion in the next question?
Garrett
I tried messing with allow_url_fopen only after I posted (thought it was a good enough lead to put out there). I'll be more diligent next time. Thanks for verifying the behavior. In any case, the main essence of my answer was in removing the @ and seeing what errors/warnings were being suppressed. That's how this will really get solved.
Asaph
A: 

Here is an updated response that isn't returning booleans as strings, and it's weird to check if its the error message before checking if its not the error message.

<?php
function twitauth($username, $password){
 $xml = @simplexml_load_file("http://". urlencode($username) .":". urlencode($password) ."@twitter.com/statuses/friends_timeline.xml");
 return ($xml->error != "Could not authenticate you.") ? true : false;
}
?>


file_get_contents() will only return the response of the page, which can be an authenticated user or a bad response, you need to use SimpleXML or what not to parse the response to determine whether or not they were authenticated. Which looks like:

<?xml version="1.0" encoding="UTF-8"?>
<user>
  <id>800316</id>
  <name>Garrett</name>
  <screen_name>garrettb</screen_name>
  <location>WHER>!, CA, USA</location>
  <description>Build websites, wants to be rich, and loves my Mac. You?</description>
  <profile_image_url>http://a1.twimg.com/profile_images/185221952/pic_normal.png&lt;/profile_image_url&gt;
  <url></url>
  <protected>false</protected>
  <followers_count>158</followers_count>
  <profile_background_color>352726</profile_background_color>
  <profile_text_color>3E4415</profile_text_color>
  <profile_link_color>D02B55</profile_link_color>
  <profile_sidebar_fill_color>99CC33</profile_sidebar_fill_color>
  <profile_sidebar_border_color>829D5E</profile_sidebar_border_color>
  <friends_count>139</friends_count>
  <created_at>Wed Feb 28 06:03:17 +0000 2007</created_at>
  <favourites_count>18</favourites_count>
  <utc_offset>-28800</utc_offset>
  <time_zone>Pacific Time (US &amp; Canada)</time_zone>
  <profile_background_image_url>http://s.twimg.com/a/1251845223/images/themes/theme5/bg.gif&lt;/profile_background_image_url&gt;
  <profile_background_tile>false</profile_background_tile>
  <statuses_count>1781</statuses_count>
  <notifications></notifications>
  <verified>false</verified>
  <following></following>
  <status>
    <created_at>Wed Sep 02 19:07:59 +0000 2009</created_at>
    <id>3716655439</id>
    <text>@lucaspatton09 take a picture, I want to see.</text>
    <source>&lt;a href=&quot;http://www.atebits.com/&amp;quot; rel=&quot;nofollow&quot;&gt;Tweetie&lt;/a&gt;</source>
    <truncated>false</truncated>
    <in_reply_to_status_id>3716512637</in_reply_to_status_id>
    <in_reply_to_user_id>59230940</in_reply_to_user_id>
    <favorited>false</favorited>
    <in_reply_to_screen_name>lucaspatton09</in_reply_to_screen_name>
  </status>
</user>

If the request is denied (bad access), it will have a authentication dialog drop down, which is probably causing you problems.

Garrett
He's not parsing the response, he's just checking if file_get_contents() returned anything or not.
jimyi
He needs to parse the response to see if it's a valid user, why are you down voting everyone with the same response? Seems silly to me.
Garrett
I'm downvoting because though they may be good suggestions, they don't solve his particular problem.
jimyi
They will solve his problem because file_get_contents will always be true because it will always return something, he needs to check his response to determine if it's a valid user, not a valid response.
Garrett
+1  A: 

I came up with an alternative solution.

<?
function twitauth($username, $password){
$xml = @simplexml_load_file("http://".$username.":".$password."@twitter.com/statuses/friends_timeline.xml");
$noway = $xml->error;
$errorcheck = "Could not authenticate you.";
if($noway == $errorcheck){
return "0";
} else {
return "1";
}

}

?>
Patrick
That's a lot of superfluous information to to fetch and parse just to find out if a username/password combination is valid. I'm still curious what was the return value of file_get_contents() with an invalid password.
Mike B
@Mike B: boolean false.
jimyi
@jimyi his original question stated that his function always returned 1, meaning file_get_contents() was returning something other than false.
Mike B
A: 

file_get_contents usually gives warning and returns nothing upon encountering http error code, but in case of your other server it probably returns body of error page (maybe it can be set up by some configuration).

Code below should work for both cases:

if(strpos(
  @file_get_contents("http://".$username.":".$password."@twitter.com//account/verify_credentials.xml"), 
  "Could not authenticate you.") === false) {
    echo "credentials ok";
} else {
    echo "credentials not ok";
}
Kamil Szot