Artículos+recientes

En defensa de los derechos fundamentales en internet

Derechos de internetAnte la inclusión en el Anteproyecto de Ley de Economía sostenible de modificaciones legislativas que afectan al libre ejercicio de las libertades de expresión, información y el derecho de acceso a la cultura a través de Internet, los periodistas, bloggers, usuarios, profesionales y creadores de internet manifestamos nuestra firme oposición al proyecto, y declaramos que:

  1. Los derechos de autor no pueden situarse por encima de los derechos fundamentales de los ciudadanos, como el derecho a la privacidad, a la seguridad, a la presunción de inocencia, a la tutela judicial efectiva y a la libertad de expresión.
  2. La suspensión de derechos fundamentales es y debe seguir siendo competencia exclusiva del poder judicial. Ni un cierre sin sentencia. Este anteproyecto, en contra de lo establecido en el artículo 20.5 de la Constitución, pone en manos de un órgano no judicial -un organismo dependiente del ministerio de Cultura-, la potestad de impedir a los ciudadanos españoles el acceso a cualquier página web.
  3. La nueva legislación creará inseguridad jurídica en todo el sector tecnológico español, perjudicando uno de los pocos campos de desarrollo y futuro de nuestra economía, entorpeciendo la creación de empresas, introduciendo trabas a la libre competencia y ralentizando su proyección internacional.
  4. La nueva legislación propuesta amenaza a los nuevos creadores y entorpece la creación cultural. Con Internet y los sucesivos avances tecnológicos se ha democratizado extraordinariamente la creación y emisión de contenidos de todo tipo, que ya no provienen prevalentemente de las industrias culturales tradicionales, sino de multitud de fuentes diferentes.
  5. Los autores, como todos los trabajadores, tienen derecho a vivir de su trabajo con nuevas ideas creativas, modelos de negocio y actividades asociadas a sus creaciones. Intentar sostener con cambios legislativos a una industria obsoleta que no sabe adaptarse a este nuevo entorno no es ni justo ni realista. Si su modelo de negocio se basaba en el control de las copias de las obras y en Internet no es posible sin vulnerar derechos fundamentales, deberían buscar otro modelo.
  6. Consideramos que las industrias culturales necesitan para sobrevivir alternativas modernas, eficaces, creíbles y asequibles y que se adecuen a los nuevos usos sociales, en lugar de limitaciones tan desproporcionadas como ineficaces para el fin que dicen perseguir.
  7. Internet debe funcionar de forma libre y sin interferencias políticas auspiciadas por sectores que pretenden perpetuar obsoletos modelos de negocio e imposibilitar que el saber humano siga siendo libre.
  8. Exigimos que el Gobierno garantice por ley la neutralidad de la Red, en España ante cualquier presión que pueda producirse, como marco para el desarrollo de una economía sostenible y realista de cara al futuro.
  9. Proponemos una verdadera reforma del derecho de propiedad intelectual orientada a su fin: devolver a la sociedad el conocimiento, promover el dominio público y limitar los abusos de las entidades gestoras.
  10. En democracia las leyes y sus modificaciones deben aprobarse tras el oportuno debate público y habiendo consultado previamente a todas las partes implicadas. No es de recibo que se realicen cambios legislativos que afectan a derechos fundamentales en una ley no orgánica y que versa sobre otra materia.

Este manifiesto, elaborado de forma conjunta por varios autores, es de todos y de ninguno. Se ha publicado en multitud de sitios web. Si estás de acuerdo y quieres sumarte a él, difúndelo por Internet.

eMule: nuevos servidores y correcciones de velocidad

eMulePor peticiones on y off-line os dejo más instrucciones sencillas para poder tener una mejor búsqueda de archivos, descarga mas rápida y mas servidores validos.

Lista de servidores actualizados:

  1. Seleccionar todas las direcciones y copiarlas.
    http://www.gruk.org/server.met
    http://www.peerates.net/servers.php
    http://usuarios.lycos.es/guillespi/server.met
    http://www.peerates.net/servers.php
    http://www.picsystems.net/emule/servermet/all_server.met
  2. servidor

  3. Hacer click en en Preferencias > Servidor > Editar...
  4. En la ventana del block de notas que aparece borrar todo el texto
  5. pulsar edición > pegar
  6. reiniciar el emule

Si se prefiere solo añadir puntualmente unos cuantos servidores, se puede hacer click en los enlaces que aparecen arriba.

Otro de los servidores mas famosos que no suele estar dentro de ninguna lista es el creado por TusSeries.com . Se trata de un servidor de emule “en beta” pero que funciona realmente bien. Para incluirlo solo hay que hacer click en el siguiente enlace: servidor de emule de TusSeries.

Tablas de velocidad
Para alcanzar la mejor velocidad de emule hay que cambiar algunos parámetros de velocidad. Los pasos son los siguientes.
hacemos el Test de velocidad para ver que velocidad alcanza realmente nuestra linea.
Según los resultados cambiamos los valores por los de la tabla siguiente.
(Situar la flecha encima de los textos subrayados de la tabla para obtener información adicional de la configuración.)

Velocidad 1MB / 300 kbps 2MB / 300 kbps 3MB / 300 kbps 4MB / 512 kbps 6MB 8MB hasta 20 megas con ADSL2+
Capacidad Descarga 100 KB/s 204 KB/s 306 KB/s 400 KB/s 612 KB/s 816 KB/s 2040 KB/s
Límite Descarga sin límite sin límite sin límite sin límite sin límite sin límite sin límite
Capacidad Subida 22 KB/s 22 KB/s 22 KB/s 35 KB/s 45 KB/s 44 KB/s 70 KB/s
Límite Subida 22 KB/s 22 KB/s 22 KB/s 45 KB/s 35 KB/s 44 KB/s 70 KB/s
Tamaño de la cola 5000 5000 5000 5000 5000 5000 5000
Conexiones máximas 1000 1000 1000 1000 1000 1000 1000
Máx. Fuentes/archivo 1000 1000 1000 1000 1000 1000 1000
Nuevas Conexiones máx.5/seg. 60 60 60 60 60 60 60
Máx. Conexiones a medio abrir 9 9 9 9 9 9 50
(tabla extraída de testdevelocidad.es)

Es importante tener los puertos abiertos para obtener una buena velocidad, es lo que se suele llamar tener una ID alta.
Al terminar hay que guardar los valores y cerrar el emule para que cargue los datos.

Filtro AntiSpam
Muchos de los servidores actuales contienen datos de Spam corruptos que impiden que obtengamos resultados al hacer búsquedas.
Para evitar que esto nos pase podemos establecer un filtro que elimine las conexiones malintencionadas y limpie los resultados finales.
para hacer esto tenemos que:
Seguridad eMule

  1. Entramos en Preferencias > Seguridad.
  2. En la seccion de Filtrar IP activamos Filtrar servidores.
  3. en Actualizar desde URL borramos el contenido y escribimos
  4. http://surfnet.dl.sourceforge.net/sourceforge/emulepawcio/ipfilter.dat y pulsamos el boton cargar.
  5. En caso de no encontrar el boton de cargar reiniciamos el emule.

Si todo funciono correctamente, el archivo .dat será actualizado y se borraran automáticamente muchos de los servidores.

Efecto con jQuery tipo LiveUp

estrellas liveUpOs acordáis de SuperMario cuando cogía una vida nueva? pues el otro día pensando en como avisar a los usuarios de alertas gráficamente sin abrir alert() o PopUp innecesarios me acorde de eso mismo.. y fruto de esa idea ha salido este código..

Se trata de una función que al ejecutarla muestra una imagen sobre el elemento indicado, desvaneciéndose y subiendo en un tiempo determinado.

Para ejecutar la función tenemos que poner como primer parámetro el identificador del objeto, ya sea el nombre del tag HTML, del ID o de la clase como en cualquier elemento jQuery es decir, si es un ID con # delante y si es una clase con . delante.
El siguiente parámetro es la dirección de la imagen que queremos que se abra cuando se ejecute la función. El tercer y cuarto valor es respectivamente el alto y ancho de la imagen que vamos a mostrar, el quinto (la variable zenit) es la altura que va a alcanzar la imagen al desaparecer (por defecto esta en 100px). El ultimo valor es el tiempo que tarda en desvanecerse el objeto seleccionado, el tiempo predeterminado es 1 segundo pero si se quiere poner uno hay que ponerlo en ms (1s = 1000).

