Archivo

Entradas Etiquetadas ‘acceso’

Publicando mensajes en Facebook sin que el usuario esté ahora mismo en la web [ modo offline ]

Viernes, 27 de Enero de 2012 Gaspar Fernández Sin comentarios

enchufe

Una de las grandes utilidades que nos da Facebook por si creamos una aplicación de escritorio, o una aplicación web que publique posts de nuestro blog automáticamente en nuestro muro, son los mensajes Offline, con este modo, no es necesario que un usuario esté identificado realmente en Facebook, aunque, debemos tener cuidado a la hora de trabajar con la aplicación, los usuarios nos han dado permiso para publicar en su nombre contenidos que nosotros generamos, por lo que debemos evitar que se pueda acceder a la publicación de contenidos directamente. Es decir, lo que voy a mostrar ahora es un mero ejemplo de cómo se haría, aunque muestro un programa que es lo más inseguro del mundo, ya que, cualquiera que entre en la dirección web especificada podrá escribir en Facebook con nuestro ID de usuario.

Creando la aplicación y practicando la publicación

Para esto, hay dos posts anteriores que te recomiendo leer si no lo has hecho ya:

Creando dos interfaces

Por un lado necesitamos la interfaz que conecta con Facebook, tal y como la hemos hecho ya en el post anterior, desde aquí se pedirá permiso para poder publicar mensajes, y para poder acceder de forma offline. Este será nuestro index.php en los ejemplos (aunque podemos cambiarlo por cualquier página que destinemos a la identificación en Facebook).

Por otro lado, necesitamos el script que realmente va a publicar texto en Facebook, este script no debe identificarse en el sistema, sólo debe enviar la publicación (será en el ejemplo publica.php)

El código fuente completo podrás verlo y descargarlo al final del post.

Pidiendo permiso

Para escribir en Facebook con el modo offline, debemos pedir el permiso, concretamente el permiso offline_access. Con este permiso la palabra clave que nos da acceso con el usuario elegido no caducará (las claves normales, sin offline access, tienen una caducidad limitada, aunque funcionarán durante un tiempo (¿minutos?) aunque el usuario haya dejado de estar activo).

Para manejar los permisos de Facebook de una mejor forma, he extendido la clase Facebook con algunos métodos que nos ayudarán a la hora de pedir permisos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?php
  /**
   *************************************************************
   * @file facebook_ext.php
   * @brief Extensión de la clase Facebook que permite manejar
   *        algunas opciones de forma más intuitiva.
   *
   * @author Gaspar Fernández <blakeyed@totaki.com>
   * @version
   * @date 14 ene 2012
   * Historial de cambios:
   *
   *
   *
   *************************************************************/


require ('facebook.php');

class FacebookExtended extends Facebook
{
  private $permissions=false;

  function __construct($config)
  {
    parent::__construct($config);
  }

  function askForPermission($ext_perm, $uid=false)
  {
    if (!$uid)
      $uid=$this->getUser();

    if (!$this->permissions)
      $this->permissions=$this->api('/'.$uid.'/permissions');
   
    if ( (isset($this->permissions['data'])) && (isset($this->permissions['data'][0])) )
      return $this->permissions['data'][0][$ext_perm];
  }

  function askForPermissions($ext_perms, $uid=false)
  {
    $permArray = explode(",", $ext_perms);

    $permissionsOk=true;

    $nElems=count($permArray);
    for ($i=0; $i< $nElems; $i++)
      {
    $ext_perm=trim($permArray[$i]);
    if ($ext_perm!='')
      {
        /* Internal debug */
        /* echo $i.'-'.$this->askForPermission($ext_perm, $uid)."<br>"; */
        $permissionsOk= ($this->askForPermission($ext_perm, $uid) && $permissionsOk);
      }
      }
    return $permissionsOk;
  }

  function loginUser($permissions)
  {
    if ($permissions)
      $loginUrl=$this->getLoginUrl(array('scope'=>$permissions));
    else
      $loginUrl=$this->getLoginUrl();

    header('Location: '.$loginUrl);
    exit;
  }

};
?>

Esta clase, se encargará de preguntar por los permisos que necesitamos de forma automática (en realidad fue como se explicó en el post anterior, aunque cuando tenemos que preguntar por varios permisos nuestro código puede crecer bastante).

Ahora, para pedir permiso haremos lo sigueinte:

1
2
3
4
$permissions = $facebook->askForPermissions('publish_stream,offline_access');
   
  if (!$permissions)
    throw new Exception('No tengo permisos suficientes', NO_PERMISSIONS);

