Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

Sign in to follow this  
skin

fopen não funciona bem...

Recommended Posts

skin

Eu tenho este código para validar o se um URL é válido ou não, e até agora tinha funcionado com todos os sites... mas hoje testei não sei bem porquê com o http://www.youtube.com e retornou falso em vez de verdadeiro. Alguém me sabe indicar porquê?

function url($url) {
$estado = @fopen($url,"r");
if($estado) return true;
else return false;
}


Our lives begin to end the day we become silent about things that matter - Martin Luther King

Share this post


Link to post
Share on other sites
pmg

Bom ... se tirares o @ da função, talvez o PHP te diga porque não abriu o site :confused:

Se ele te disser que foi "Bad Request" experimenta o curl

http://php.net/curl

Ohhhhhhhhhhhhh PS

Já agora actualiza o teu código para fechar o 'resource'

$estado = @fopen();
@fclose($estado);
if () ...


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
skin

Warning: fopen(http://www.youtube.com) [function.fopen]: failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request

Sim deu bad request. O curl não queria muito visto que é necessário ter a libcurl no servidor e alguns servidores não têm e este trabalho pode ir para onde não haja e dá problemas... Talvez vá fazer é uma verificação diferente.


Our lives begin to end the day we become silent about things that matter - Martin Luther King

Share this post


Link to post
Share on other sites
pedrotuga

O fopen está a funcionar sem problemas, o servidor é que está a devolver um erro 400 ao teu pedido.

Deves ter um erro qq no teu url. Algum caracter não permitido ou algum parametro que não pode ter o valor que lhe estás a atribuir.

EDIT: pois, possivelmente isso, a falta da inclusão da path no url.

Share this post


Link to post
Share on other sites
skin

Experimenta o url com uma barra no fim (http://www.youtube.com/).

Warning: fopen(http://www.youtube.com/) [function.fopen]: failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request

The same...

Acho que vou matchar isto com regex, isto é para bem de quem utilizar por isso não têm grande vantagem em introduzir dados que não sejam válidos... :confused:


Our lives begin to end the day we become silent about things that matter - Martin Luther King

Share this post


Link to post
Share on other sites
pedrotuga

É esquisito que devolve um 400. Aqui, usando o curl devolve um 303, e redireciona para o mesmo sítio mas com 3 cookies.

~$ curl -I http://youtube.com/
HTTP/1.1 303 See Other
Date: Sun, 19 Oct 2008 04:07:42 GMT
Server: Apache
Set-Cookie: use_hitbox=72c46ff6cbcdb7c5585c36411b6b334edAEAAAAw; path=/; domain=.youtube.com
Set-Cookie: PREF=gl=US&hl=en; path=/; domain=.youtube.com; expires=Wed, 17-Oct-2018 04:07:42 GMT
Set-Cookie: GEO=4b349fedee573c4238c75ffd85d18460cwwAAAAyU0VV4IKeAI6y+kg=; path=/; domain=.youtube.com; expires=Tue, 21-Oct-2008 04:07:42 GMT
Expires: Tue, 27 Apr 1971 19:44:06 EST
Cache-Control: no-cache
Location: http://www.youtube.com/
Content-Type: text/html; charset=utf-8

Experimenta com o curl... escreve umas funções que sirvam de alternativa para o file() e para o file_get_contents() e a partir daí fazes tudo na mesma.

Mais ou menos como está aqui:

http://wiki.dreamhost.com/CURL

Share this post


Link to post
Share on other sites
skin

Não posso usar o curl porque isto vai ser para distribuir ou seja quantos menos requisitos externos melhor..


Our lives begin to end the day we become silent about things that matter - Martin Luther King

Share this post


Link to post
Share on other sites
pedrotuga

Há mais serviços de alojamento com suporte para curl do que com allow_remote_fopen ou lá como se chama a directiva.

Dito isto e tendo em conta a compatibilidade, o ideial era suportares os dois silenciosamente: se um não desse automaticamen seria usado o outro método.

Estive aqui a experimentar e não há volta a dar-lhe, o youtube envia sempre um 400. Não estive a fazer testes extensos, mas tudo me leva a crer que só aceitam pedidos por parte ce clientes com suporte para cookies. Experimenta desactivar os cookies do teu browser e ve o resultado.

Share this post


Link to post
Share on other sites
skin

Acho que vou verificar se o URL introduzido é a válido a nível da sua consituição usando regex e ponho o teste do fopen e do curl para dizer se foi verificado o seu estado online.


Our lives begin to end the day we become silent about things that matter - Martin Luther King

Share this post


Link to post
Share on other sites
pmg

Para detectares se tens o curl disponível em determinado sítio podes usar a função "function_exists"

if (function_exists('curl_init')) {
  /* usa curl */
} else {
  /* usa fopen */
}


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
djthyrax

pedrotuga, deu-te 303 porque estás a pedir youtube.com e não www.youtube.com


Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Share this post


Link to post
Share on other sites
pedrotuga

:)

pois foi, nem reparei:

 curl -I http://www.youtube.com
HTTP/1.1 200 OK
Date: Sun, 19 Oct 2008 12:06:42 GMT
Server: Apache
Set-Cookie: use_hitbox=72c46ff6cbcdb7c5585c36411b6b334edAEAAAAw; path=/; domain=.youtube.com
Set-Cookie: VISITOR_INFO1_LIVE=-QRGL0-D8VM; path=/; domain=.youtube.com; expires=Wed, 17-Oct-2018 12:06:42 GMT
Set-Cookie: PREF=gl=US&hl=en; path=/; domain=.youtube.com; expires=Wed, 17-Oct-2018 12:06:42 GMT
Set-Cookie: GEO=28e3d256efef72ae10fecd84dfe70e52cwwAAAAyU0VV4IKeANIi+0g=; path=/; domain=.youtube.com; expires=Tue, 21-Oct-2008 12:06:42 GMT
Expires: Tue, 27 Apr 1971 19:44:06 EST
Cache-Control: no-cache
Content-Length: 96824
Content-Type: text/html; charset=utf-8

Isso torna a situação mais esquisita ainda :)

Share this post


Link to post
Share on other sites
djthyrax

Mais vale usarem o wireshark para apanharem o request que estão a enviar para se poder analisar.


Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Share this post


Link to post
Share on other sites
fnds

Bem vou ter de fazer o requeste usando sockets, já mostro o resultado.

Edit:

>>> import socket
>>> s = socket.socket()
>>> s.connect(("www.youtube.com", 80))
>>> s.send("""GET / HTTP/1.1\r\nHost:www.youtube.com\r\n\r\n""")
40
>>> s.recv(10000)
'HTTP/1.1 400 Bad Request\r\nDate: Sun, 19 Oct 2008 15:29:52 GMT\r\nServer: Apache\r\nExpires: Tue, 27 Apr 1971 19:44:06 EST\r\nCache-Control: no-cache\r\nnnCoection: close\r\nTransfer-Encoding: chunked\r\nContent-Type: text/plain\r\n\r\n0\r\n\r\n'
>>> s.close()

>>> s = socket.socket()
>>> s.connect(("www.youtube.com", 80))
>>> s.send("""GET / HTTP/1.1\r\nHost:www.youtube.com\r\nUser-Agent: MeuBrowser\r\n\r\n""")
>>> s.recv(10000)
'HTTP/1.1 200 OK\r\nDate: Sun, 19 Oct 2008 15:32:49 GMT\r\nServer: Apache\r\nSet-Cookie: use_hitbox=72c46ff6cbcdb7c5585c36411b6b334edAEAAAAw; path=/; domain=.youtube.com\r\nSet-Cookie: VISITOR_INFO1_LIVE=pYypP9gcZ_g; path=/; domain=.youtube.com; expires=Wed, 17-Oct-2018 15:32:49 GMT\r\nSet-Cookie: PREF=gl=US&hl=en; path=/; domain=.youtube.com; expires=Wed, 17-Oct-2018 15:32:49 GMT\r\nSet-Cookie: GEO=ba10db1306c1a0257531a9b666beff38cwwAAAAyUFRV8KYTACFT+0g=; path=/; domain=.youtube.com; expires=Tue, 21-Oct-2008 15:32:49 GMT\r\nExpires: Tue, 27 Apr 1971 19:44:06 EST\r\nCache-Control: no-cache\r\nContent-Length: 96250\r\nContent-Type: text/html; charset=utf-8\r\n\r\n<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">\n\n\n\t<html lang="en">\n\n
(....)

Resumindo o problema é mesmo do User-Agent.

Share this post


Link to post
Share on other sites
djthyrax

O teu pedido deu bad-request, fnds, porque segundo a especificação 1.1 do protocolo tens de dizer o estado que é para ficar a ligação, salvo erro. Experimenta usar "GET / HTTP/1.0\r\nHost: www.youtube.com\r\n\r\n" e "GET / HTTP/1.1\r\nHost: www.youtube.com\r\nConnection: close\r\n\r\n"

Isto segundo o protocolo, porque sim, é possível que o YouTube te devolva um 400 por alternativa do programador.


Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Share this post


Link to post
Share on other sites
pedrotuga

400 Bad Request

The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications. 

fonte: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

Ou seja... um erro com código 400 é par aquele tipo de pedido que o dono do site não quer responder nem explicar porquê. Mas claro, para quem mantem o servidor é tecnicamente possivel enviar o que quer que seja numa qualquer dada situação.

Mas está visto, como acabou de provar o fnds, o youtube só responde com a página a quem especificar o user-agent.

Descoberto que está o problema, (skin, vas ter mesmo que usar o curl) aproveito para perguntar uma coisa:

Alguem conhece uma forma simples de enviar headers assim como o fnds fez mas sem ter que escrever um script?

Em tempos li uma forma que envolvia o uso de telnet mas já não me lembro. A libcurl é fie e permite ver os headers da resposta facilmente e mudar os headers do pedido mais ou menos facilmente... mas fixe fixe era escrever mesmo o pedido manualmente, sem  complicações.

Share this post


Link to post
Share on other sites
fnds

O teu pedido deu bad-request, fnds, porque segundo a especificação 1.1 do protocolo tens de dizer o estado que é para ficar a ligação, salvo erro. Experimenta usar "GET / HTTP/1.0\r\nHost: www.youtube.com\r\n\r\n" e "GET / HTTP/1.1\r\nHost: www.youtube.com\r\nConnection: close\r\n\r\n"

Isto segundo o protocolo, porque sim, é possível que o YouTube te devolva um 400 por alternativa do programador.

É a mesma coisa.

>>> s = socket.socket()
>>> s.connect(("www.youtube.com",80))
>>> s.send("GET / HTTP/1.0\r\nHost: www.youtube.com\r\n\r\n")
>>> s.recv(1000)
'HTTP/1.1 400 Bad Request\r\nDate: Sun, 19 Oct 2008 18:11:36 GMT\r\nServer: Apache\r\nExpires: Tue, 27 Apr 1971 19:44:06 EST\r\nCache-Control: no-cache\r\nConnection: close\r\nContent-Type: text/plain\r\n\r\n'

>>> s = socket.socket()
>>> s.connect(("www.youtube.com",80))
>>> s.send("GET / HTTP/1.1\r\nHost: www.youtube.com\r\nConnection: close\r\n\r\n")
>>> s.recv(1000)
'HTTP/1.1 400 Bad Request\r\nDate: Sun, 19 Oct 2008 18:12:12 GMT\r\nServer: Apache\r\nExpires: Tue, 27 Apr 1971 19:44:06 EST\r\nCache-Control: no-cache\r\nConnection: close\r\nTransfer-Encoding: chunked\r\nContent-Type: text/plain\r\n\r\n0\r\n\r\n'

Alguem conhece uma forma simples de enviar headers assim como o fnds fez mas sem ter que escrever um script?

Em tempos li uma forma que envolvia o uso de telnet mas já não me lembro. A libcurl é fie e permite ver os headers da resposta facilmente e mudar os headers do pedido mais ou menos facilmente... mas fixe fixe era escrever mesmo o pedido manualmente, sem  complicações.

Não estou a perceber o teu problema, "escrever mesmo o pedido manualmente, sem  complicações"?

Share this post


Link to post
Share on other sites
pmg

Alguem conhece uma forma simples de enviar headers assim como o fnds fez mas sem ter que escrever um script?

Em tempos li uma forma que envolvia o uso de telnet mas já não me lembro.

Qual é o problema do telnet?

Mas também podes usar o netcat ( http://www.rootr.net/man/info/netcat ).

$ cat conn.txt

GET / HTTP/1.1
Host: google.com

$ sed "-es/$/\r/" conn.txt | nc google.com 80

HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Sun, 19 Oct 2008 18:30:39 GMT
Expires: Tue, 18 Nov 2008 18:30:39 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
djthyrax

Dá 400 porque o youtube requer o envio do User Agent. Resolvido!


Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Share this post


Link to post
Share on other sites
pedrotuga

pmg, não é problema nenhum eu é que não me lembrava como o usar.

Mas estive a experimentar e é trivial.

Basta escrever:

telnet host porta

e depois escrever o pedido manualmente. Isto é porreiro porque dá para fazer debugging de servidores.

p@p-laptop:~$ telnet google.com 80
Trying 64.233.187.99...
Connected to google.com.
Escape character is '^]'.
GET /
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.se/">here</A>.
</BODY></HTML>
Connection closed by foreign host.

Sem complicações estva eu a dizer, porque se quero ter 100% de controlo do meu pedido não há nada melhor de que simplesmente escreve-lo. Entre usar a libcurl, recorrer a uma linguagem de programação e abrir e ler de sockets manualmente, ou usar o cat, sed, netcat, acho que é sempre menos pratico do que simlesmente escrever o header e clicar enter. Mas isto tambem já aqui estamos a dicutir promenorzitos que não interessam ao menino jesus.

Share this post


Link to post
Share on other sites
pmg

Só mais um pormenorzito que nem interessa ao menino jesus:

Com o netcat podes redireccionar o input para um ficheiro e escusas de estar sempre a escrever o pedido à mão.

Suponho que isto é impossível (agora não posso testar) com o telnet ...

nc google.com 80 < pedido.txt
telnet google.com 80 < pedido.txt


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.