JavaScript:
  1. function liveUp(id, img, h, w, zenit, wait){
  2.     if(img==null)      img        = 'star.png';
  3.     if(h==  null)      h    = '32';
  4.     if(w==  null)      w    = '32';
  5.     if(zenit== null)    zenit   = 50;
  6.     if(wait== null)  wait = 100;
  7.     $(id).each(
  8.         function(i, domEle){
  9.             var d         = new Date().getTime();
  10.             var liveUpId    = id+'_'+i+'_'+d; //i;'_LiVE_Up'+
  11.             liveUpId        = liveUpId.replace('#', '_');
  12.             var offset    = $(domEle).offset();
  13.             var object    = '<img id="'+liveUpId+'" src="'+img+'" height="'+h+'" width="'+w+'" />';
  14.            
  15.             $('body').append(object);
  16.            
  17.             $('#'+liveUpId)
  18.                 .animate({opacity: 1.0}, wait)
  19.                 .css({'visibility':'visible', '':''})
  20.                 .css({'position':'absolute'})
  21.                 .css({'top':offset['top'], 'left':(offset['left']+($(domEle).width()/2)-(w/2) )})
  22.                 .animate({opacity: 0.0, top: offset['top']-zenit}, 1000,
  23.                     function (){
  24.                         $('#'+liveUpId).remove();
  25.                     }
  26.                 )
  27.             ;
  28.         }
  29.     );
  30. }

Este código es una función que usa jQuery y jQuery.Easing para ejecutar los efectos base.. ha sido testado en Firefox3, Safari4 y IE7.0.5730.11IC bajo winXP.

A continuación os dejo un ejemplo. Para hacerlo funcionar solo tenéis que guardar con extensión html.

HTML:
  1. <html style="background:gray; color: white;">
  2.     <head>
  3.         <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
  4.         <script src="http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.1.3.js" type="text/javascript"></script>
  5.         <script type="text/javascript">
  6.  
  7.             function liveUp(id, img, h, w, zenit, wait){
  8.                 if(img==null)      img        = 'star.png';
  9.                 if(h==  null)      h    = '32';
  10.                 if(w==  null)      w    = '32';
  11.                 if(zenit== null)    zenit   = 50;
  12.                 if(wait== null)  wait = 100;
  13.                 $(id).each(
  14.                     function(i, domEle){
  15.                         var d         = new Date().getTime();
  16.                         var liveUpId    = id+'_'+i+'_'+d; //i;'_LiVE_Up'+
  17.                         liveUpId        = liveUpId.replace('#', '_');
  18.                         var offset    = $(domEle).offset();
  19.                         var object    = '<img id="'+liveUpId+'" src="'+img+'" height="'+h+'" width="'+w+'" />';
  20.                        
  21.                         $('body').append(object);
  22.                        
  23.                         $('#'+liveUpId)
  24.                             .animate({opacity: 1.0}, wait)
  25.                             .css({'visibility':'visible', '':''})
  26.                             .css({'position':'absolute'})
  27.                             .css({'top':offset['top'], 'left':(offset['left']+($(domEle).width()/2)-(w/2) )})
  28.                             .animate({opacity: 0.0, top: offset['top']-zenit}, 1000,
  29.                                 function (){
  30.                                     $('#'+liveUpId).remove();
  31.                                 }
  32.                             )
  33.                                    
  34.                         ;
  35.                     }
  36.                 );
  37.             }
  38.            
  39.             //direccion de la imagen... en base64 para que funcione directamente con el archivo
  40.             var url_imagen = 'data:image/png;base64,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';   </script>
  41.         <title></title>
  42.     </head>
  43.     <body>
  44.         <br /><br /><br /><br /><br /><br /><br /><br /><br />
  45.         <b id="estrella" onclick="liveUp('#estrella', url_imagen, 20, 20)">
  46.             pulsa aqui para ver como sale una estrella de 20px por 20px
  47.         </b>
  48.         <br /><br /><br /><br /><br /><br /><br /><br /><br />
  49.         <b id="logo" onclick="liveUp('#logo', 'http://www.tierra0.com/wp-content/themes/satori/images/LogoTierra0-2.gif', 100, 200, null, 200)">
  50.             pulsa aqui para ver como sale el logo de google pero mucho mas lento
  51.         </b>
  52.         <p>Ejemplo creado en tierra0.com, mas info en <a href="http://www.tierra0.com/2009/09/07/efecto-con-jquery-tipo-liveup/">tutorial de liveUp</a></p>
  53.     </body>
  54. </html>

Para problemas ruegos y preguntas los comentarios, y para donaciones, invitadme a un café ;)

Función de extracción de datos Youtube() en PHP version4

LogoYoutubePHPContinuo con el desarrollo de una nueva versión de esta función que tan famosa parece estarse haciendo.. como todo el mundo sabe su funcionamiento es muy sencillo, se le pasa una variable que puede ser la URL de un video de youtube o su ID y da como resultado un montón de datos sobre el video ordenados dentro de un array, teniendo un segundo parámetro que podemos activar en caso de error y que nos facilita información interna sobre la función..

Esta 4º versión de la función ha salido sobre todo gracias al generoso "cafe" al que me ha invitado @Tx y a los apuntes sobre errores que ha encontrado @Nach en los textos con acentos y similares. De modo que el funcionamiento general de la función es exactamente el mismo.

La otra novedad que tiene esta actualización es el modo en que se realiza la petición de datos, ya que ahora lo hace prácticamente a la misma velocidad pero indicando a youtube que somos un navegador firefox, de manera que así obtendremos los mismos datos que un navegador web normal a su misma velocidad.
Esta modificación se encuentra entre las lineas 9 y 23 de manera que si alguien tiene problemas con esta nueva manera de obtener los datos o encuentra que tiene un consumo de memoria o de tiempo mayor puede volver al modo anterior solo sustituyendo ese párrafo por query = @file_get_contents($url);.