La excepción podemos crearla como queramos, yo he seguido la técnica del post anterior, que podréis observar mejor con el código completo, lo que está claro es que el código no debe continuar pasado este punto, y debemos pedir los permisos necesarios. Además, a la hora de pedir los permisos, con la clase que hemos visto anteriormente, podemos hacer lo siguiente:

1
$facebook->loginUser('publish_stream,offline_access');

Con lo que también nos ahorramos unas líneas de código.

También, para publicar en nombre de los usuarios debemos obtener un Access Token, es una palabra de acceso única que identifica al usuario de Facebook en nuestra aplicación y nos permite interactuar, para ver esta palabra debemos hacer:

1
echo $facebook->getAccessToken();

Publicando contenido

Para publicar contenido, ahora hemos creado el archivo publica.php que sólo publicará contenido en el muro, con este archivo tenemos que tener especial cuidado, ya que en este caso, cualquiera podrá publicar contenido nada más accediendo al archivo (Código fuente de publica.php):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php

$api_key = 'Rellenar con nuestra API key';
$api_sec = 'Rellenar con nuestra API secret';

require_once('facebook_ext.php');

$facebook = new FacebookExtended(array(  
                       'appId'  => $api_key,
                       'secret' => $api_sec,
                       'cookie' => true ,
                     ));

try
{
  $destino="gaspy";     // O el nombre de usuario que queramos usar
  $public='Probando mensajes automáticos con el modo offline';
  $access_token='palabra que vimos cuando nos autorizamos, muy laarga';

  print_r( $facebook->api('/'.$destino.'/feed', 'post', array('access_token' => $access_token, 'uid' => $destino, 'message' => $public)));  
} catch (Exception $e)
{
  echo "Ocurrió un error";
}
?>

Ahora, para publicar contenido, en la llamada a la API debemos especificar:

  • uid = UID con la que queremos publicar, es decir, el usuario en nombre de quién hablamos.
  • message = Mensaje que queremos publicar
  • access_token = Palabra de acceso

Es más, podemos publicar en el muro o la página de quien queramos con esta técnica, igual que hacíamos antes, pero en este caso, lo hacemos sin que tengamos que estar identificados como ese usuario.

Código fuente de index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php

$api_key = 'Rellenar con nuestra API key';
$api_sec = 'Rellenar con nuestra API secret';

require_once('facebook_ext.php');

// Definimos códigos de error
define(NOT_INSTALLED,      1);
define(NO_PERMISSIONS,     2);
define(MALFORMED_ARRAY,   90);

$facebook = new FacebookExtended(array(  
                       'appId'  => $api_key,
                       'secret' => $api_sec,
                       'cookie' => true ,
                     ));

try
{
 
  $sesion = $facebook->getUser();
  if (!$sesion)
    throw new Exception('Aplicación no instalada', NOT_INSTALLED);

  echo "Estamos identificados en Facebook<br/>";
  echo "Usuario: ".$sesion."<br/>";

  $permissions = $facebook->askForPermissions('publish_stream,offline_access');
   
  if (!$permissions)
    throw new Exception('No tengo permisos suficientes', NO_PERMISSIONS);
 
  echo "No tienes que hacer nada, cierra esta ventana.";
}
catch (FacebookException $e)
{
  echo "Error de Facebook: ".$e->getCode().": ".$e->getMessage();
}
catch (Exception $e)
{
  switch ($e->getCode())
    {
    case NOT_INSTALLED:
      $facebook->loginUser();
      break;
    case NO_PERMISSIONS:
      $facebook->loginUser('publish_stream,offline_access');
      break;

    case MALFORMED_ARRAY:
      echo $e->getMessage();
      break;

    default:
      echo "Ocurrió un error no identificado";
    }
}
?>

Para descargar el código fuente: modooffline.tar.bz2 (1.7Kb)
Hay que incluir la API de Facebook para que funcione y sustituir $api_key y $api_sec por nuestra API Key y API secret respectivamente.

Foto: Samuel M. Livingston (Flickr)

Login a Facebook y acceso a aplicación automatizado

Miércoles, 11 de Agosto de 2010 Gaspar Fernández Sin comentarios

A medida que va creciendo Facebook, los desarrolladores van siendo más imaginativos a la hora de crear aplicaciones que trabajen sobre esta red. Actualmente existen clientes para Facebook que no necesitan que estemos dentro de la página, y lo que presento a continuación es un pequeño ejemplo de todo ello.