PHP:
  1. function youtube($id, $debug = false) {
  2.     $_id = parse_url($id);
  3.     parse_str($_id['query']);
  4.     unset($_id);
  5.     $id = empty($v) ? $id : $v;
  6.  
  7.     $url = 'http://es.youtube.com/watch?v='.$id;
  8.     // Obtencion de los datos desde la web // // //
  9.     //  (si esta parte te resulta demasiado lenta sustitullela por $query = @file_get_contents($url);
  10.     $cookie = tempnam ("/tmp", "YOUTUBE");
  11.     $user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10';
  12.     $c  = curl_init($url);
  13.             curl_setopt($c, CURLOPT_COOKIEJAR,      $cookie);
  14.             curl_setopt($c, CURLOPT_COOKIEFILE,    $cookie);
  15.             curl_setopt($c, CURLOPT_FOLLOWLOCATION,  true);    // no sigue las redirecciones
  16.             curl_setopt($c, CURLOPT_HEADER,      false);   // no mostrar el header denro de la salida
  17.             curl_setopt($c, CURLOPT_RETURNTRANSFER,  1);
  18.             curl_setopt($c, CURLOPT_USERAGENT,      $user_agent);
  19.  
  20.     $query= curl_exec($c);
  21.             curl_close($c);
  22.    
  23.     // // // // // // // // // // // // // // // //
  24.    
  25.     $exp_info = '!&t=(.+)&!U';
  26.     preg_match_all($exp_info,$query,$t);
  27.    
  28.     $exp_info = "!<meta name=\"title\" content=\"(.+)\">!U";
  29.     preg_match_all($exp_info,$query,$titulo);
  30.    
  31.     $exp_info = "!<meta name=\"description\" content=\"(.+)\">!U";
  32.     preg_match_all($exp_info,$query,$descripcion);
  33.        
  34.     $exp_info = "!<span class=\"watch-video-added post-date\">(.+) de (.+) de (.+)</span>!U";
  35.     preg_match_all($exp_info,$query,$fecha);
  36.    
  37.     $exp_info = "<meta name=\"keywords\" content=\"(.+)\">";
  38.     preg_match_all($exp_info,$query,$tags);
  39.    
  40.     $exp_info = "!href=\"/user/(.+)\"!U";
  41.     preg_match_all($exp_info,$query,$user);
  42.    
  43.     $t        = $t[1][0];
  44.     $titulo   = $titulo[1][0];
  45.     $descripcion    = $descripcion[1][0];
  46.     $fecha      = ($fecha[1][0]&&$fecha[2][0]&&$fecha[3][0]) ? $fecha[1][0].' de '.$fecha[2][0].' de '.$fecha[3][0] : '';
  47.     $tags         = $tags[1][0];
  48.     $user         = $user[1][0];
  49.            
  50.     $salida["id"]         = $id;
  51.     $salida["t"]            = $t;
  52.     $salida["url"]      = $url;
  53.     $salida["iurl"]   = "http://img.youtube.com/vi/".$id."/2.jpg";
  54.     $salida["reproductor"]  = "http://www.youtube.com/p.swf?video_id=".$id."&iurl=http://img.youtube.com/vi/".$id."/2.jpg&t=".$t;
  55.     $salida["video"]        = "http://youtube.com/get_video.php?video_id=".$id."&t=".$t;
  56.     $salida["html"]   = "<object width=\"425\" height=\"350\"><param name=\"movie\" value=\"http://www.youtube.com/v/".$id."\"></param><param name=\"wmode\" value=\"transparent\"></param><embed src=\"http://www.youtube.com/v/".$id."\" type=\"application/x-shockwave-flash\" wmode=\"transparent\" width=\"425\" height=\"350\"></embed></object>";
  57.    
  58.     $salida["title"]        = utf8_decode(html_entity_decode($titulo));
  59.     $salida["descripcion"]  = utf8_decode(html_entity_decode($descripcion));
  60.     $salida["fecha"]        = $fecha;
  61.     $salida["tags"]   = utf8_decode(html_entity_decode($tags));
  62.     $salida["usuario"]    = utf8_decode(html_entity_decode($user));
  63.  
  64.     if($debug){
  65.         //sistema de diagnostico
  66.         $salida['debug']                = $query;
  67.         $s['la url de lectura es']    = $url;
  68.         $s['lectura de video']      = ($query  )    ? 'si' : 'no' ;
  69.         $s['t encontrado']        = ($t   )    ? 'si' : 'no' ;
  70.         $s['titulo encontrado']   = ($titulo      )  ? 'si' : 'no' ;
  71.         $s['descripcion encontrada']    = ($descripcion )    ? 'si' : 'no' ;
  72.         $s['fecha encontrada']      = ($fecha  )    ? 'si' : 'no' ;
  73.         $s['tags encontrados']      = ($tags    ) ? 'si' : 'no' ;
  74.         $s['usuario encontrado']        = ($user        )   ? 'si' : 'no' ;
  75.         $s['contenido para debug']    = $salida;
  76.         return  $s;
  77.     }
  78.    
  79.     if($t == ""){ //Error de conexion
  80.         return false;
  81.     } else { // todo OK
  82.         return $salida;
  83.     }
  84. }

Esta función responde un array con las variables del video siempre que el video no haya sido borrado, caso en el que devuelve false.
Un ejemplo practico.

PHP:
  1. $datos = youtube('http://es.youtube.com/watch?v=aWCD69urAqQ&fmt=18');
  2. if($datos){
  3.     foreach($datos as $nombres => $valor){
  4.         echo $nombre.' = '.$valor."<br />\n";
  5.     }
  6. } else {
  7.     echo 'el video que intentaba ver no existe';
  8. }

Si aun queda algún error solo tenéis que comentarlo ah!, y las donaciones/cafés son bienvenidas ;)

Ejemplo de upload simple para uno o varios archivos

rocketFileDado que me comentaron aun con el ultimo post que no se aclaraban muy bien como subir archivos esta vez no voy a poner una función si no un código de ejemplo para subir uno o varios archivos a nuestro servidor.
El código es muy fácil y esta muy comentado así que espero que no haya ningún problema en seguirlo o modificarlo.
Se trata de un formulario muy simple con una caja para subir el archivo y un botón de enviar. Se puede modificar y poner todas las cajas que queramos para subir todos los archivos que queramos. Como plus le he incorporado una sentencia que hace que si esa caja esta vacía no se envíe el formulario hasta que se complete.

la segunda parte hace una comprobación de si se ha enviado algún archivo para subir, si es así no pone nuestro formulario y en vez de eso pone todos los datos que podemos obtener de la subida del archivo. Si se ha enviado un archivo para subir pero ocurrió algún error, nos lo indicara también. En caso de no haber enviado nada pondrá el formulario.

Cada echo la lista de echo seguidos de comentarios son todas las variables que podemos usar en nuestro script. En caso de subir varios archivos a la vez este apartado se duplicara por cada archivo subido.

PHP:
  1. <html>
  2.     <head>
  3.         <title></title>
  4.     </head>
  5.     <body>
  6.         <?php
  7.         //formulario simple para subir el archivo (a traves de este mismo archivo)
  8.         $fomulario = '<form method="post" enctype="multipart/form-data" onsubmit="return (this.archivo.value!=\'\')">
  9.             <input type="file" name="archivo"/>
  10.             <button type="submit">Subir a la web</button>
  11.         </form>';
  12.        
  13.         //direccion donde queremos dejar el archivo
  14.         $path = './';
  15.        
  16.         //si se ha enviado uno o varios archivos no ponemos el formulario
  17.         if(count($_FILES)>0) {
  18.             //obtenemos todos los archivos uno por uno
  19.             foreach($_FILES as $name => $values){
  20.                
  21.                 //comprobamos que esten en la carpeta que nosotros queremos
  22.                 if( move_uploaded_file($values['tmp_name'],$path.$values['name']) ){
  23.                
  24.                     echo 'El archivo ha sido subido correctamente.<br/>';
  25.                     echo 'Otros datos del archivo:<br/>';
  26.                     echo 'Nombre del objeto del formulario: '.    $name.                    '<br/>';
  27.                     echo 'Nombre original del archivo: '.         $values['name'].      '<br/>';
  28.                     echo 'Tipo de archivo: '.                  $values['type'].      '<br/>';
  29.                     echo 'Nombre del archivo temporal: '.         $values['tmp_name'].   '<br/>';
  30.                     echo 'Error producido al subir el archivo: '.   $values['error'].    '<br/>';
  31.                     echo 'Tama&ntilde;o del archivo: '.    $values['size'].  '<br/>';
  32.                     echo '<br/>';
  33.                                    
  34.                 } else {
  35.                     //si no estan en la carpeta que nosotros queremos
  36.                     echo 'Ha ocurrido un error.<br/>';
  37.                
  38.                 }
  39.             }
  40.         } else {
  41.             //muestra el formulario si no se ha realizado ningun envio de archivo
  42.             echo $fomulario;
  43.         }
  44.         ?>
  45.     </body>
  46. </html>

El método de uso es muy sencillo. Copia el código de arriba, crea un archivo con extensión php, pega el codigo dentro y guardalo.
Una vez realizado esto solo tienes que cambiar el texto asociado a la variable $path de la linea 14 y poner la dirección de donde quieres que se guarden los archivos una vez en el servidor.
Un usuario "anónimo" ha echo un aporte a este articulo indicando que la función copy() no es la mas adecuada para este tipo de casos aun que sea la mas extendida entre los ejemplos. La mas adecuada es move_uploaded_file() como vemos en la linea 22 que realiza una comprobación previa de que el archivo que va a mover ha sido enviado por HTTP POST desde un formulario, y no es un archivo de dentro de nuestro servidor, evitando de esta manera problemas de seguridad.

vimeo_upload(), sube vídeos a vimeo desde tu servidor con PHP

upload_vimeoSi como a mi os gusta mas vimeo que youtube ya sea por su diseño, facilidad de uso o mayores capacidades de personalización (como la capacidad de descargar los vídeos directamente, personalización de thumbnails...) estáis de enhorabuena..

El siguiente código es capaz de subir vídeos directamente desde nuestro servidor a vimeo agregando titulo, descripción, tags y permisos de acceso. Para hacer esto y cumpliendo una pasada promesa, utilizaremos source_extract() así que es necesario que esta función también esté en el mismo archivo.

PHP:
  1. function vimeo_upload(
  2.     $file,
  3.     $mail,
  4.     $pass,
  5.     $title='',
  6.     $descripcion='',
  7.     $tags='',
  8.     $permisos=false,
  9.     $api_key='e1dfce4136d69d7f99d2a4d00c4a0d71',
  10.     $api_secret='e9ff591b0'
  11. ){
  12.    
  13.     @set_time_limit(0);
  14.     $title      = htmlentities($title,            ENT_NOQUOTES, 'UTF-8');
  15.     $descripcion    = htmlentities($descripcion,    ENT_NOQUOTES, 'UTF-8');
  16.     $cookie         = tempnam ("/tmp", "VIMEO");
  17.     $api_login_url  = "http://www.vimeo.com/log_in";
  18.     $api_rest_url   = "http://www.vimeo.com/api/rest/";
  19.     $api_auth_url   = "http://www.vimeo.com/services/auth/";
  20.     $api_upload_url = "http://www.vimeo.com/services/upload/";
  21.  
  22.     if($file){
  23.         #login
  24.         $args = array(
  25.             'sign_in[email]'    => $mail,
  26.             'sign_in[password]' => $pass
  27.         );
  28.         $login = source_extract($api_login_url, $args, '', '', true, $cookie);
  29.        
  30.         #frob
  31.         $args = $_args = array(
  32.             'api_key'   => $api_key,
  33.             'perms'  => 'write',
  34.             'format'    => 'php'
  35.         );
  36.        
  37.         $s=$api_secret; foreach($args as $k=>$v){   $s .= $k.$v;   }  $args['api_sig'] = md5($s);
  38.         $frob = source_extract($api_auth_url, '', $args, '', true, $cookie);
  39.         if(!$frob['header']['Location']){ //si aun no fue aceptada la autorizacion
  40.             $frob = source_extract($api_auth_url, $_args, '', '', true, $cookie);   #lo autorizamos por POST
  41.             $frob = source_extract($api_auth_url, '', $args, '', true, $cookie);    #y pedimos el frob de nuevo
  42.         }
  43.         $frob = substr($frob['header']['Location'], strpos($frob['header']['Location'], 'frob=')+strlen('frob=') );
  44.        
  45.         #token
  46.         $args = array(
  47.             'api_key'   => $api_key,
  48.             'format'    => 'php',
  49.             'frob'    => $frob,
  50.             'method'    => 'vimeo.auth.getToken'
  51.         );
  52.         $s=$api_secret; foreach($args as $k=>$v){   $s .= $k.$v;   }  $args['api_sig'] = md5($s);
  53.         $token = source_extract($api_rest_url, '', $args, '', true, $cookie);
  54.         $token = unserialize($token['content']);
  55.         $token = $token->auth->token;
  56.        
  57.         #tiket
  58.         $args = array(
  59.             'api_key'   => $api_key,
  60.             'format'    => 'php',
  61.             'frob'    => $frob,
  62.             'method'    => 'vimeo.videos.getUploadTicket'
  63.         );
  64.        
  65.         $s=$api_secret; foreach($args as $k=>$v){   $s .= $k.$v;   }  $args['api_sig'] = md5($s);
  66.         $tiket = source_extract($api_rest_url, '', $args, '', true, $cookie);
  67.         $tiket = unserialize($tiket['content']);
  68.         $tiket = $tiket->ticket->id;
  69.        
  70.         #upload video
  71.         $file = array('video'=>$file);
  72.         $args = array(
  73.             'api_key'   => $api_key,
  74.             'format'        => 'php',
  75.             'auth_token'    => $token,
  76.             'ticket_id'  => $tiket
  77.         );
  78.        
  79.         $s=$api_secret; foreach($args as $k=>$v){   $s .= $k.$v;   }  $args['api_sig'] = md5($s);
  80.         $upload = source_extract($api_upload_url, $args, '', $file, true, $cookie);
  81.        
  82.         #check
  83.         $args = array(
  84.             'api_key'   => $api_key,
  85.             'format'    => 'php',
  86.             'frob'    => $frob,
  87.             'method'    => 'vimeo.videos.checkUploadStatus',
  88.             'ticket_id' => $tiket
  89.         );
  90.        
  91.         $s=$api_secret; foreach($args as $k=>$v){   $s .= $k.$v;   }  $args['api_sig'] = md5($s);
  92.         $check = source_extract($api_rest_url, '', $args, '', true, $cookie);
  93.         $check = unserialize($check['content']);
  94.        
  95.        
  96.         #title
  97.         $args = array(
  98.             'api_key'   => $api_key,
  99.             'format'    => 'php',
  100.             'method'    => 'vimeo.videos.setTitle',
  101.             'title'  => $title,
  102.             'video_id'  => $check->ticket->video_id,
  103.         );
  104.        
  105.         $s=$api_secret; foreach($args as $k=>$v){   $s .= $k.$v;   }  $args['api_sig'] = md5($s);
  106.         $title = source_extract($api_rest_url, '', $args, '', true, $cookie);
  107.         $title = unserialize($title['content']);
  108.        
  109.         #caption
  110.         $args = array(
  111.             'api_key'   => $api_key,
  112.             'caption'   => $descripcion,
  113.             'format'    => 'php',
  114.             'method'    => 'vimeo.videos.setCaption',
  115.             'video_id'  => $check->ticket->video_id,
  116.         );
  117.        
  118.         $s=$api_secret; foreach($args as $k=>$v){   $s .= $k.$v;   }  $args['api_sig'] = md5($s);
  119.         $caption = source_extract($api_rest_url, '', $args, '', true, $cookie);
  120.         $caption = unserialize($caption['content']);
  121.        
  122.        
  123.         #tags
  124.         $args = array(
  125.             'api_key'   => $api_key,
  126.             'format'    => 'php',
  127.             'method'    => 'vimeo.videos.addTags',
  128.             'tags'    => $tags,
  129.             'video_id'  => $check->ticket->video_id,
  130.         );
  131.        
  132.         $s=$api_secret; foreach($args as $k=>$v){   $s .= $k.$v;   }  $args['api_sig'] = md5($s);
  133.         $tags = source_extract($api_rest_url, '', $args, '', true, $cookie);
  134.         $tags = unserialize($tags['content']);
  135.        
  136.         #privacidad
  137.         if($permisos){
  138.             $permisos = strtolower($permisos);
  139.             if( $permisos!='anybody' && $permisos!='nobody' && $permisos!='contacts' && !strpos($permisos, ',')){
  140.                 return  'ERROR: Los permisos permitidos son "nobody" para que sea privado, "anybody",'.
  141.                         ' para que sea publico, "contacts" para que solo lo puedan ver los contactos del'.
  142.                         ' usuario registrado o una lista de usuarios separada por comas para que solo esos'.
  143.                         ' usuarios puedan ver el video. (la funcion requiere que si se usa esta ultima'.
  144.                         ' opción se ponga al menos una coma final.';
  145.             }
  146.            
  147.             if(strpos($permisos, ',')) {
  148.                 $args = array(
  149.                     'api_key'   => $api_key,
  150.                     'format'    => 'php',
  151.                     'method'    => 'vimeo.videos.setPrivacy',
  152.                     'privacy'   => 'users',
  153.                     'users'  => (substr($permisos, -1)==',') ? substr($permisos, 0, -1) : $permisos,
  154.                     'video_id'  => $check->ticket->video_id,
  155.                 );
  156.             } else {
  157.                 $args = array(
  158.                     'api_key'   => $api_key,
  159.                     'format'    => 'php',
  160.                     'method'    => 'vimeo.videos.setPrivacy',
  161.                     'privacy'   => $permisos,
  162.                     'video_id'  => $check->ticket->video_id,
  163.                 );
  164.             }
  165.            
  166.             $s=$api_secret; foreach($args as $k=>$v){   $s .= $k.$v;   }  $args['api_sig'] = md5($s);
  167.             $permisos = source_extract($api_rest_url, '', $args, '', true, $cookie);
  168.             $permisos = unserialize($permisos['content']);
  169.         }
  170.        
  171.         return array(
  172.             'login'  => $login,
  173.             'frob'    => $frob,
  174.             'token'  => $token,
  175.             'tiket'  => $tiket,
  176.             'upload'    => $upload,
  177.             'check'  => $check,
  178.             'title'  => $title,
  179.             'caption'   => $caption,
  180.             'tags'    => $tags,
  181.             'privacity' => $permisos,
  182.         );
  183.     }
  184. }

Como resultado la función da un conjunto ordenado en array de las respuestas ofrecidas en cada consulta a la API de vimeo para que podamos extraer o interpretar los datos que queramos.