Este script es parte investigación / parte navegación y lectura de foros en los que no he encontrado la respuesta exacta a mis necesidades. El problema está en que, a pesar de la existencia de Facebook Connect, si queremos automatizar tareas en Facebook tenemos que estar identificados en el sistema y entonces es cuando podemos hacer la tarea en cuestión.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php

$face_cookie='/tmp/fcbk_cookie';
$useragent="Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3";
$login_email='*************';
$login_pass='**************';

function curl_load_url($url, &$error, $postfields=false)
{
  global $useragent, $face_cookie;
  $cu = curl_init();
  curl_setopt($cu, CURLOPT_URL, $url);
  curl_setopt($cu, CURLOPT_HEADER, 0);
  curl_setopt($cu, CURLOPT_FOLLOWLOCATION, 1);
  curl_setopt($cu, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($cu, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($cu, CURLOPT_USERAGENT, $useragent);
  curl_setopt($cu, CURLOPT_COOKIEJAR, $face_cookie);
  curl_setopt($cu, CURLOPT_COOKIEFILE, $face_cookie);
  if ($postfields)
    {
      curl_setopt($cu, CURLOPT_POSTFIELDS, $postfields);
      curl_setopt($cu, CURLOPT_POST, 1);
    }

  $cont=curl_exec($cu);
  $error=curl_errno($cu);

  curl_close($cu);

  return $cont;
}

function fb_login($email, $passwd)
{
  $error=false;
  curl_load_url('http://login.facebook.com/login.php', $error);

  $ch_test='&euro;,&acute;,€,´,水,Д,Є';
  $postfields='cuarset_test='.urlencode($ch_test).'&locale=es_ES&email='.urlencode($email).'&pass='.urlencode($passwd).'&pass_placeholder=&cuarset_test='.urlencode($ch_test);
  $cont=curl_load_url('https://login.facebook.com/login.php?login_attempt=1', $error, $postfields);

 /* Si hay un error de cURL lo decimos */
 if ($error)
   echo 'Error (cURL): '.$error."\n";

 /* Esta palabra *login_attempt* aparece en los intentos de login de Facebook */
 /* es raro que en la página principal salga. */
 /* Podemos también, verificar si está el enlace a editaccount.php para decir */
 /* que hemos sido identificados correctamente */
 if (strpos($cont, 'login_attempt')!==false)
/*  if (strpos($cont, 'editaccount.php')===false) */
   {
     echo 'Error (Facebook): E-mail o contraseña incorrecto';
     $err=1;
   }
 /* Si no hay errores nos daremos por identificados, aunque si el password es incorrecto */
 return (!$err);
}

if (fb_login($login_email,$login_pass)){
  $error=false;
  $cont = curl_load_url('http://apps.facebook.com/minutofilosofico/', $error);
  // Mostramos el contenido de la página
  echo $cont;
}
?>

¿Qué aplicaciones prácticas puede tener esto? Podemos hacer fácilmente un programa de escritorio para manejar Facebook, enviarnos por e-mail o un sms automáticamente si alguien que esperamos nos escribe, subir fotos de forma más rápida con un script en nuestro ordenador… o publicar un mensaje a la hora que hayamos especificado.

Como el ejemplo está en cURL será fácil portarlo a otro lenguaje con el que os sintáis más cómodos.

Extrayendo datos de direcciones web (C++ sin cURL)

Jueves, 29 de Julio de 2010 Gaspar Fernández Sin comentarios

url

En ocasiones, estamos inmersos en un proyecto que requiere conexión con un servidor.

Soy consciente de que existen muchas librerías que nos garantizan el acceso, y tienen muchas opciones aunque, a veces, no necesitamos tanto, sólo un simple acceso y un intercambio sencillo de información; del mismo modo, no nos apetece engordar demasiado nuestro ejecutable, o hacer que nuestro programa dependa de alguna librería externa.

Con esa intención, hice esta clase para C++ y que utilicé para uno de mis pequeños proyectos
hace unos años. Tengo que advertir que es una clase muy simple, y por eso también es válida para los que se quieran iniciar en programación de sockets.

Se puede descargar mysocktar (3.7Kb)

Para compilar el ejemplo:

$ g++ -c MySock.cpp
$ g++ -o ej_mysock ej_mysock.cpp MySock.o

Aún quedan cosas por hacer, sin perder el objetivo de una clase ligera, muy ligera:

  • Hacer documentación compatible con Doxygen
  • Mejor soporte para cabeceras HTML
  • Extracción de tags HTML
  • Soporte para contraseñas

Foto: Diego_3336 (Flickr)

Visita otras webs de la red