Para que funcione correctamente tenemos que poner las siguientes variables (en orden):

  • Dirección del archivo a subir. La dirección tiene que estar en el servidor. No se permite indicar otras paginas web por motivos de seguridad en cURL.
  • Email de la cuenta de usuario a la que se quiere subir el archivo.
  • Contraseña de la cuenta de vimeo a la que se va a subir el archivo
  • Titulo del video a subir (opcional)
  • Descripción del video (opcional)
  • Etiquetas del video, IMPORTANTE: separadas por comas (opcional)
  • Permiso de acceso al video. Los vídeos se suben como predeterminado con el permiso en nobody, lo que quiere decir que solo los puede ver el usuario que los ha subido. Los permisos que se pueden poner aquí son nobody para que sea un video privado, anybody para que sea público, contacts para que lo puedan ver solo los contactos agregados a la cuenta de vimeo en la que se sube el video o los nombres de los usuarios a los que se desea dar permiso para que puedan ver el video. Si solo se desea dar permiso a un usuario es obligatorio escribir una coma al final. (opcional)
  • Key del programa. Vimeo identifica las firmas de cada aplicación a partir de las key, así que si quieres usar esta función sin modificar esto no hay problema. La función viene ya con una key pero si quieres modificar la que tiene predeterminada para firmar tu propio programa solo tienes que ponerla aquí. (opcional)
  • Key secreta. Es el complemento a la key anterior para firmar las peticiones. si cambias el parámetro anterior es obligatorio que cambies este también por los datos de la nueva key. (opcional)

Y ahora un ejemplo simple:
Este ejemplo sube un video en mp4 llamado "gato_saltando.mp4" situado en la misma carpeta donde se ejecute al función.

PHP:
  1. $video_datos = vimeo_upload('gato_saltando.mp4', 'cuenta_de_usu@rio.com', 'SeCrEt0', 'Gato saltando!!', 'Texto que explica lo que se ve en el video. En este caso supongo que seria un gato saltando un rato....', 'gato, saltando, cat, jumping', 'anybody');
  2.  
  3. if(strpos($video_datos['upload']['content'],'stat="ok"')) {
  4.     echo 'El video se ha subido con &eacite;xito';
  5. } else {
  6.     echo 'No se pudo subir el video: '."\n";
  7.     print_r($video_datos);
  8. }

Recordad que siempre los archivos a enviar tiene que estar previamente dentro del servidor web.
Para subir los vídeos a vuestro servidor web hay muchísimos script que podéis usar.

Si alguien quiere hacer algo parecido o modificar esta función se puede sentir libre de hacerlo, y si lo deja por aquí mejor que mejor..! Solo comentar que si queréis seguir usando otras propiedades de la API de vimeo tened en cuenta que aun no se por que pero en mi experiencia el "orden" de lo introducido en la consulta es vital para evitar que aparezcan los errores Invalid "111 Signature" sin razón aparente.
Para cualquier cosa comentario.. y como mención especial no puedo dejar de agradecer al señor @edeleon la rápida y acertada respuesta en mis dudas, Gracias.
Gracias de nuevo al Sr. @edeleon he encontrado un bug que afecta a la primera vez que se intenta subir un video a una cuenta nueva... el sistema intentaba asociar la API-KEY a la cuenta y al no conseguirlo, no podia subir el video correctamente. Por esto se le ha añadido una comprobación en el apartado #frob.

Source_extract() version2, envío y extracción de datos desde PHP como si fuera un navegador

source extractLos retos se amplían y source_extract() necesitaba un nuevo enfoque para madurar y ser mas versátil, de manera que, frente a la anterior version que solo enviaba POST y usaba Cookies suplantando un navegador, esta nueva version mejora el soporte, permitiendo enviar datos por GET y POST, pudiendo enviar no solo textos si no a demás poder hacer upload de archivos, con opción de mostrar la cabecera HTTP y todo sin perder la opcion de usar cookies. El único problema es que la reestructuración de variables ha echo que no sean igual que en la anterior versión ya que se ha re-escrito casi entera.

PHP:
  1. function source_extract(
  2.         $url,
  3.         $POSTdata='',
  4.         $GETdata='',
  5.         $file_upload='',
  6.         $header=false,
  7.         $cookie=false
  8.     ){
  9.     $user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.0.9) Gecko/20061206 Firefox/1.5.0.9';
  10.    
  11.     #get
  12.     if(is_array($GETdata)){
  13.         foreach($GETdata as $k => $v){  $GETdata[$k] = $k.'='.urlencode($v)}
  14.         $GETdata = implode('&', $GETdata);
  15.     }
  16.     if($GETdata!='') $url .= strpos($url, '?') ? '&'.$GETdata : '?'.$GETdata;
  17.    
  18.     #post+files
  19.     if(is_array($POSTdata)&&!is_array($file_upload)){
  20.         foreach($POSTdata as $k => $v){ $POSTdata[$k] = $k.'='.$v;   }
  21.         $POSTdata = implode('&', $POSTdata);
  22.     } elseif(count($POSTdata)==0){
  23.         $POSTdata = array();
  24.     }
  25.     if(is_array($file_upload)){ 
  26.         foreach($file_upload as $k=>$v){
  27.             $v          = (substr($v,0,1)!='.'&&substr($v,0,1)!='/') ? './'.$v : ''.$v;
  28.             $path_v    = realpath(dirname($v));
  29.             $file_v    = basename($v);
  30.             $file_upload[$k]    = '@'.$path_v.(substr($path_v,-1)!='/' ? '/' : '').$file_v;
  31.         }
  32.         $file_upload = array_merge($POSTdata, $file_upload);
  33.     }
  34.    
  35.     $ch = curl_init($url);
  36.     if(is_array($file_upload)|| $POSTdata!=''){
  37.         curl_setopt($ch, CURLOPT_POST, 1);
  38.         curl_setopt($ch, CURLOPT_POSTFIELDS, (is_array($file_upload) ? $file_upload : $POSTdata));
  39.     }
  40.     if($cookie){
  41.         curl_setopt ($ch, CURLOPT_COOKIEJAR, $cookie);
  42.         curl_setopt ($ch, CURLOPT_COOKIEFILE, $cookie);
  43.     }
  44.     if($header){
  45.         curl_setopt ($ch, CURLOPT_HEADER, 1);
  46.     }
  47.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  48.     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (substr($url,0,5)=='https'));
  49.     curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
  50.     $_url_content = $url_content = curl_exec ($ch);
  51.     curl_close($ch);
  52.         $url_content = array(
  53.             'url'      =>$url,
  54.             'post'    =>$file_upload ? $file_upload : $POSTdata,
  55.             'content'   =>$_url_content
  56.         );
  57.     if($header){
  58.         $_url_content = explode("\r\n\r\n", $_url_content,3);
  59.        
  60.         $url_content['header']  = (count($_url_content)>2) ? $_url_content[0]."\r\n".$_url_content[1] : $_url_content[0];
  61.        
  62.         $url_content['header']  = explode("\r\n", $url_content['header']);
  63.         foreach($url_content['header'] as $k=>$v){  $o[$k] = explode(': ', $v,2); $o[$o[$k][0]] = $o[$k][1]; unset($o[$k]);   }
  64.         $url_content['header'] = $o;
  65.        
  66.         $url_content['content'] = (count($_url_content)>2) ? $_url_content[2] : $_url_content[1];
  67.     }
  68.     return $url_content;
  69. }

El primer parámetro es la URL de referencia donde queremos hacer la consulta o extraer el texto.
El segundo, y tercero son arrays que respectivamente introducen los datos a enviar por POST y GET. En ambos casos se pueden introducir tanto texto en formato campo=valor&campo2=valor o siendo un array en el que las key son los nombres de los campos a enviar y los valores los textos a enviar. Si se pretende enviar algún archivo en la petición es obligatorio que los valores que se envíen por POST estén en formato array.
El cuarto parámetro es un array de archivo/s a subir por POST a la URL de destino. El array debe tener como key los nombres de campo y como valor las direcciones donde se encuentran los archivos. Los archivos tienen que estar dentro del servidor, si se redireccióna alguno externo no se enviará correctamente.
El quinto parametro es un valor boleano de true o false, que tiene false por defecto. Si se pone a true mostrara un valor en el array de salida llamado header que contiene una array de las distintas propiedades devueltas en la consulta HTTP.
El sexto y ultimo parámetro indica la utilización de cookies. Por defecto esta en false para no ser utilizado pero si se le indica la ruta de un archivo, este actúa como un cache de cookies entre consultas almacenando valores entre estas.

Esta vez pondré en otro articulo un ejemplo mas real, por ahora aquí os va un ejemplo para probar todas las propiedades..

Creamos en la misma carpeta un archivo que se llame cookie.txt, y subimos en el mismo sitio una imagen JPG a la que cambiaremos el nombre por "imagen.jpg". Esta imagen va a ser la que vamos a "transmitir".
A continuacion creamos otro que se llame receptor.php, y en este escribimos lo siguiente.

PHP:
  1. <?php
  2. //archivo creado para comprobar si se obtienen bien los datos de get, post y files
  3. echo '////////// INICIO DEL CONTENIDO DE LA PAGINA /////////////////';
  4. $data = array(
  5.             '_GET'    => $_GET,
  6.             '_POST'  => $_POST,
  7.             '_FILES'    => $_FILES
  8. );
  9. echo '////////// FIN DEL CONTENIDO DE LA PAGINA ////////////////////';
  10. print_r($data);
  11. ?>

Este archivo nos servirá como receptor de la prueba con la que vamos a poder comprobar que datos llegan..

Por ultimo hacemos el código de la pagina propia, con el que vamos a hacer la consulta.
Ponemos el nombre que queramos a la pagina y insertamos el código a continuación.

PHP:
  1. <?php
  2. $url = 'receptor.php';
  3. $post = array('ejemplo_post'=>'Ejemplo de datos enviados por post', 'otro_ejemplo'=>32486245378934);
  4. $get = array('ejemplo_get'=>'Ejemplo de datos enviados por get', 'otro_ejemplo_por_get'=>37827489237);
  5. $file_upload = array('Nombre_de_archivo'=> './imagen.jpg');
  6. print_r(source_extract($url, $post, $get, $file_upload, true, './cookie.txt'));
  7.  
  8. /*Esta parte debeis sustituirla por el codigo de la funcion que aparece en la parte de arriba*/
  9. ?>

Hay que tener muy en cuenta que hay q sustituir el ultimo comentario por la función de arriba del todo para que el ultimo archivo se ejecute correctamente.

Cuanto tengamos todo y abramos el ultimo archivo desde el navegador veremos que nos aparecen varios datos entre los que se encontrara la cabecera, un array con todos los datos contenidos de la pagina receptor.php y los datos enviados por post, url...

Pronto tendremos un ejemplo más tangible..
A peticion del publico he realizado una corrección en la linea 78 del código de la función que activa automáticamente el soporte de SSL para las paginas web HTTPS. Si alguien tiene algún problema o incompatibilidad con esa corrección q me lo comente

Apuntes sobre APIs

ApiUna gran necesidad y oportunidad para una herramienta onlie es poder compartir sus potencia de una forma fácil con el resto de la comunidad de desarrolladores para que entre estos puedan usar los datos y capacidades de la aplicación para crear nuevos servicios. Por esto en la web 2.0 es algo totalmente necesario crear una API no solo para que otros servicios puedan acceder al nuestro si no para que inclusive nosotros podamos desarrollar y cambiar la parte gráfica de la aplicación independientemente del código que ofrece el servicio, ofreciendo las mejores prestaciones a los desarrolladores internos y externos. Por esto existen API abiertas que cualquiera puede utilizar y cerradas, que son propias y especificas dentro del servicio.

Ultimamente he visto q toda la web tiene de estas API y que cada una funciona casi de una forma, pero quería reunirme por escrito las igualdades que he ido viendo por si me puede servir en algún proyecto o para crear una propia en algun proyecto..

Al parecer entre varios estándar las web 2.0 prefieren con diferencia usar REST, la cual esta basada en la utilización de los métodos GET, POST, PUT y DELETE para el envío y recepción de información entre el usuario y el servidor, aun que este estándar no se cumple en la mayoría. El estándar primitivo indica que para subir algún archivo se debería usar PUT, y para borrarlos DELETE entre otras funciones reestablecidas, devolviendo siempre los datos en XML. Pero normalmente se usa un sistema con el que están más familiarizados el resto de desarrolladores.
Lo que se suele usar es un sistema mixto que recibe los datos por REST usando FriendlyUrl y GET, y utilizando POST para las modificaciones o para subir archivos.

Esto se suele realizar así por que es muy fácil utilizar un proxy o un programa en el servidor que realce una cache parcial de los datos si estos se pasan dentro de la URL de consulta, y es mas complejo si van acompañados de los datos en la misma cabecera...

En cuanto a las resupuestas de las aplicaciones lo que mas abunda son en XML. es un sistema facil y limpio que es facil de leer por todos los lenguajes en los que se quiera hacer el mashup. Pero el tiempo ha llevado a los creadores de API a poner alternativas con mejor rendimiento para los lenguajes estrella en la web, y casi todas se pueden traducir a jSon, un sistema para mostrar la información mucho mas liviano en aplicaciones JavaScript o PHP. Aunque para la utilización de los datos en PHP, debido a que solo desde la versión 5.0 esta soportado natívamente jSon, algunas API permiten obtener los datos convertidos por serialize() directamente para recogerlos con unserialize() de una forma rápida y liviana.

Como norma general no se suele utilizar la identificación del usuario o el almacenamiento de datos en cookies debido a que seria un obstáculo en algunos lenguajes como también lo seria para el almacenamiento en cache.

Algunos lenguajes de ejemplo:
APIs de las aplicaciones de google | code.google.com
APIs de las aplicaciones de Yahoo | developer.yahoo.com
API de vimeo | www.vimeo.com/api

Como ultimo apunte os dejo un enlace sobre como crear un motor de respuestas REST desde sematopia.com

pag(), paginación de resultados, objetos o paginas en PHP

Función pag()Algo que suele ser repetitivo en la mayoría de proyectos sobre todo si se usan bases de datos o listados de objetos, archivos, arrays... (cosa que en casi todos por no decir en todos se usa) es la paginación. La paginación como todos supongo que sabréis vale para dividir un conjunto de datos muy grande en porciones y poder navegar de esta forma entre los resultados. (si queréis ver un ejemplo solo tenéis que ir a la parte de abajo de google después de hacer una búsqueda).

Después de investigar como hacían otros este proceso me di cuenta que las soluciones mas comunes estaba solo orientadas dentro del PHP a mysql, y integraban no solo el manejo del menú de la pagina si no que a demás cortaban los objetos a mostrar o no mostrar.. cosa que no me interesaba. Yo solo quería el menú, y queria que pudiera valerme no solo para una base de datos, si no para un array o lo q fuera necesario.. :S.

La función que propongo hoy para solucionar esto es pag() la cual lo que hace es a partir de unos datos básicos introducidos como la pagina en la que se quiere estar, el numero de elementos a representar en el menú y el numero de elementos a visualizar por pagina devuelve un array con el contenido personalizado en numero de cada objeto, rango de objetos.. dando opciones a personalizar esta salida o mostrarlo con un simple enlace..

Para meternos en materia os pongo para que vale cada variable de la función por su orden:

  1. Pagina en la que se quiere estar o nombre de la variable GET o POST que va a contener el numero de pagina
  2. Total de objetos que hay en la lista a representar (total de resultados de una consulta, o de un array, o de archivos en una carpeta que queramos representar paginada)
  3. Numero de objetos que queremos que aparezcan en cada pagina
  4. Numero que indica cuantas paginas se ven en el menú generado
  5. Código HTML o texto que acompañará a cada numero.. si está vacio será representado por un enlace simple pero se puede completar con un texto HTML cualquiera. En este texto podemos insertar [p] en cada parte que deseemos que aparezca el numero de pagina. Si se inserta un array con dos textos, el primero corresponderá a los números de pagina normales y el segundo cuando la pagina sea la pagina que se está visitando.
  6. Si se desea incluir el botón "atrás" o "anterior" a partir de esta variable se puede escribir true para que aparezca un botón estándar, false para que no aparezca ningún botón o un texto HTML como en la anterior variable, en el que también se sustituirá [p] por el numero de pagina "anterior". Si el menú esta situado en la primera pagina no se mostrara este botón.
  7. Idéntico funcionamiento al anterior. Esta variable establece si queremos mostrar el botón de "pagina siguiente". Como en el anterior false o true lo activan o desactivan y un texto personalizado puede ser establecido como base, siendo sustituido [p]. (este botón no será mostrado si el menú está en el ultimo resultado.)
  8. Esta ultima variable de la función establece si se quiere mostrar un botón que lleva a la ultima pagina. Como en los anteriores, si se quiere activar el modo por defecto que incluye un enlace, solo hay que poner true, si se prefiere que no salga, false y si se quiere personalizar solo hay que poner el texto o código HTML con [p] en las zonas donde se quiere que se escriban el numero correspondiente.

Aquí va el código de la función:

PHP:
  1. function pag(
  2.     $pag_actual    = 1,     //pagina actual
  3.     $total_objetos      = 60//total de objetos a contar
  4.     $objetos_por_pagina  = 5//total de objetos por cada pagina
  5.     $objetos_por_menu      = 5,   //números que aparecerán en el menú
  6.     $texto_html   = '',
  7.     $anterior            = true,    //poner botón par anterior o texto
  8.     $siguiente        = true,   //poner botón para siguiente o texto
  9.     $final          = false   //poner la ultima pagina
  10.    
  11. ){
  12.     #argumentos adicionales para cálculos
  13.     $texto_html      = $texto_html=='' ? array('<a href="#[p]">[p]</a>', '<a>[p]</a>') : $texto_html;
  14.     $total_paginas          = ceil($total_objetos/$objetos_por_pagina);   //total de paginas
  15.     $mitad_de_objetos_por_menu    = round($objetos_por_menu/2);    //mitad del menú
  16.     $mitad_de_objetos_por_menu_baj  = floor($objetos_por_menu/2);    //mitad del menú a la baja
  17.    
  18.     #corrección de errores en pagina introducida
  19.     if(!is_numeric($pag_actual)){      $pag_actual = $_GET[$pag_actual] ? $_GET[$pag_actual] : $_POST[$pag_actual];   }
  20.     if($pag_actual<=0){     $pag_actual = 1;                }
  21.     elseif($pag_actual>$total_paginas){ $pag_actual = $total_paginas;                                                    }
  22.    
  23.     if($pag_actual<=$mitad_de_objetos_por_menu){
  24.     //detectamos si esta al principio      [desde el 1 hasta el $mitad_de_objetos_por_menu]
  25.         $debug_zone = 'inicio';
  26.         $ini = 1;
  27.         $fin = $objetos_por_menu<$total_paginas ? $objetos_por_menu : $total_paginas;
  28.     } elseif($pag_actual<=($total_paginas-$mitad_de_objetos_por_menu)){
  29.     //detectamos si esta en la zona central [desde el $mitad_de_objetos_por_menu hasta el ($total_paginas-$mitad_de_objetos_por_menu)]
  30.         $debug_zone = 'medio';
  31.         $ini = $mitad_de_objetos_por_menu_baj>$pag_actual ?
  32.             $mitad_de_objetos_por_menu_baj-$pag_actual : $pag_actual-$mitad_de_objetos_por_menu_baj;
  33.         $fin = $mitad_de_objetos_por_menu_baj+$pag_actual;
  34.     } else {
  35.     //detectamos si esta al final         [desde ($total_paginas-$mitad_de_objetos_por_menu) hasta $total_paginas]
  36.         $debug_zone = 'fin';
  37.         $ini = $total_paginas-$objetos_por_menu+1;
  38.         $fin = $total_paginas;
  39.         $final = false;
  40.     }
  41.    
  42.     //generamos el array de números necesarios para el menú
  43.     for($i=$ini;$i<=$fin;$i++){
  44.         $out['menu']['pags'][] = $i;
  45.         $out['menu']['link'][] = '<a href="?p='.$i.'">'.$i.'</a>';
  46.         if(is_array($texto_html)){
  47.             $out['menu']['html'][] = str_replace('[p]', $i, ($pag_actual==$i ? $texto_html[1] : $texto_html[0]) );
  48.         } else {
  49.             $out['menu']['html'][] = str_replace('[p]', $i, $texto_html);
  50.         }
  51.     }
  52.    
  53.     #determinamos si se puede poner anterior
  54.     if($pag_actual!=1 && $anterior){
  55.         if($anterior===true){   $anterior = $pag_actual-1;  }
  56.         $out['anterior'] = $pag_actual-1;
  57.         $out['menu']['pags'] = array_merge(array('anterior' => $pag_actual-1                                    )$out['menu']['pags']);
  58.         $out['menu']['link'] = array_merge(array('anterior' => '<a href="?p='.($pag_actual-1).'">anterior</a>'  ),    $out['menu']['link']);      if($siguiente!==true){
  59.             $out['menu']['html'] = array_merge(array('anterior' => str_replace('[p]', $pag_actual-1, $anterior) ),   $out['menu']['html']);
  60.         } elseif($siguiente!==true){
  61.             $out['menu']['html'] = array_merge(array('anterior' => '<a href="?p='.($pag_actual-1).'">anterior</a>'  ),    $out['menu']['html']);
  62.         }
  63.     } else {    unset($anterior);   }
  64.    
  65.     #determinamos si se debe poner el max final
  66.     if($final){
  67.         $out['final']                  = $total_paginas;
  68.         $out['menu']['pags']['final']      = $total_paginas;
  69.         $out['menu']['link']['final']      = '<a href="?p='.$total_paginas.'">...'.$total_paginas.'</a>';
  70.         if($final!==true){
  71.             $out['menu']['html']['final']   = str_replace('[p]', $total_paginas, $final);
  72.         } elseif($final===true){
  73.             $out['menu']['html']['final']      = '<a href="?p='.$total_paginas.'">...'.$total_paginas.'</a>';
  74.         }
  75.     } else {    unset($final);    }
  76.    
  77.     #determinamos si se puede poner siguiente
  78.     if($pag_actual!=$total_paginas && $siguiente){
  79.         $out['siguiente']                  = $pag_actual+1;
  80.         $out['menu']['pags']['siguiente']      = $pag_actual+1;
  81.         $out['menu']['link']['siguiente']      = '<a href="?p='.($pag_actual+1).'">siguiente</a>';
  82.         if($siguiente!==true){
  83.             $out['menu']['html']['siguiente']   = str_replace('[p]', ($pag_actual+1), $siguiente);
  84.         } elseif($siguiente===true){
  85.             $out['menu']['html']['siguiente']   = '<a href="?p='.($pag_actual+1).'">siguiente</a>';
  86.         }
  87.     } else {    unset($siguiente)}
  88.    
  89.     $out['ini'] = ($pag_actual*$objetos_por_pagina)-$objetos_por_pagina;    //primer objeto de la página
  90.     $out['fin'] = ($pag_actual*$objetos_por_pagina)-1;            //ultimo objeto de la página
  91.     return $out;
  92. }

La función comienza con el supuesto de que la 1º pagina es la pagina 1 (y no la cero) y el primer objeto es el 0 (no el uno) para seguir una correlación lógica entre la parte del código/consulta y la parte de la interfaz del usuario.
Si se encuentra con que la pagina es 0, o menor a 0 la sustituirá por 1 y si se encuentra que la pagina es mayor del numero total de paginas calculadas la sustituirá por la ultima pagina.

Como salida esta función da un array multidimensional que muestra las key ini que corresponde al número del primer objeto de la página, fin que corresponde al número del ultimo objeto de la pagina, y menu que contendrá a su vez en forma de array las tres formas de representación del menú pags (contiene un array con todos los números de pagina resultantes), link (que muestra un menú estándar echo de enlaces) y html (que muestra el menú personalizado a partir de los textos html).
Como opcional en cada punto y según las opciones seleccionadas, pueden aparecer adicionalmente en el array las key anterior, siguiente y final, que contendrían los botones específicos para ir a esas paginas.

Y ahora q sabemos como controlarlo todo y que sale en consecuencia vamos a hacer alguna prueba..

El primer ejemplo es el modo más simple y estático de usar la función. Usaremos los valores por defecto desactivando todos los botones adicionales para que solo aparezca el menú con enlaces estándar.

PHP:
  1. $menu = pag(
  2.     1,   //pagina actual
  3.     600,    //total de objetos a contar
  4.     6,    //total de objetos a mostrar por cada pagina
  5.     10,  //numeros que apareceran en el menu
  6.     '',  //texto personalizado a obtener
  7.     false//poner boton par anterior o texto
  8.     false//poner boton para siguiente o texto
  9.     false   //poner la ultimapagina
  10. );
  11. echo implode(' ', $menu['menu']['link'])."<br/>\n";
  12. echo 'El primer objeto seria el objeto numero '.$menu['ini'].', y el ultimo el '.$menu['fin'];

El siguiente ejemplo muestra como hacer un menu que usa p como variable GET que determina en que pagina estamos, complementando el código automático. A demás incluye los botones siguiente y anterior. ha sido personalizado para que tenga 50 objetos y muestre 5 en cada pagina, teniendo un menu de 3 numeros

PHP:
  1. $menu = pag(
  2.     'p',       //pagina actual
  3.     50//total de objetos a contar
  4.     5,    //total de objetos a mostrar por cada pagina
  5.     3,    //numeros que apareceran en el menu
  6.     '',  //texto personalizado a obtener
  7.     true,   //poner boton par anterior o texto
  8.     true,   //poner boton para siguiente o texto
  9.     false   //poner la ultimapagina
  10. );
  11. echo implode(' | ', $menu['menu']['link'])."<br/>\n";
  12. echo 'El primer objeto seria el objeto numero '.$menu['ini'].', y el ultimo el '.$menu['fin'];

El siguiente ejemplo tiene los botones persolanizado para que use la variable GET pagina para determinar en que pagina estamos a la vez que incluye el código HTML de cada botón.

PHP:
  1. $menu = pag(
  2.     'pagina',     //pagina actual
  3.     60,    //total de objetos a contar
  4.     5,        //total de objetos a mostrar por cada pagina
  5.     4,        //numeros que apareceran en el menu
  6.     '<a class="menu" href="?pagina=[p]">[p]</a>',               //texto personalizado a obtener
  7.     '<a class="menu" href="?pagina=[p]" title="anterior">&larr;</a>',   //poner boton par anterior o texto
  8.     '<a class="menu" href="?pagina=[p]" title="siguiente">&rarr;</a>'//poner boton para siguiente o texto
  9.     false            //poner la ultimapagina
  10. );
  11. echo implode(' | ', $menu['menu']['link'])."<br/>\n";
  12. echo 'El primer objeto seria el objeto numero '.$menu['ini'].', y el ultimo el '.$menu['fin'];

Como ultimo ejemplo vamos a hacer que muestra la misma estructura del anterior pero a demás, discrimina la pagina actual en el menu, y no le pone enlace para que se pueda diferenciar..

PHP:
  1. $menu = pag(
  2.     'pagina',     //pagina actual
  3.     60,    //total de objetos a contar
  4.     5,        //total de objetos a mostrar por cada pagina
  5.     4,        //numeros que apareceran en el menu
  6.     array(      //texto personalizado indicando cuando es la pagina actual
  7.         '<a class="menu" href="?p=[p]">[p]</a>',
  8.         '<a class="menu" id="actual">[p]</a>'
  9.     ),
  10.     '<a class="menu" href="?pagina=[p]" title="anterior" class="pag_normal">&larr;</a>',    //poner boton par anterior o texto
  11.     '<a class="menu" href="?pagina=[p]" title="siguiente" class="pag_actual">&rarr;</a>',   //poner boton para siguiente o texto
  12.     false            //poner la ultimapagina
  13. );
  14. echo implode(' | ', $menu['menu']['link'])."<br/>\n";
  15. echo 'El primer objeto seria el objeto numero '.$menu['ini'].', y el ultimo el '.$menu['fin'];

Que lo disfrutéis..

Función de extracción de datos Youtube() en PHP version3

Youtube()A estas alturas supongo que los que lean este blog seguramente sepan que hace esta función. Es una función que a partir de una ID de youtube extrae el resto de datos del mismo video...
El motivo de esta actualización es el aviso de @pablo que me indicaba que en la versión 1 se la función si que se obtener el usuario que ha subido el video, asi que esa ha sido la primera corrección.
Revisando el código a demás me di cuenta que la fecha también fallaba, así como el debug de fecha, y como guinda.. mucha gente esta usando la direccion de youtube completa para obtener el ID y para los usuarios menos expertos es un coñazo el extraerlo.. así que he incorporado el metodo que el genio Alex Barros diseño en Boozox y uno de sus lectores @Javier compartieron para que ahora podamos ver los vídeos no solo con la ID si no que también con la URL.

PHP:
  1. function youtube($id, $debug = false) {
  2.     $_id = parse_url($id);
  3.     parse_str($_id['query']);
  4.     unset($_id);
  5.     $id = empty($v) ? $id : $v;
  6.  
  7.     $url = 'http://es.youtube.com/watch?v='.$id;
  8.     $query = @file_get_contents($url);
  9.    
  10.     $exp_info = '!&t=(.+)&!U';
  11.     preg_match_all($exp_info,$query,$t);
  12.    
  13.     $exp_info = "!<meta name=\"title\" content=\"(.+)\">!U";
  14.     preg_match_all($exp_info,$query,$titulo);
  15.    
  16.     $exp_info = "!<meta name=\"description\" content=\"(.+)\">!U";
  17.     preg_match_all($exp_info,$query,$descripcion);
  18.        
  19.     $exp_info = "!<span class=\"watch-video-added post-date\">(.+) de (.+) de (.+)</span>!U";
  20.     preg_match_all($exp_info,$query,$fecha);
  21.    
  22.     $exp_info = "<meta name=\"keywords\" content=\"(.+)\">";
  23.     preg_match_all($exp_info,$query,$tags);
  24.    
  25.     $exp_info = "!href=\"/user/(.+)\"!U";
  26.     preg_match_all($exp_info,$query,$user);
  27.    
  28.     $t        = $t[1][0];
  29.     $titulo   = $titulo[1][0];
  30.     $descripcion    = $descripcion[1][0];
  31.     $fecha      = ($fecha[1][0]&&$fecha[2][0]&&$fecha[3][0]) ? $fecha[1][0].' de '.$fecha[2][0].' de '.$fecha[3][0] : '';
  32.     $tags         = $tags[1][0];
  33.     $user         = $user[1][0];
  34.            
  35.     $salida["id"]         = $id;
  36.     $salida["t"]            = $t;
  37.     $salida["url"]      = $url;
  38.     $salida["iurl"]   = "http://img.youtube.com/vi/".$id."/2.jpg";
  39.     $salida["reproductor"]  = "http://www.youtube.com/p.swf?video_id=".$id."&iurl=http://img.youtube.com/vi/".$id."/2.jpg&t=".$t;
  40.     $salida["video"]        = "http://youtube.com/get_video.php?video_id=".$id."&t=".$t;
  41.     $salida["html"]   = "<object width=\"425\" height=\"350\"><param name=\"movie\" value=\"http://www.youtube.com/v/".$id."\"></param><param name=\"wmode\" value=\"transparent\"></param><embed src=\"http://www.youtube.com/v/".$id."\" type=\"application/x-shockwave-flash\" wmode=\"transparent\" width=\"425\" height=\"350\"></embed></object>";
  42.     $salida["title"]        = $titulo;
  43.     $salida["descripcion"]  = $descripcion;
  44.     $salida["fecha"]        = $fecha;
  45.     $salida["tags"]   = $tags;
  46.     $salida["usuario"]    = $user;
  47.  
  48.     if($debug){
  49.         //sistema de diagnostico
  50.         $salida['debug']                = $query;
  51.         $s['la url de lectura es']    = $url;
  52.         $s['lectura de video']      = ($query  )    ? 'si' : 'no' ;
  53.         $s['t encontrado']        = ($t   )    ? 'si' : 'no' ;
  54.         $s['titulo encontrado']   = ($titulo      )  ? 'si' : 'no' ;
  55.         $s['descripcion encontrada']    = ($descripcion )    ? 'si' : 'no' ;
  56.         $s['fecha encontrada']      = ($fecha  )    ? 'si' : 'no' ;
  57.         $s['tags encontrados']      = ($tags    ) ? 'si' : 'no' ;
  58.         $s['usuario encontrado']        = ($user        )   ? 'si' : 'no' ;
  59.         $s['contenido para debug']    = $salida;
  60.         return  $s;
  61.     }
  62.     if($t == ""){ //Error de conexion
  63.         return false;
  64.     } else { // todo OK
  65.         return $salida;
  66.     }
  67. }

Un ejemplo con ID:

PHP:
  1. $datos = youtube('aWCD69urAqQ');
  2. print_r($datos);

El mismo ejemplo de antes pero esta vez con la URL completa:

PHP:
  1. $datos = youtube('http://es.youtube.com/watch?v=aWCD69urAqQ&fmt=18');
  2. print_r($datos);

He sacado una nueva version que corrige errores de peticion y caracteres. la podeis encontrar en Función de extracción de datos Youtube() en PHP version4