Planeta GNOME Hispano
La actividad Hispana de GNOME 24 x 7

06 de julio de 2014

Bloqueando el seguimiento de Facebook con Adblock Plus

Hace unos días leí en Genbeta que en Adblock Plus se podía bloquear el seguimiento que hace Facebook de nuestra navegación añadiendo la lista”Fanboy’s Annoyance List” disponible en la web de las diferentes listas de bloqueo de Adblock Plus. Esta lista, en realidad, bloquea botones “+1″, “Me gusta” y demás que podamos poner en nuestras páginas (y que permiten a Facebook y compañía hacernos seguimiento cuando navegamos por cualquier web que los incorpore).

Sin embargo, no era suficiente: veía que en muchas páginas seguía apareciendo mi usuario para introducir comentarios, con lo que entendí que Facebook estaría, de nuevo, siguiéndonos. Comprendo que a mucha gente no le apetezca que le sigan, así que busqué información y encontré la forma de arreglarlo en esta entrada del foro de Adblock Plus: se trata de bloquear los plugin “sociales” de Facebook. Y listo. Eso sí, en las páginas afectadas ya no podremos hacer comentarios.

En realidad, estos trucos los suelo tener desactivados. Pero comprendo que a mucha gente le preocupe, y con razón, el seguimiento que los grandes de Internet hagan de la actividad de los usuarios, incluso navegando fuera de sus sitios web.

Dejo abajo el vídeo. Seguro que muchos tenéis reglas para bloquear otros plugins “sociales” de Google+, twitter, Youtube y demás. Agradezco comentarios.

PD: Si te ha gustado este artículo, haz “Me gusta” ya puestos X-))

http://www.youtube.com/watch?enablejsapi=1&autoplay=0&cc_load_policy=0&iv_load_policy=1&loop=0&modestbranding=0&rel=1&showinfo=1&autohide=2&theme=dark&color=red&wmode=opaque&vq=&controls=2&" frameborder="0" type="text/html" class="__youtube_prefs__" allowfullscreen webkitallowfullscreen mozallowfullscreen >

25 de junio de 2014

C#/Cocoa – Animate a split view’s collapsing/expanding

When I started working at Xamarin, I had the intention to blog about new technologies I was learning, but it’s been already 6 months and it didn’t happen at all, so better to start late than never. I’ll start then with a nice piece of code I came up with, and which is this:

public static class CocoaExtensions
{
	public static void AnimatedSetPositionOfDivider (this NSSplitView splitView, float position, int divider)
	{
		var view0 = splitView.Subviews [0];
		var view1 = splitView.Subviews [1];

		var newFrame0 = view0.Frame;
		var newFrame1 = view1.Frame;
		if (splitView.IsVertical) {
			newFrame0.Width = position == 0 ? 0 : position - splitView.DividerThickness;
			newFrame1.Width = position == splitView.MaxPositionOfDivider (divider)
				? 0
				: splitView.Bounds.Width - position - splitView.DividerThickness;
		} else {
			newFrame0.Height = position == 0 ? 0 : position - splitView.DividerThickness;
			newFrame1.Height = position == splitView.MaxPositionOfDivider (divider)
				? 0
				: splitView.Bounds.Height - position - splitView.DividerThickness;
		}

		newFrame0.Width = newFrame0.Width < 0 ? 0 : newFrame0.Width;
		newFrame0.Height = newFrame0.Height < 0 ? 0 : newFrame0.Height;
		newFrame1.Width = newFrame1.Width < 0 ? 0 : newFrame1.Width;
		newFrame1.Height = newFrame1.Height < 0 ? 0 : newFrame1.Height;

		view0.Hidden = view1.Hidden = false;
		view0.AutoresizesSubviews = view1.AutoresizesSubviews = true;

		if ((newFrame0.Width == 0 && newFrame0.Height == 0) ||
		    (newFrame1.Width == 0 && newFrame1.Height == 0)) {
			return;
		}

		var singleAnimation0 = new NSMutableDictionary ();
		singleAnimation0 [NSViewAnimation.TargetKey] = view0;
		singleAnimation0 [NSViewAnimation.EndFrameKey] = NSValue.FromRectangleF (newFrame0);

		var singleAnimation1 = new NSMutableDictionary ();
		singleAnimation1 [NSViewAnimation.TargetKey] = view1;
		singleAnimation1 [NSViewAnimation.EndFrameKey] = NSValue.FromRectangleF (newFrame1);

		var animation = new NSViewAnimation (new NSDictionary[] { singleAnimation0, singleAnimation1 });
		animation.Duration = 0.25f;
		animation.StartAnimation ();
	}
}

The main reason to share this code is because I couldn’t find anything that worked to do that (animate the collapsing and expanding of a NSSplitView, which is, yes, you got it right, a split view, like GTK’s GtkPaned), so I hope it is useful for someone. But it also shows a few interesting things about both C# and Cocoa:

  • The most obvious one: writing Cocoa apps in C# is much better than using Objective C (although, to be honest, I also like Objective C).
  • Cocoa (and CoreAnimation) lets you easily add animations to your UI, by having the animations layer tightly integrated into the API. Of course, animations are not always great, but in some cases, like this one where the collapsing/expansion of the split view’s subviews is animated, it makes such a huge difference to the UI that it’s very nice to be able to do it that easily.
  • C# allows extending existing classes, by writing extension methods (static methods in static classes that have a “this” modifier in the 1st argument, which specifies the class the method extends). This is a great way to extend existing classes, without having to do any subclassing. Once you have the extension method, you can just call it on any NSSplitView:
    mySplitView.AnimatedSetPositionOfDivider (position, divider);
    

    You can extend any class, and this what a lot of technologies (LINQ, Reactive Extensions, etc) in the .NET world use.

I started also, when I started working at Xamarin, getting some of the nice ideas from Cocoa and C# into GLib/GTK, so will publish that as soon as I get something useful from it. Hopefully it won’t be another 6 months :-D

And yes, Xamarin is hiring. If interested, drop me a mail, or just apply directly, as you wish.

17 de junio de 2014

Frogr 0.10 released

frogrQuick post to let the world know that I’ve just released a new version of frogr right now, in order to address a few issues present in the previous version. Mainly:

  • Deprecation of non-SSL end points for the Flickr API (see these two posts for more info). From now on, frogr will use SSL-only API calls.
  • Address issues with frogr‘s AppData file. Apparently, the AppData file was neither valid (according to appdata-validate) nor being installed properly, preventing frogr from showing up nicely in the GNOME Software app.
  • Allow disabling video uploads at configuration time (enabled by default), instead of making the decision depending on the detected platform. This will hopefully make life easier for packagers of other platforms (e.g. MacPorts).
  • Removed libsoup-gnome code once and for all (API deprecated a while ago).
  • Other things: updated translations and fixed a few minor bugs.

As usual, feel free to check the website of the project in case you want to know more about frogrhow to get it or how to contribute to it.

04 de junio de 2014

Receta rápida para optimizar MySQL

Siguiendo con el post anterior (recordemos, tengo un servidor muy humilde en recursos que quiero aprovechar al máximo), le toca el turno al servidor MySQL. Tengo un libro (High Performance MySQL, de la editorial O’Reilly) que -entre otras cosas- se dedica a explicar cómo obtener el mejor rendimiento de un servidor MySQL, así que en […]

31 de mayo de 2014

Desactivando módulos innecesarios en Apache

Tengo un servidor Apache montado en una máquina física muy justita de recursos (especialmente de memoria RAM). El servidor Apache que viene por defecto tendría que cambiarlo por nginx. Por lo que dicen en los mentideros de Internet parece que consume menos recursos que Apache… mientras tomo la decisión de migrar, he optado por recortar […]

29 de mayo de 2014

Introducción a Open edX (III). Devstack

Como dijimos en el anterior post, Devstack es una instancia Vagrant diseñada para facilitar la vida a los desarrolladores de Open edX. Diferenciaremos Devstack de Fullstack en que ésta última es una instancia Vagrant diseñada para tener todos los servicios de edX en un único servidor de producción. Además, Devstack simplifica algunas características de Fullstack para hacerlo más ligero […]

27 de mayo de 2014

Introducción a Open edX (II)

La arquitectura de la plataforma edX cuenta con varios componentes, tal y como puede apreciarse en la figura adjunta. Iremos desgranando todos ellos en diferentes posts. Hoy empezaremos a tratar los dos más importantes: el LMS (Learning Management System) y el CMS (Content Management System), éste último también conocido como edX Studio. El primero (LMS) forma […]

21 de mayo de 2014

Introducción a Open edX

Los que leéis este blog ya sabéis qué es un MOOC (Massive Open Online Course). Lo que no se suele tratar tanto es la infraestructura que hay detrás. ¿Qué sistema permite ofrecer cursos masivos online con alta disponibilidad y multitud de características asociadas a estos MOOC (soporte de vídeos, subtítulos, evaluación colaborativa, distintos tipos de […]

20 de mayo de 2014

Banshee GSoC-2014 projects under Gnome umbrella

Here we are, at the beginning of a great summer!

This time, Google has given plenty of slots to the GNOME project, so we could accept many participants, including 3 brilliant students to work on the Banshee project. In case they haven't blogged about it, or didn't give much detail, I'll elaborate a bit about what they will be aiming to do these months:

  • Nicholas Little will be working on creating a new extension for Bluetooth synchronization, and if time permits, refactoring our MTP support. In regards to the latter, if you have an Android phone you might have experienced some bugs getting it to work with Banshee lately (our MassStorage synchronization support is great, but the latest versions of Android have been deprecating this mode in favour of MTP, which we never supported very well); we have been working hard on fixing them, but Nicholas is going to try to give it that extra push at the end of the summer, which I'm confident he will do very well (he was the developer who brought Symbian support for the masses -or rather, for his Nokia N95 ;) -, on Banshee 2.9.0). And you may be wondering, why do we need Bluetooth sync? Well, we understand that it's much slower than USB or Wifi, but:
  1. USB can work for the first sync, but whenever you update your library, I never remember to connect my phone again with my cable, or I'm too lazy to do it. Now imagine that whenever your phone is near your computer (and of course if you have Banshee running), they could negotiate together to update the sync without the need of moving a finger!
  2. Wifi could work also for the use case I just explained, but getting Wifi to work, compared to Bluetooth, would involve creating an app for the phone that could talk with Banshee. And we all know what are the problems associated with that: we would need to be cross-platform for at least the 3 main mobile platforms out there (well, iOS wouldn't even work neither with this nor with Bluetooth, because there are no public APIs to integrate with the music database of the OS, sigh iTunes...), and that means a lot of maintenance burden (even if we choose a same-language native platform like Xamarin), and a user experience that is not so seamless (as it would require the user to install an app first).
  • Marcin Kolny, which has convinced us that he will do a great job given his great patches and the fact that he's already very involved in opensource (maintainer of C++ bindings to GStreamer if I recall correctly), will be working on integration with AcoustID. To summarize it very bluntly, AcoustID is the open-source alternative to Shazam, so thanks to this, if you have many tracks in your library which didn't get ripped properly with tags, or you got from some friend which is not very metadata-driven ;) then you will be able to fix this situation! We will be likely reusing the MetadataFixer extension that we already have in Banshee, to not reinvent the UI wheel.
  • Dmitriy Petukhov, a very motivated Russian student, will be helping us get two extensions in shape, which were developed in the last GSoC (more details about this in my previous blog post), but were not ready for mainstream yet. The FanArt.TV extension, which retrieves artist logos and shows them next to your album icons, needs some caching (we could even violate FanArt.TV service's ToS if we don't do this) and UI polish (our ListView widget doesn't play well with differently-sized images, so we need to modify this custom GTK widget to allow rendering rows with different heights). The SongKick extension works great, but also needs caching, and it especially needs GeoLocation to maybe even work autonomously (imagine, you don't even know what SongKick is, and because you installed the banshee-community-extensions package of your distro, you suddenly get told that one of your favorite bands is soon playing a gig near your city!).
As you can see, most things are work under-the-hood this year, with little UI work. That's good for me because I'm no design expert. However, there is one area which we could do with some help: the new backgound tasks that will be implemented will need a way to notify the user (i.e. SongKick: when a new gig is discovered; AcoustID: when new/better metadata is found). In this respect, maybe Hylke Bons (our chief designer for the last Gnome .NET hackfest) and Garrett LeSage (assistance that Hylke proposed now to avoid getting himself swamped!) will be able to help! (BTW, if you're interested in participating in this year's Gnome .NET hackfest, message David Nielsen, which started to plan it recently.)

I'm very happy about starting the mentoring of these projects this year. And I'm specially jealous about my students... I became mentor of GSoC myself without being GSoC student first! (Maybe I should switch roles in the future?)

Wish them good luck! It was actually just yesterday when GSoC really started! (gotta love mondays)

UPDATE: Fixed embarrassing typo: I meant AcoustID, not OpenID!

09 de mayo de 2014

A late devX hackfest report, gestures

Last week the developer experience hackfest took place in Berlin. Quite some blogging has happened during and since, nonetheless this was a pretty good excuse to blow the cobwebs off my blog and chime in too :).

The event was quite intense, plenty of discussion happened around the GNOME platform, developer tools, API documentation generation, and introspection. My main point of interest there was GTK+, it was great to see a roadmap shape up, and a consensus about the gestures branch (more about that below). I also offered to look into doing something that could replace GtkNotebook in the future, which I started hacking on during the hackfest. I also had a nice opportunity to chat with Philip about Freebase support in libgdata, and solve a few questions around Tracker.

Other than that, nice chatting, and a very fine choice of places for food and beverages. Many thanks to Chris Kühl and the Endocode guys for making this as much enjoyable!

Gestures

One point in the GTK+ meeting agenda was gesture support. The gestures branch (which has had a somewhat intermitent history during the last ~2.5 years) has lately shaped up into something that was agreed mergeable for 3.14. This branch introduces “gesture” objects that abstract away all the intricacies of (multi)touch management. These objects handle events, tracking individual touches, when gestures enters in a “recognized” state, high-level signals will be emitted. This has been made to work parallelly to regular event delivery, in order to allow for different degrees of interoperation with handlers there, and making single-touch gestures to work with pointer events is just a call away.

There is of course a need of cooperation between gestures, both within a widget, and across the widget “stack” that’s receiving events for each individual touch, each of those will be triggering a number of gesture objects as the touchpoint moves. To cater for that, gestures have a none/claimed/denied state on each tracked touch, and changes in those are communicated across the stack (possibly causing cancellation on child widgets also handling the touchpoint, or cancelling other same-level gestures that previously claimed the sequence).

Intra-widget, some simultaneity may be wanted when handling touchpoints (eg. long press and nth-click handling), gestures may be grouped so those share the same state and can act upon the same events, a widget can have multiple mutually-exclusive gesture groups (eg. scrolling and “switch page” panning on a scrolledwindow).

So that is it! in a very tiny nutshell, the API added in the branch is documented, that will be a more accurate source :). Now, a video showcasing this, unedited because Pitivi didn’t get along today. A 42 seconds journey from well-known lands to barren plains of insanity, made manageable thanks to this branch:

The branches for eog and evince are available too, for anyone willing to play soon with this. But as said, hopefully everything will be soon in master!

05 de mayo de 2014

GSoC 2013 with Gnome

So let this be a belated report about previous GSoC! sorry for the delay.

In summer 2013, Tomasz Maczynski worked on Banshee as a GSoC student, and he did great work! He developed a SongKick extension, and a FanArt.tv one. Both were worked on in the banshee-community-extensions repository. They work very well but there are a few downsides about this work, which we didn't have time to fix:
  • The FanArt.TV extension depended on some Banshee API that hasn't been added yet to mainline. The patch to add it lived in bugzilla for a while, in a bug about a feature request to have images in the artist list. The reason for not committing the patch even if I had already reviewed it was because I was wary about it, since it allowed FanArt.TV to hook its ArtistList widget, but wouldn't be really extension friendly. What I mean is that if there was other extension that wanted to also attach a different ArtistList, it would conflict with FanArt extension when enabled at the same time. The ideal thing would be to expose this functionality as an extension point, so that if more than one extension attached a new kind of ArtistList widget, the user could switch between the two from the UI when both extensions were enabled. When I mentioned this in the bug, awesome Banshee-extension developer Frank Ziegler jumped in and created the extension interface necessary for this. I've been reviewing the patches in the last days (couldn't do it before because I really wanted to release 2.9.1 and 2.6.2 versions before landing this work) and I'll likely commit them this week.
  • The FanART.TV extension uses Hyena's ListView widget to show images. This is the main widget that Banshee uses for showing the tracks in the main view. It's a great custom widget because it allows very fast rendering of data coming from an SQLite database, but it wasn't optimized for rendering images. The main disadvantage of it is in the case that images have different heights, because the ListView will just allocate a height for each row equal to the tallest of the images used. This means that the widget shown could be a bit ugly if you have many artists in your library and some of them have very differently sized images. Tomasz worked on this a bit, but couldn't finish it because of lack of time (we have a WIP patch). But fortunately this will be fixed this summer!
  • Both SongKick and FanArt.TV don't implement caching yet. This is not only important to save bandwidth from the point of view of the client, but also from the point of view of the server! (We could even violate their ToS if we didn't implement this, IIRC.) Fortunately this will be fixed this summer!
  • SongKick extension provides several ways to discover gigs: searching by city, by artist, etc. It even suggests you artists extracted from your library that composed songs which you marked with a high rating! But IMO this is not enough, SongKick extension should even be smarter and query ahead of time looking for your favorite artists *and* near your area (doing the latter via GeoLocation). Fortunately this will be fixed this summer! (and we will use Gnome infrastructure for it)

That is all folks! Stay tuned for the next blog post, which will explain the plan for GSoC 2014 (this year I get to mentor three students!).

03 de mayo de 2014

Belated Gnome .NET Hackfest post

OMG, I should feel embarrassed about posting such a belated blog post (yes, the hackfest was more than 6 months ago), but oh well, at least I can say I have enough excuses:
  • I got my house refurbished in the last months, which has been such a long planning endeavour, and a real stressful PITA while it was being done.
  • Before the above started, and after it was finished, I had to move, so that's 2 moves! (I hate moving)
  • I've been kind of busy in regards to Gnome-related contributions: we released Banshee 2.6.2, GStreamer-Sharp 0.99.0, Banshee 2.9.1, and a big etcetera (including pre-mentoring for GSoC! more about that in a subsequent post).
So this doesn't leave enough room for blogging, which is a necessary but a less appealing task. But I have to say it somewhere: the hackfest that David Nielsen organized was amazing, the best kind I have attended so far, as I came to meet for the first time some awesome hackers such as him, and:
  • Hylke Bons, sparkleshare creator, Red Hat designer.
  • Mirco Bauer, smuxi creator and debian developer (mono packager).
  • Jo Shields, debian developer (mono packager), Collabora sysadmin.
  • Robert Nordan, Pinta contributor.
  • Jared Jennings, Tomboy contributor.
  • Stephen Shaw, ex-Novell coworker (build developer), and currently at Xamarin. (Yes, I was Stephen's team-mate when at Novell, but had never met him in person!)
  • Stefan Hammer, Tomboy contributor and hackfest local-host.
  • Timo Dörr, Tomboy and Banshee contributor, GSoC student.
  • Stephan Sundermann, GSoC student for GStreamerSharp and Bindinator.

(BTW I didn't include the awesome Bertrand Lorentz, fellow Banshee co-maintainer and GtkSharp gatekeeper, in the list, because I had already met him before, it wasn't my first time!).

And it was with the latter Stephan (not Stefan) the one I ended up spending more time with, because we decided to work on the new GStreamerSharp bindings since the 2nd day of the hackfest (the 1st day I mainly worked with Bertrand to release Banshee 2.9.0, our first Gtk3 compatible release, which he already blogged about).

So what was special about this work?
  • GStreamerSharp 0.10.x releases were not compatible with GStreamer 1.x releases, so this had to be fixed soon. However, much of the architecture of this old version of the bindings used many manually crafted binding code.
  • Stephan, by using the new Bindinator (a GObjectIntrospection metadata parser that outputs GAPI metadata, that allows generating .NET bindings, created by Andreia Gaita) in his GSoC, created a better foundation for the new bindings.
  • He targetted GI metadata from GStreamer 1.0 and 1.2 versions (the jump from 0.10 to 1.0 was a big and not easy leap, since lots of APIs were modified and deprecated).
  • We needed to polish them enough to make Banshee be able to consume them without glitches.
"Polish" sounds like easy work, but it wasn't. We fixed lots of crashes, and we contributed fixes to GObject-Introspection metadata upstream. And we proposed big patches for the gtk-sharp GAPI generator. And of course we updated our Banshee managed playback backend to the new GStreamerSharp API.

Main kudos should go to him though. I mainly added Banshee expertise, gtk-sharp contributing expertise, and lots of motivation (or at least I thought).

We had a big success: a Banshee playing audio with GStreamerSharp. Unfortunately video playback was freezing. But some months later after the hackfest we fixed it, and we released first GStreamerSharp 1.0 preview, which we called "0.99.0", and we released the first Banshee release that depends on this work: 2.9.1.

And it was my first time in Austria (and in Vienna). Overall a great experience, and I need to mention our awesome sponsors:


The GNOME Foundation, providers of the GNOME desktop


The University of Vienna and the Institute for Theoretical Chemistry, our venue sponsors

Collabora Ltd, Open Source Consulting

Norkart AS, Norway’s premier supplier of Geographic Information Systems and related consulting


Novacoast IT, Professional Services and Product Development

 
Hotel Schottenpoint, our hotel partner

28 de abril de 2014

Tu país también se merece otra bandera

Porque la República Checa también se merece otra bandera, con sus estereotipos y su todo:

 New flag of the Czech Republic

La todopoderosa cerveza.
Los malditos knedliky.
Los cutres zapatos que casi todos llevan en el trabajo.

Etiquetas: , ,

11 de abril de 2014

09 de abril de 2014

perl: warning: Setting locale failed

Conectamos por ssh contra nuestro servidor, lanzamos un comando erróneo y aparte del mensaje de error el intérprete de comandos nos suelta el siguiente sermón: # comando erróneo perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LANGUAGE = (unset), LC_ALL = (unset), LC_PAPER = "es_ES.UTF-8", LC_ADDRESS = "es_ES.UTF-8", LC_MONETARY = […]

08 de abril de 2014

Parchear Ubuntu para evitar el bug OpenSSL Heartbleed

Ayer a la tarde se levantó una buena polvareda con el bug Heartbleed de OpenSSL. Básicamente, cualquier usuario podría acceder a una zona de 64Kb de memoria del servidor, cercana a la zona donde se gestionan las operaciones con SSLv3. Esto podría llegar a permitir acceder a información privilegiada, como por ejemplo la clave privada […]

06 de abril de 2014

04 de abril de 2014

01 de abril de 2014

Resize de volúmenes en LVM

Tenemos un sistema de discos LVM con las siguientes “particiones”: [juanan@S000161 ~]$ df -h Filesystem Size Used Avail Use% Mounted on /dev/mapper/vg_s000161-lv_root 50G 39G 8.6G 82% / tmpfs 5.8G 316K 5.8G 1% /dev/shm /dev/mapper/ddf1_4c5349202020202080862925000000004711471100001450p1 485M 58M 402M 13% /boot /dev/mapper/vg_s000161-lv_home 395G 87G 288G 24% /home Si nos fijamos, el volumen lógico (lv) asignado a / […]

30 de marzo de 2014

Primeros días con Ubuntu 14.04: problemas wifi y otros

Ya me pasé a Ubuntu 14.04 LTS (Beta 2). Las mejoras no parecen de momento muy visibles frente a la versión que tenía (y yo trabajo siempre con la LTS, así que para dos años sin cambiar, creo que debería notarlo más). Finalmente deseché cambiar a Ubuntu Gnome (aunque me pareció una muy buena alternativa) y me quedé con lo conocido.

Eso sí, echo en falta el instalar cómodamente el soporte de 32 bits (antes se podía instalando el paquete ia32-libs). Actualmente, aun es posible hacerlo, pero me ha costado un poco averiguar el cómo. Ya sé que vivimos en un mundo de 64 bits, pero, hoy por hoy, muchos todavía tenemos que instalar, por razones de trabajo, pequeñas aplicaciones privativas que no las publican en 64 bits. En mi caso, para añadir el soporte de 32 bits que necesitaba primero añadí el soporte de instalación de paquetes de este tipo:

dpkg --add-architecture i386

y luego instalé lo que necesitaba en ese momento:

apt-get install nspluginwrapper lib32z1 libc6-i386 libxml2:i386 \
  libstdc++6:i386 libxerces-c3.1:i386 libcanberra-gtk-module:i386 \
  libcurl3:i386 libasound2-plugins:i386 libgstreamer-plugins-base0.10-0:i386

Esto me sirve para utilizar sin problemas cosas como Citrix Receiver o el Forticlient VPN SSL. Cosas de mi trabajo…

Trabajando ya con el sistema, lo más molesto que me he encontrado es una inusual inestabilidad de la conexión Wifi. Continuamente se me reconectaba la wifi con mensajes en el sistema como éstos (reconectando a 1 Mbps con cierta frecuencia):

wlan0: Limiting TX power to 20 (20 - 0) dBm as advertised by xx:xx:xx:xx:xx:xx
wlan0: deauthenticated from xx:xx:xx:xx:xx:xx (Reason: 6)
Calling CRDA to update world regulatory domain
cfg80211: World regulatory domain updated:
cfg80211: (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
cfg80211: (2402000 KHz - 2472000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
...

Aunque apenas lo notaba, el verdadero problema es que en algún momento no era capaz de renegociar y me topaba con un:

IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready

y la única solución para seguir conectado era, desconectar y reconectar las funciones de radio (Fn-F2 en mi portátil, un Dell V131). Finalmente, examinando varios bugs de Ubuntu (marcados como inválidos, y pocas veces corregidos, como suele ocurrir: ejemplo 1, ejemplo 2) encontré la recomendación de algún usuario final: desactivar 802.11n. Gracias a esto, ya no se desconecta y siempre tengo 54 Mbps en la tarjeta. Para hacerlo, ver más abajo el fichero personal-opts.conf.

Otro problema que he tenido, esta vez con el lector de tarjetas flash integrado, es que está continuamente enviando estos mensajes, los cuales ralentizan un poco el sistema:

sd 6:0:0:0: [sdb] Test WP failed, assume Write Enabled
sd 6:0:0:0: [sdb] Asking for cache data failed
sd 6:0:0:0: [sdb] Assuming drive cache: write through

Examinando bugs he encontrado que tal vez se podría solucionar cargando el módulo ums_realtek con la opción ss_en=0. Sin embargo, no es suficiente: en este caso lo que sucede es que aparentemente el dispositivo se conecta y desconecta continuamente al bus USB. Finalmente, lo que he tenido que hacer es ponerlo en la lista negra para evitar que cargue el driver. Total, para lo que uso el lector de tarjetas…

Para dejar fijas ambas soluciones (entiendo que temporales, ya veremos) he creado un archivo /etc/modprobe.d/personal-opts.conf con el siguiente contenido:

options iwlwifi 11n_disable=1
blacklist ums-realtek
# options ums-realtek ss_en=0

Después de hacer estos cambios, se puede decir que ya disfruto de mi nuevo Ubuntu 14.04 LTS en 64 bits ;-)

27 de marzo de 2014

Depurar, editar y guardar ficheros JS en Google Chrome

Receta rápida para los desarrolladores JavaScript interesados, y para retomar el blog tras un parón de unos cuantos meses (he estado ocupado :-) La cuestión es: las DevTools de Google Chrome permiten editar y depurar código JavaScript desde el propio navegador. Pero cuando editas un fichero .js y lo intentas guardar, salta el siguiente error: […]

24 de marzo de 2014

WebKitGTK+ 2.4.0: the multiprocess made easy

Yes, we did it again, we have just released WebKitGTK+ 2.4.0, another major stable release with a lot of bug fixes, some new features and more complete API.

Multiple Web Processes

This is the most important new feature included in this release, and the one we have spent most of the release cycle with. All started during the WebKitGTK+ hackfest when a team of around 10 people worked together to implement the base of the multi-process support. And at the very end of the release cycle we have been able to turn it on by default in Epiphany.

DOM touch events support

WebKitWebView now processes the touch events happening in the widget to notify the DOM, making modern websites using DOM touch API properly work. Carlos Garnacho has taken a screencast to show it in action


Plugins cache

When the first page containing plugins was loaded, the UI process got blocked for some time, while the plugins were scanned. This was one of the most annoying bugs of WebKitGTK+ introduced in 2.0. Plugins are synchronously scanned on demand during the page load, and it’s something that can’t be avoided. WebKitGTK+ 2.4 uses a persistent cache to store information about all plugins, so that plugins are only scanned the first time or when they change.

New API

As always a huge thanks to all the contributors that make this possible, and very specially in this release to the sponsors of the WebKitGTK+ hackfest 2013 (Igalia and the GNOME Foundation).

WebKit1 deprecation

There’s one last thing I would like to mention. Even when WebKit1 API has been deprecated since we released WebKitGTK+ 2.0, we have kept shipping both APIs in our tarball releases. A decision hasn’t been made yet, but this is probably the last release including the WebKit1 API, we have plans to remove the WebKit1 code from trunk and move all the build bots to run only WebKit2 tests. We encourage everybody to port their applications to WebKit2, submitting bug reports if there’s anything preventing the switch, and of course we are happy to help on IRC, mailing list, etc.

14 de marzo de 2014

Cargador de signo de exclamación en Atari – Decodificado

El famoso signo de exclamación

Cuando los computadores Atari recién llegaron a Chile, practicamente todos los juegos que se podían encontrar en cassette usaban el famoso cargador del signo de exclamación.  Se iniciaba la carga de cassete encendiendo el computador con las teclas OPTION + START presionadas, sonaba un beep, se presionaba una tecla y después de unos 10 segundos sonaban unos 6 “pitos” y aparecía un signo de exclamación en la parte inferior derecha de la pantalla, luego pasaban unos 10 segundos más y comenzaba a sonar la carga del juego en sí, a veces amenizada por alguna simple pantalla de presentación.

Si algo fallaba durante la carga, se debía comenzar desde cero, por lo que toda la ansiedad acumulada durante los varios minutos de carga se veía absolutamente recompensada cuando finalmente aparecía el juego en pantalla.  Posteriormente aparecieron mejores sistemas de carga aplicando “turbo” (mayor bitrate) y un mecanismo de recuperación de errores que permitía continuar la carga desde el punto de falla y así no comenzar todo desde cero.  Estos sistemas de carga avanzados merecen un artículo propio, lo que vamos a ver acá es el cargador original del signo de exclamación.

Básicamente estos sistemas de carga funcionaban así: Al iniciar el sistema, la tecla OPTION presionada indicaba al sistema operativo del ATARI que desconectara la ROM del lenguaje BASIC (su espacio era ocupado por muchos juegos), y la tecla START indicaba que se quería hacer un boot desde cassette.  Cuando el usuario presionaba una tecla después del beep, el sistema operativo del ATARI cargaba un archivo y lo ejecutaba.  En el caso de practicamente todos los juegos, este archivo era un cargador un poco más inteligente que se encargaba de cargar el juego en un formato más flexible (XEX).  Si vieramos la cinta como un esquema, sería así:

| ------- CARGADOR EN FORMATO BOOT DE ATARI -------|---------- JUEGO EN FORMATO XEX ----------|
| CARRIER - BLK1 - BLK2 - BLK3 - BLK4 - BLK5 - EOF | CARRIER - BLK1 - BLK2 - ... - BLKn - EOF |

Siempre quise saber exactamente qué hacía el código de este cargador tan simple, y por qué era tan grande (unos 640 bytes). Gracias al usuario AsCrNet de AtariWare que me envió un dump del cargador pude finalmente decodificarlo y ver qué hacía.

Formato XEX

Para que sea más fácil entender el cargador conviene entender primero cuál era el formato del archivo que procesaba el cargador, el formato “del juego”.  Este formato es conocido con el nombre XEX y tiene más o menos la siguiente estructura

|---------------- Archivo en formato XEX ------------- ...
|------ ENCABEZADO ------ | DATA |------ ENCABEZADO -- ...
|FF FF INIL INIH ENDL ENDH| DATA |FF FF INIL INIH ENDL ...

Un archivo XEX son varios bloques de datos.  Cada bloque comienza opcionalmente con un marcador con la secuencia FF FF (hexadecimal), luego viene la dirección de inicio expresada como 2 bytes (INIL INIH) y la dirección de término expresada también como 2 bytes (ENDL ENDH).  Estos 6 bytes son la cabecera del bloque, luego vienen los datos propiamente tal.  Por ejemplo si el juego tiene dos bloques, uno desde 32768 hasta 40959 y otro desde 3072 a 4096 veríamos la siguiente secuencia hexadecimal

|---------------------------- Archivo en formato XEX ----------------------------|
|--------------- BLOQUE 1 ----------------|------------- BLOQUE 2 ---------------|
|--- ENCABEZADO ---|-------DATOS----------|--- ENCABEZADO --|-------DATOS--------|
|FF FF 00 80 FF 99 | 16384 bytes de datos |FF FF 00 0C FF 0F| 1024 bytes de datos|

Después de cargar cada bloque, el cargador ejecuta una llamada a la dirección apuntada por el par de direcciones 738 y 739 ($02E2, $02E3).  Si el cargador quisiese ejecutar un código durante la carga, por ejemplo para mostrar una presentación, debía poner un bloque que escribiera en esas direcciones.  Supongamos que el código que muestra la presentación está en la direcció $0A3B, entonces aparecería un bloque así:

FF FF E2 02 E3 02 3B 0A

Cuando se llega al final de la carga, se transfiere el control al código apuntado por las direcciones 736 y 737 ($02E0, $02E1) utilizando el mismo esquema recién explicado.

El cargador

El cargador tiene el formato de BOOT propio de Atari, obviamente ya que de otro modo el sistema no lo podría ejecutar.  El sistema de BOOT de Atari comienza con 6 bytes para definir el número de bloques de datos, la dirección de inicio de carga y la dirección de ejecución.  En este cargador vienen los valores (hex) : 20  05  00 07 20 07 que son interpretados como : 5 bloques cargados a partir de $0700, inicio de ejecución en $0720. Por qué suenan 6 bloques de carga y acá dice que son 5? Porque son 5 de datos y el 6to es el EOF (End of File).

Si bien la dirección de ejecución es $0720, el sistema operativo de Atari primero ejecuta lo que está a continuación de este encabezado, en este caso es lo que está en $0706.  Y ahí comienzan las sorpresas!!!

Lo primero que me llamó la atención es que eset vil cargador está protegido.  Si uno trata de ver el código directamente, no se puede a menos que se vaya revisando la ejecución paso a paso.  Lo primero que hace el cargador es automodificarse para comenzar a ejecutarse en una dirección diferente a la que viene cargada originalmente. De la siguiente forma (ordenado por legibilidad):

BOOT:
706  32 244   8  JSR STOPANDPATCH ; $8F4

[...]

STOPANDPATCH:
8f4  32 207   8 JSR MOTOROFF
8f7  32 213   8 JSR PATCHJSR
8fa  96         RTS

MOTOROFF:
8cf 169  60     LDA #60
8d1 141   2 211 STA 54018
8d4 96          RTS

PATCHJSR:
8d5 169  32     LDA #32   ; JSR
8d7 141   9   7 STA $709
8da 169 157     LDA #157  ; $9D
8dc 141  10   7 STA $70A
8df 169   8     LDA #8    ; $08
8e1 141  11   7 STA #70B
8e4  96         RTS

Cuando se ejecuta PATCHJSR se modifica el código que se ejecutará justo después de volver via RTS en $8D4, para que salte a $089D, y qué encontramos ahí? La rutina que desprotege el resto del código invirtiendo todos los bits mediante XOR #$FF, una ténica que podríamos considerar milenaria.

A partir de ese momento, el código queda legible completamente.

No voy a analizar el detalle del cargador, pero sí me interesa destacar las siguientes curiosidades:

  • No logré identificar la parte en donde se pone el signo de interrogación en la pantalla.  Sólo veo la impresión de un caracter que limpia la pantalla.  Será el signo de exclamación un bug del sistema operativo del Atari?
  • El código de carga XEX en este cargador es HO-RRI-BLE.  Esto se debe principalmene a que está mezclada la llamada a las rutinas del sistema operativo para cargar datos desde cassette, con la interpretación de los encabezados XEX. En comparación, cargadores más modernos como CAIN (ahem!) usan una abstracción tipo stream, en donde los bytes se procesan uno a uno y la carga física de los bloques se procesa en forma independiente, como si se tratara de un sistema opaco subyacente (le puse color ah).  En todo caso, se entiende que sea así, hay que pensar que ese código debe ser de principios de los ’80, cuando muchos de nosotros no sabíamos ni ir a comprar el pan.
  • Si la carga falla en algún momento, se invoca a la rutina del sistema operativo que imprime BOOT ERROR.  Por algún motivo, en los computadores que conocí esto nunca fue así, y el sistema simplemente se colgaba.  Es probable que la dirección de rutina haya sido válida sólo para equipos antiguos (400/800) y no para sistemas operativos más modernos (XL/XE).
  • Se nota que el código fue parchado a nivel binario, ya que usaron NOP en varias partes, desactivando código.
  • Derivado de lo anterior, hay muchos accesos de 16 bit a direcciones que están en la página cero, en donde se pueden usar instrucciones especiales que direccionan con sólo 8 bits (ej, 133, 2 en vez de 141, 2, 0).
  • Si hay un cartridge insertado, aparece un mensaje en pantalla que lo advierte.  Este mensaje nunca lo había visto, y es muy probable de que hasta el momento nadie lo haya visto tampoco!  Les adjunto una captura al final de este artículo foryourpleasure.

Para quién quiera ver el detalle de cargador, les dejo los siguientes archivos en una carpeta de DropBox:

  • casboot.asm : Archivo de texto con el código del cargador. Lo decodifiqué a mano, por lo que el código no es compatible con ningún assembler.
  • dump.c : Programa en C para hacer un dump del código que me envió AsCrNet.  Al cambiar UNPROTECT a 1, se aplica el XOR #$255 para desproteger el código
  • casboot.atr : Imagen de disco que contiene un pequeño programa en BASIC que hice para saber cómo se vería el mensaje del cartridge insertado (cartmsg.bas)

PD1 : La imagen del cargador que encabeza este artículo es un fake.  Fue lo más rápido que pude hacer.

PD2 : Por algún motivo se borró la mitad de este artículo mientras lo estaba creando. Lo tuve que hacer de nuevo. NOT FUN.

PD3 : Ningún juego fue dañado durante la creación de este artículo.


ACTUALIZACIÓN: Gracias a los aportes de Guillermo Fuenzalida y ArCrNet finalmente fue resuelto el enigma del signo de exclamación.  Cuando el cargador imprime el caracter de limpiar pantalla, lo hace con el siguiente código:

765 169 125     LDA #125   ; CLEAR SCREEN
767 32  164 246 JSR PRINT  ; $F6A4

Sin embargo la rutina del SO para imprimir en $F6A4 sólo es válida para la ROM de la generación Atari 400/800, porque en la ROM de los Atari XL/XE se encuentra en otro lugar.  Según Mapping the XL/XE:

Many 400/800 programs made direct jumps to keyboard ‘get’ and ‘put’ routines rather than through the proper vectors, which makes them incompatible with XL/XE machines. The get routines in the XL/XE begin at 62026 ($F24A). This was 63038 ($F63E) in the 800. The put routines begin at 62128 ($F2B0). or 63140 ($F6A4) in the 800. If you have a program which won’t work on your XL/XE, try finding if it uses these locations and change them.

Por lo tanto, el famoso caracter “!” de este cargador aparece debido a un bug sin mayores consecuencias.  Para comprobarlo, modifiqué la llamada a $F6A4 y la cambié por $F2B0 y efectivamente, se limpia la pantalla y no aparece el caracter “!”.  Lo mismo demostró ArCrNet usando el cargador en un emulador con la ROM del 400/800, nada de signo de exclamación.

Cartridge insertado

Mensaje que aparece si hay un cartridge insertado

 

27 de febrero de 2014

New media controls in WebKitGtk+ (reloaded)

In December we organized in A Coruña the WebKitGTK+ hackfest at the Igalia premises as usual and also as usual it was an awesome oportunity to meet the rest of the team. For more information about the progress done in the hackfest, you can have a look at KaL’s post.

As part of the hackfest I decided to take a task that it would take some time so that I could focus and I decided to go for rewriting once again the WebKitGTK+ multimedia controls. People who just read this post will wonder why I say again and the reason is that last year we completely redesigned the multimedia controls. This time I have not redesigned them (well, a bit) but rewritten them in JavaScript as the Apple guys had done before.

To get the job done, the first step was bundling the JavaScript code and activating the codepath to use those controls. I used the Apple controls as template so you can imagine that the first result was a non-working monster that at some point reminded to Safari multimedia controls. At that point I could do two things, forking or inheriting. I decided to go with inheritance because it keeps the spirit of WebKit (and almost all Free Software projects) of sharing as much code as possible and because forking later is easier than merging. Then step by step I kept redefining JavaScript methods and tweaking some stuff in the C++ and CSS code to create the current user experience that we had so far.

Some of the non-aesthetic changes are the following:

  • Focus rings are now managed from CSS instead of C++.
  • Tests got new fixes, rebaselines and more love.
  • CMake support for the new controls.
  • Load captions icon from theme.
  • Load and hide elements handled now with CSS (and JavaScript).

The captions icon problem was interesting because I found out that the one we were using was “user-invisible-symbolic” and it was hardcoded directly in the CSS code. I changed it to be loaded from the theme but it raised the issue of using the incorrect metaphor though the current icon looks nice for captions. I filed a GNOME bug (and another WebKit bug to follow this up) so that a new icon can be created for captions/subtitles with the correct metaphor.

And which are the controls aesthetic changes?

  • Show a very subtle gradient when the elements are focused or active to improve the accessibility support (which won’t be complete until bug 117857 is fixed).
  • Volume slider rolls up and down with a nice animation.
  • Some other elements are not shown when they are not needed.
  • Captions menu shows up with both click and mouse hover for coherence with the volume slider.
  • Captions menu is also animated the same way as the volume slider.
  • Captions menu was propertly centered.
  • Captions menu style was changed to make it more similar to the rest of the controls (fonts, margings…)
  • Volume slider shows below the media element when it is too close to the page top and it cannot be shown on it. This was a regression that I introduced with the first rewrite, happy to have it fixed now.

As I already said the aesthetic differences with the former C++ are not a big deal unless you compare them with the original controls:

Starting point

To appreciate the new controls I cannot just show a screenshot, because the nicest thing are the animations. Therefore a video is needed (and if you have WebKit compiled you can experience them yourself)):

Of course, I thank our hackfest sponsors as the it was possible because of them:

Igalia GNOME Foundation

23 de febrero de 2014

La caída de whatsapp… y los fallos de Telegram

Ayer fue un día curioso: seguramente muchos usuarios de smartphones descubrieron que había una aplicación llamada “LINE“; incluso que existía una función de fábrica llamada “SMS” y que hasta podían llamar por el teléfono. Pero a fin de mes podrían llegar a ver algunos experimentos reflejados en su factura…

Lo que realmente pasó ya lo sabemos: Whatsapp, el producto sobrevalorado por Facebook, sufrió un colapso durante más de tres horas. Y mira por donde su mejor rival, Telegram, sufrió la mayor demanda que se conoce, que ha tenido que poner las pilas a sus dueños. Porque se vino abajo: sencillamente no pudo soportar algo que, probablemente, Whatsapp sí que soporta: 100 usuarios nuevos por segundo. Millón y pico de usuarios nuevos en un día.

telegram_vs_whatsapp

Lo que ha pasado es clara señal de que Telegram es el rival con más peligro: es el rival que además de más seguro, fiable, barato y bla bla que Whatsapp, es, sobre todo, el más parecido. Y probablemente esta sea la causa de su próximo éxito y no otra cosa.

Ahora, un aviso para navegantes (o mejor, para los creadores de Telegram): tiene un muy buen punto de partida, pero aun tiene importantes fallos y su proyecto de desarrollo debe tener cariño/financiación suficientes para corregirlos. Sin ir más lejos, el otro día notifiqué un fallo que me descubrió un compañero de trabajo, que hace que el cliente descarte los mensajes cuando la conexión no es posible en un plazo de tiempo. Esto en Whatsapp no pasa, pero con Telegram sí; y esto es fácil que nos afecte si escribimos un mensaje a un contacto cuando estamos, por ejemplo, atravesando un túnel sin cobertura. La respuesta de los desarrolladores a mi correo fue, inicialmente, casi decirme que más que fallo era una característica; tras mi insistencia reconocieron que lo arreglarían cuando pudiesen.

Por cierto, la crisis del Whatsapp me trajo ayer una pequeña avalancha de contactos nuevos desde mi agenda telefónica. Felicidades a los desarrolladores, pero también a los usuarios: por elegir una alternativa mucho mejor, aunque no sepan muy bien por qué.

Nota: Este artículo no contiene enlaces a medios de «AEDE» y, en todo caso, se acoge al derecho de cita de la vigente LPI para la publicación de los mismos.

09 de febrero de 2014

Adición de un controlador de dominio (DC) con Samba 4

Continuando con el artículo anterior, vamos a ver a continuación como añadir controladores de dominio adicionales a nuestra red con Samba 4. Partiremos de la existencia de al menos un controlador de dominio implementado preferiblemente con Samba 4, o con Windows Server en su defecto. Nuevamente, nuestro servidor contará con CentOS 6.x como sistema operativo y los paquetes de Enterprise Samba.

Requisitos

Debemos contar con un servidor con CentOS 6.x o Red Hat Enterprise Linux 6.x, y los paquetes de Enterprise Samba ya instalados; así como los paquetes de Bind modificados, de acuerdo a como indicamos en el artículo anterior.

Disponibilidad del directorio activo

Para comprobar su disponibilidad, probaremos un login con Kerberos. Creamos un fichero /etc/krb5.conf como el siguiente:

[libdefaults]
 default_realm = DRAMOR.INT
 dns_lookup_realm = false
 dns_lookup_kdc = true

También, verificaremos que el sistema tiene puesto como servidor DNS, el del otro controlador de dominio:

# cat /etc/resolv.conf
search dramor.int
nameserver 192.168.56.10

Y trataremos de obtener un ticket:

# kinit Administrador@DRAMOR.INT
Password: xxxx
Warning: Your password will expire in 41 days on Sun Mar 23 13:19:48 2014

Si todo ha ido correcto podremos conectarnos a algún recurso con ese usuario:

# smbclient -k //centos6ad/netlogon
Domain=[DRAMOR] OS=[Unix] Server=[Samba 4.1.4-SerNet-RedHat-7.el6]
smb: \> quit
# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: Administrador@DRAMOR.INT
Valid starting Expires Service principal
02/08/14 23:43:38 02/09/14 09:43:41 krbtgt/DRAMOR.INT@DRAMOR.INT
 renew until 02/09/14 23:43:38
02/08/14 23:43:54 02/09/14 09:43:41 cifs/centos6ad@DRAMOR.INT

Unión como controlador de dominio (DC)

Nos uniremos con la orden samba-tool. Nos pedirá la contraseña del administrador y a continuación se unirá mostrándonos información abundante sobre el proceso de replicación de datos:

# samba-tool domain join dramor.int DC -UAdministrator --dns-backend=BIND9_DLZ
Finding a writeable DC for domain 'dramor.int'
Found DC centos6ad.dramor.int
Password for [DRAMOR\Administrator]:
workgroup is DRAMOR
realm is dramor.int
checking sAMAccountName
Adding CN=CENTOS6AD2,OU=Domain Controllers,DC=dramor,DC=int
Adding CN=CENTOS6AD2,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=dramor,DC=int
Adding CN=NTDS Settings,CN=CENTOS6AD2,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=dramor,DC=int
Adding SPNs to CN=CENTOS6AD2,OU=Domain Controllers,DC=dramor,DC=int
Setting account password for CENTOS6AD2$
Enabling account
Adding DNS account CN=dns-CENTOS6AD2,CN=Users,DC=dramor,DC=int with dns/ SPN
Setting account password for dns-CENTOS6AD2
Calling bare provision
No IPv6 address will be assigned
Provision OK for domain DN DC=dramor,DC=int
Starting replication
Schema-DN[CN=Schema,CN=Configuration,DC=dramor,DC=int] objects[402/1550] linked_values[0/0]
Schema-DN[CN=Schema,CN=Configuration,DC=dramor,DC=int] objects[804/1550] linked_values[0/0]
Schema-DN[CN=Schema,CN=Configuration,DC=dramor,DC=int] objects[1206/1550] linked_values[0/0]
Schema-DN[CN=Schema,CN=Configuration,DC=dramor,DC=int] objects[1550/1550] linked_values[0/0]
Analyze and apply schema objects
Partition[CN=Configuration,DC=dramor,DC=int] objects[402/1620] linked_values[0/0]
Partition[CN=Configuration,DC=dramor,DC=int] objects[804/1620] linked_values[0/0]
Partition[CN=Configuration,DC=dramor,DC=int] objects[1206/1620] linked_values[0/0]
Partition[CN=Configuration,DC=dramor,DC=int] objects[1608/1620] linked_values[0/0]
Partition[CN=Configuration,DC=dramor,DC=int] objects[1620/1620] linked_values[28/0]
Replicating critical objects from the base DN of the domain
Partition[DC=dramor,DC=int] objects[98/98] linked_values[23/0]
Partition[DC=dramor,DC=int] objects[313/215] linked_values[23/0]
Done with always replicated NC (base, config, schema)
Replicating DC=DomainDnsZones,DC=dramor,DC=int
Partition[DC=DomainDnsZones,DC=dramor,DC=int] objects[41/41] linked_values[0/0]
Replicating DC=ForestDnsZones,DC=dramor,DC=int
Partition[DC=ForestDnsZones,DC=dramor,DC=int] objects[19/19] linked_values[0/0]
Partition[DC=ForestDnsZones,DC=dramor,DC=int] objects[38/19] linked_values[0/0]
Committing SAM database
Sending DsReplicateUpdateRefs for all the replicated partitions
Setting isSynchronized and dsServiceName
Setting up secrets database
Joined domain DRAMOR (SID S-1-5-21-2470081830-1300756272-1234487377) as a DC

 

Ajuste de entradas DNS

Comprobaremos si se creó una entrada DNS para el nuevo servidor en el servidor al que nos hemos unido. Para ello intentamos resolver:

# host -t A centos6ad2.dramor.int.
Host centos6ad2.dramor.int. not found: 3(NXDOMAIN)

Si nos da error, debemos dar de alta el registro DNS. Podemos hacerlo con samba-tool. Si la IP del servidor DNS es 192.168.56.20 y la del servidor que acabamos de unir (centos6ad) es 192.168.56.10 introduciríamos una orden como:

# samba-tool dns add 192.168.56.30 dramor.int centos6ad2 a 192.168.56.10 -Uadministrador
Password for [DRAMOR\administrador]:
Record added successfully

Probamos de nuevo:

# host -t A centos6ad2.dramor.int.
centos6ad2.dramor.int has address 192.168.56.30

Tanto si hemos tenido que añadir este registro como si no, seguramente tendremos que añadir el GUID del servidor como registro CNAME del DNS. Comprobaremos si existe, en primer lugar obteniendo el GUID:

# ldbsearch -H /var/lib/samba/private/sam.ldb '(invocationid=*)' --cross-ncs objectguid
# record 1
dn: CN=NTDS Settings,CN=CENTOS6AD2,CN=Servers,CN=Nombre-predeterminado-primer-sitio,CN=Sites,CN=Configuration,DC=dramor,DC=int
objectGUID: 99889a59-e3b6-4c9d-a005-dc61fa238cad
...

Buscamos el registro:

# host -t CNAME 99889a59-e3b6-4c9d-a005-dc61fa238cad._msdcs.dramor.int.
Host 99889a59-e3b6-4c9d-a005-dc61fa238cad._msdcs.dramor.int. not found: 3(NXDOMAIN)

Si nos da este error, lo creamos:

# samba-tool dns add 192.168.56.20 _msdcs.dramor.int 99889a59-e3b6-4c9d-a005-dc61fa238cad CNAME centos6ad2.dramor.int -Uadministrador
Password for [DRAMOR\administrador]:
Record added successfully

Y probamos de nuevo:

# host -t CNAME 99889a59-e3b6-4c9d-a005-dc61fa238cad._msdcs.dramor.int.
99889a59-e3b6-4c9d-a005-dc61fa238cad._msdcs.dramor.int is an alias for centos6ad2.dramor.int.

Configuración de BIND

Para configurar y arrancar el servicio DNS tenemos que realizar las mismas configuraciones y posteriores revisiones de permisos de ficheros que hicimos con el primer controlador de dominio (ver artículo anterior).

Una vez arrancado podemos probar con dig que es capaz de resolver cualesquiera de los equipos de la red, por ejemplo, los dos servidores DC configurados hasta ahora (centos6ad y centos6ad2):

# host -t A centos6ad.dramor.int 127.0.0.1
Using domain server:
Name: 127.0.0.1
Address: 127.0.0.1#53
Aliases:
centos6ad.dramor.int has address 192.168.56.10
# host -t A centos6ad2.dramor.int 127.0.0.1
Using domain server:
Name: 127.0.0.1
Address: 127.0.0.1#53
Aliases:
centos6ad2.dramor.int has address 192.168.56.30

 

Arranque de Samba

Para arrancar Samba4 en modo directorio activo, editamos el fichero /etc/default/sernet-samba cambiando la variable SAMBA_START_MODE al valor “ad” en lugar de “none”. Finalmente, arrancamos con “service sernet-samba-ad start”.

Si vemos en los logs ( /var/log/samba/log.samba ) un error similar a este:

 

Failed to bind to uuid e3514235-4b06-11d1-ab04-00c04fc2dcd2 for e3514235-4b06-
11d1-ab04-00c04fc2dcd2@ncacn_ip_tcp:b78fee18-83b9-4478-9239-0d9a13b654c2._msdcs.
dramor.int[1024,seal,krb5] NT_STATUS_UNSUCCESSFUL

normalmente reiniciando el samba de esa máquina se soluciona.

Una vez dejemos de ver los errores, podemos comprobar que los objetos del directorio activo se replican, para ello desde uno de los servidores creamos un usuario:

# samba-tool user add usuario1
Password: XXXX
# samba-tool user list
dns-CENTOS6AD2
Administrator
dns-CENTOS6AD
usuario1
krbtgt
Guest

Tras unos segundos, ejecutando la misma orden (samba-tool user list) en el otro servidor DC debemos ver que también aparece el usuario1 recién creado.

Interacción con DC Windows Server

Si el servidor DC es Windows Server y no Samba 4, debemos tener en cuenta que tras añadir el servidor Samba 4 y arrancar Samba, no funcionará la replicación. Esto se verá con un error en los logs de Samba, similares a:

UpdateRefs failed with WERR_DS_DRA_BAD_NC/NT

Para solucionarlo, debemos ejecutar “repadmin /kcc” en el servidor Windows, o bien el siguiente comando en el Samba 4:

# samba-tool drs kcc -Uadministrator w2003srv.dramor.int
 Consistency check on centos6ad.dramor.int successful.

Tras esto podemos verificar la replicación con:

# samba-tool drs showrepl
 Default-First-Site-Name\CENTOS6AD2
 DSA Options: 0x00000001
 DSA object GUID: b78fee18-83b9-4478-9239-0d9a13b654c2
 DSA invocationId: 45869512-53e2-4e3e-9478-3c874e4352d7
==== INBOUND NEIGHBORS ====
DC=ForestDnsZones,DC=dramor,DC=int
 Default-First-Site-Name\W2003SRV via RPC
 DSA object GUID: ff97c348-e990-4a6a-a9c5-879c9b1e2dea
 Last attempt @ Sun Feb 9 14:04:42 2014 CET was successful
 0 consecutive failure(s).
 Last success @ Sun Feb 9 14:04:42 2014 CET
DC=dramor,DC=int
 Default-First-Site-Name\W2003SRV via RPC
 DSA object GUID: ff97c348-e990-4a6a-a9c5-879c9b1e2dea
 Last attempt @ Sun Feb 9 14:04:43 2014 CET was successful
 0 consecutive failure(s).
 Last success @ Sun Feb 9 14:04:43 2014 CET
...

 

 

También nos fallará el backend DNS BIND_DLZ, si el servidor es Windows 2003. Esto es en este momento, un error conocido sin resolver en Samba4, Se puede evitar utilizando el backend DNS interno de Samba 4, aunque habrá que tener en cuenta sus limitaciones.

 

05 de febrero de 2014

#AllTrials: campaña de cabildeo a los eurodiputados

Desde AllTrials.net informan de los avances en la campaña para que la Unión Europea regule la transparencia de los resultados de todos los ensayos clínicos que se realicen a la hora de estudiar posibles nuevas medicinas.

Para el siguiente paso nos solicitan dirigirnos a nuestros eurodiputados para hacerles llegar una carta pidiéndoles el voto a favor del llamado informe Willmott en una votación que tendrá lugar el próximo 3 de abril. Me he tomado la libertad de traducirla a español y ponerla a disposición de todos los interesados:

Estimado parlamentario:

Me dirijo a usted para rogarle que apoye al Informe Willmot acerca de la Regulación de Ensayos Clínicos.

El próximo 3 de abril de 2014 suya será la oportunidad de votar a favor de aumentar significativamente la transparencia de los datos obtenidos en las pruebas clínicas. Una vez que la regulación esté en marcha todas las compañías farmacéuticas y los patrocinadores no comerciales de ensayos clínicos tendrán la obligación de:

  • enviar un resumen de los resultados a una base de datos accesible públicamente en el plazo de un año tras concluir la investigación;
  • enviar un resumen comprensible para un observador neutral;
  • enviar los informes completos de estudios clínicos de los ensayos cuando se solicite la puesta en el mercado de una medicina;
  • registrar o publicar ensayos anteriores si con ellos se pretende respaldar solicitudes para nuevos ensayos;
  • someterse a penalizaciones económicas si no se cumplen los requisitos de transparencia.

Es de enfatizar que estas reglas aplicarán en cualquier caso, no importa si el resultado del ensayo ha sido exitoso, un fracaso o inconcluyente.

Aproximadamente la mitad de todos los ensayos clínicos no han sido publicados. Algunos siquiera han sido registrados. Si no se toman medidas urgentes, el detalle de qué es lo que se ha hecho y qué se descubrió durante los ensayos podría perderse para siempre, en perjuicio de elecciones de tratamientos, oportunidades perdidas para hacer buena medicina y ensayos que habrían de ser repetidos innecesariamente.

¿Va a ayudar a mejorar la seguridad de los pacientes, a la ciencia más sólida y al avance de la medicina votando a favor del informe el 3 de abril?


Atentamente (el signatario)



La idea es enviar una copia de esta carta a nuestros europarlamentarios. También tenéis disponible el enlace a las páginas de su perfiles en la web del Parlamento Europeo, que a su vez contienen al menos el correo electrónico, en un único fichero pdf.

Desde aquí sólo puedo animaros a apoyar este extraordinario ejercicio de transparencia dirigiéndoos a vuestros parlamentarios.

02 de febrero de 2014

Creación de Directorio Activo con Samba 4 en CentOS 6

A finales de 2012 se publicó la versión 4 de Samba. La gran novedad fue la capacidad para implementar controladores de dominio de directorio activo. Durante el pasado año se ha mejorado bastante esta versión de Samba, ampliando las funcionalidades soportadas, aunque aun tiene algunas limitaciones. Por el momento no repararemos en ellas, y baste decir que en muchos entornos facilitará la implementación del directorio sin necesidad de invertir en licencias de Windows Server.

El presente procedimiento permite construir rápidamente un Directorio Activo con paquetes compilados de Samba4 en CentOS 6.x o Red Hat 6.x, ya que la mayoría de procedimientos existentes no se encuentran preparados para CentOS o requieren la compilación del código fuente. Los paquetes elegidos han sido los de Enterprise Samba, debido a la calidad de los mismos.

Requisitos

Partiremos de una máquina con CentOS 6 o Red Hat Enterprise Linux 6, recién instalada en la que desactivaremos SELINUX e IPTABLES para mayor comodidad. Posteriormente, se puede reactivar IPTABLES aunque habrá que abrir algunos puertos relacionados con la conexión de clientes al directorio activo.

Para acceder a los paquetes de Enterprise Samba 4, es necesario registrarse. Para ello iremos a https://portal.enterprisesamba.org/ y nos registraremos (Sign Up). Una vez dentro, debemos descargarnos el fichero sernet-samba-4.1.repo, en el que debemos modificar los valores USERNAME y ACCESSKEY con los que nos aparecerán en la página web anterior. Este archivo lo llevaremos a /etc/yum.repos.d/. Por ejemplo, podría quedar así:

 

[sernet-samba-4.1]
name=SerNet Samba 4.1 Packages (centos-6)
type=rpm-md
baseurl=https://tuusuario:TUCLAVEPROPORCIONADAENPORTALENTERPRISESAMBA@download.sernet.de/packages/samba/4.1/centos/6/
gpgcheck=1
gpgkey=https://tuusuario:TUCLAVEPROPORCIONADAENPORTALENTERPRISESAMBA@download.sernet.de/packages/samba/4.1/centos/6/repodata/repomd.xml.key
enabled=1

Instalación de paquetes

Instalaremos entonces algunos paquetes:

yum -y install wget gcc make wget postfix bind bind-libs bind-utils ntp krb5-workstation

Los paquetes relacionados con bind (bind, bind-libs, bind-utils) deben instalarse desde fuentes, recompilando sin la opción –disable-isc-spnego si queremos que el servidor DNS soporte actualizaciones dinámicas desde los clientes. Para ello, se recomienda instalar el grupo de paquetes “Development Tools” y buscar el paquete fuente de CentOS para reconstruir los binarios eliminando la opción anterior en el bind.spec.

También es necesario configurar NTP. Basta una configuración sencilla que haga que nuestra máquina sea servidora de hora, para que los clientes puedan sincronizar sus relojes con el servidor y así no tener problemas con Kerberos.

A continuación, instalamos desde Enterprise Samba los paquetes para crear el directorio activo:

yum install sernet-samba-ad

Provisión del directorio activo

Procedemos a provisionar el directorio con el comando samba-tool. La mayoría de los valores se pueden dejar como vienen por defecto, en particular el nombre del dominio se tomará con el dominio DNS en el que se encuentre el servidor, lo cual será suficiente en la mayoría de los casos. Por ejemplo, en mi caso puse lo siguiente:

[root@CENTOS6AD ~]# samba-tool domain provision
Realm [DRAMOR.NET]: 
 Domain [DRAMOR]: 
 Server Role (dc, member, standalone) [dc]: 
 DNS backend (SAMBA_INTERNAL, BIND9_FLATFILE, BIND9_DLZ, NONE) [SAMBA_INTERNAL]: BIND9_DLZ
Administrator password: 
Retype password:

La contraseña deberá ser compleja, es decir, incluir mayúsculas, minúsculas, números y algún signo de puntuación. Si no lo hacemos así, el proceso de creación fallará.

Si todo va bien, veremos el proceso automático de creación del directorio:

Looking up IPv4 addresses
Looking up IPv6 addresses
No IPv6 address will be assigned
Setting up share.ldb
Setting up secrets.ldb
Setting up the registry
Setting up the privileges database
Setting up idmap db
Setting up SAM db
Setting up sam.ldb partitions and settings
Setting up sam.ldb rootDSE
Pre-loading the Samba 4 and AD schema
Adding DomainDN: DC=dramor,DC=net
Adding configuration container
Setting up sam.ldb schema
Setting up sam.ldb configuration data
Setting up display specifiers
Modifying display specifiers
Adding users container
Modifying users container
Adding computers container
Modifying computers container
Setting up sam.ldb data
Setting up well known security principals
Setting up sam.ldb users and groups
Setting up self join
Adding DNS accounts
Creating CN=MicrosoftDNS,CN=System,DC=dramor,DC=net
Creating DomainDnsZones and ForestDnsZones partitions
Populating DomainDnsZones and ForestDnsZones partitions
See /var/lib/samba/private/named.conf for an example configuration include file for BIND
and /var/lib/samba/private/named.txt for further documentation required for secure DNS updates
Setting up sam.ldb rootDSE marking as synchronized
Fixing provision GUIDs
A Kerberos configuration suitable for Samba 4 has been generated at /var/lib/samba/private/krb5.conf
Once the above files are installed, your Samba4 server will be ready to use
Server Role: active directory domain controller
Hostname: CENTOS6AD
NetBIOS Domain: DRAMOR
DNS Domain: dramor.net
DOMAIN SID: S-1-5-21-2963293665-1815356632-74099400

Hemos marcado en negrita las advertencias sobre ficheros creados que nos harán falta en los siguientes pasos (BIND y Kerberos).

Configuración de BIND

Pasamos a configurar BIND. El fichero de configuración debe tener en cuenta las indicaciones recibidas durante la creación del directorio activo y algunas más. El siguiente diff contiene los cambios realizados sobre el named.conf que viene con el paquete Bind original de CentOS 6.5:

--- named.conf.orig 2010-07-19 15:34:15.000000000 +0200
+++ named.conf 2014-02-01 20:51:30.490129384 +0100
@@ -8,13 +8,13 @@
 //

 options {
- listen-on port 53 { 127.0.0.1; };
- listen-on-v6 port 53 { ::1; };
+ listen-on port 53 { any; };
+ listen-on-v6 port 53 { any; };
 directory "/var/named";
 dump-file "/var/named/data/cache_dump.db";
 statistics-file "/var/named/data/named_stats.txt";
 memstatistics-file "/var/named/data/named_mem_stats.txt";
- allow-query { localhost; };
+ allow-query { any; };
 recursion yes;

 dnssec-enable yes;
@@ -25,6 +25,8 @@
 bindkeys-file "/etc/named.iscdlv.key";

 managed-keys-directory "/var/named/dynamic";
+
+ tkey-gssapi-keytab "/var/lib/samba/private/dns.keytab";
 };

 logging {
@@ -41,4 +43,5 @@

 include "/etc/named.rfc1912.zones";
 include "/etc/named.root.key";
-
+include "/var/lib/samba/private/named.conf";
+include "/etc/rndc.key";

El fichero /etc/rndc.key lo generamos con:

rndc-confgen -a -r /dev/urandom

Antes de arrancar el Bind tendremos que ajustar algunos permisos en para permitir que el usuario named alcance los ficheros indicados ( /var/lib/samba/private/named.conf, /var/lib/samba/private/dns.keytab). En general, se trata de hacer que el grupo de los archivos de /var/lib/samba/private sea named en lugar de root.

Si al arrancar el Bind (service named start) vemos que da un error, podemos examinar /var/log/messages para averiguar qué sucedió. Casi siempre se detectarán problemas de permisos.

Una vez arrancado, comprobamos que funciona con el comando dig, buscando resolver el dominio que ha creado Samba4:

# dig @127.0.0.1 dramor.net
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.23.rc1.el6_5.1 <<>> @127.0.0.1 dramor.net
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55516
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
;; QUESTION SECTION:
;dramor.net. IN A
;; ANSWER SECTION:
dramor.net. 900 IN A 172.16.34.70
;; AUTHORITY SECTION:
dramor.net. 900 IN NS centos6ad.dramor.net.
;; ADDITIONAL SECTION:
centos6ad.dramor.net. 900 IN A 172.16.34.70
;; Query time: 4 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sat Feb 1 21:00:11 2014
;; MSG SIZE rcvd: 84

Si todo ha ido correctamente, activaremos el arranque de named con el equipo (chkconfig named on) y cambiaremos el fichero /etc/resolv.conf para que utilice este servidor:

domain dramor.net
nameserver 172.16.34.70
 

Arranque y prueba de Samba 4

Para arrancar Samba4 en modo directorio activo, editamos el fichero /etc/default/sernet-samba cambiando la variable SAMBA_START_MODE al valor “ad” en lugar de “none”. Finalmente, arrancamos con “service sernet-samba-ad start”.

El siguiente paso es probar a autenticarnos en el reino Kerberos creado por Samba4. Para ello copiamos a /etc/krb5.conf:

cp /var/lib/samba/private/krb5.conf /etc/krb5.conf

El fichero tendrá este contenido:

[libdefaults]
 default_realm = DRAMOR.NET
 dns_lookup_realm = false
 dns_lookup_kdc = true

Y comprobamos que podemos entrar y examinar el servidor, ya que durante la provisión del directorio se generó un fichero smb.conf que implementa las funciones de servidor necesarias:

# kinit Administrator@DRAMOR.NET
Password for Administrator@DRAMOR.NET:
Warning: Your password will expire in 41 days on Sat Mar 15 20:35:20 2014
# smbclient -k -L  CENTOS6AD
Domain=[DRAMOR] OS=[Unix] Server=[Samba 4.1.4-SerNet-RedHat-7.el6]
Sharename Type Comment
 --------- ---- -------
 netlogon Disk 
 sysvol Disk 
 IPC$ IPC IPC Service (Samba 4.1.4-SerNet-RedHat-7.el6)
...

A continuación ya podemos tomar un cliente Windows XP Profesional, por ejemplo, y unirlo al dominio normalmente.

Dado que Samba4 no incluye herramientas de gestión cómodas, podemos instalar en un cliente Windows las herramientas de Microsoft (herramientas RSAT en Windows 7, Administration Tools en Windows XP, etc). Samba 4 implementa la mayoría de las características del directorio activo y de las políticas GPO, si bien las políticas de contraseñas se gestionan exclusivamente con el comando samba-tool. Por ejemplo, con el comando “samba-tool domain passwordsettings set –complexity=off” podemos quitar la exigencia de complejidad en las contraseñas.

 

 

 

31 de enero de 2014

Telegram

Se está escribiendo bastante sobre Telegram un nuevo candidato para destronar a Whatsapp. La verdad, lo tiene muy difícil, pero creo que un poco menos que LINE. Algunas características que lo hacen interesante:

Telegram_Logo

  • Las más importantes, para mí, son la privacidad y la seguridad (al menos las que prometen): los mensajes viajan cifrados, con un protocolo expuesto públicamente, y las implementaciones de los clientes actuales son todas software libre, lo que facilita que las auditemos para comprobar si son tan seguras como prometen.
  • La más importante para el público en general, creo que es su parecido (digamos que calcado) con Whatsapp, en su manejo y hasta en los emoticonos.
  • No menos importante, la prometida gratuidad. La aplicación “es y será siempre gratuita”. Esto es un ataque frontal a Whatsapp, que desde hace al menos dos años propone a sus usuarios una suerte de micropago anual. Otra cosa es que lo cobren realmente: no conozco nadie de mi entorno que haya pagado hasta la fecha un céntimo a Whatsapp. Y es que, una y otra vez, cuando caduca la cuenta nos invitan a pagar durante unas horas o días y luego, por arte de magia, todo vuelve a funcionar.
  • Además, la aplicación es rápida y más ligera (ocupa menos memoria RAM y almacenamiento en los dispositivos) que cualquier competidor. Eso dicen, pero yo he verificado con algún móvil gama media, que whatsapp pese a ocupar algo más, también se abre más rápido.
  • Y encima hoy mismo ha sido publicada en español, al menos para quien use un dispositivo Android.

Pero no todo son ventajas. Telegram ya tiene algunas críticas importantes. Y no me refiero a cosas como la masa crítica de usuarios o a que no tenga videollamadas. Para el personal preocupado por la seguridad, la oferta de 200.000 dólares por romper el protocolo no convence. Además, es cierto que el protocolo es abierto y han publicado software libre suficiente para implementar clientes Telegram de todo tipo (Android, iOS, Windows…) pero del software del servidor no dicen nada. Ojalá me equivoque, pero la red Telegram ahora mismo es un servicio coleccionista de datos personales, igualito que el de Whatsapp (y LINE). Respecto al protocolo, ¿por qué reinventarlo del todo? ¿Acaso no tenemos XMPP?

El fin de semana pasado fue la explosión de Telegram. Muchos contactos míos (sobre todo, relacionados con el software libre) se lanzaron a instalarlo. El aviso de unión a Telegram de mis contactos (que en la aplicación oficial no se puede, a día de hoy, omitir) empezó a ser realmente pesado. Sin embargo, tras la tormenta llegó la calma, y casi nadie se ha vuelto a dar de alta. Al final, alrededor del 5% de mis contactos tienen Telegram, y para el resto sigue estando Whatsapp y en menor medida LINE.

Personalmente estoy convencido que el resto de mis contactos tecnófilos se unirán a Telegram cuando crean definitivamente en lo que promete. Quizás haciendo software libre el software de servidor y por tanto permitiendo que cualquiera pueda montarse uno que compita con el principal. Además de poder auditar su código. Yo le estoy dando una oportunidad, especialmente para dentro de unos días, cuando mi cuenta en Whatsapp caduque por n-sima vez. Pero bueno, tampoco estoy muy convencido ya que con mucha probabilidad, Whatsapp, también por n-sima vez, me regalará otro año.

29 de enero de 2014

Work madness: dehumanization

Work, work, work... and more work.

We can (and we usually do) lose some time checking Facebook, reading online newspapers, magazines, blogs and other stuff, but if someone calls you at work you freak out and do not pick up, unless the caller insists a lot. Doesn't matter much if you know that person a lot or not, probably if you don't know the number or the person you will be very likely less prone to pick up the call, but in any case, nowadays many (myself included) think that is not very professional to take personal calls at work. Even if it's important (or we don't know yet that it is).

And once you have picked up that call, you will say you're very busy, that do not have enough time and... put-here-whatever-the-excuse-you-want. Sometimes is just because you don't want to talk to that person, but in the end there is always that work feeling that tells you that you're being unprofessional. As if Facebooking and so on were not procrastinating... like your company does not have a proxy and a list of all the websites you visit and how muchtime you spend on each one...

But work is the perfect excuse not to talk to that person, that day, at that very same moment.

We are becoming fucking zombies.

Etiquetas: , ,

17 de enero de 2014

Frogr 0.9 released

So, after a bit more than one year without releasing any version of frogr, I finally managed to get some “spare” time to put all the pieces together and ship the ninth version of it, which I believe/hope is going to be a quite solid one.

Frogr 0.9

In all honesty, though, this version does not come with many new features as the previous ones, yet some changes and fixes that I believe were quite necessary, and therefore should help improving the user experience in some subtle ways.

For instance, the layout of the dialog to edit the details of a picture has changed (as per Ana Rey‘s comments during GUADEC) to enable a more efficient usage of vertical space, so much needed these days in small widescreen laptops. Of course, design-wise still sucks, but I believe it’s much more convenient now from a pragmatical point of view.

Also, frogr is now a little bit more “modern” in things such as that it now supports GStreamer 1.0 (0.10 still supported), a lot of deprecated code (e.g. Stock items, GtkActions) has been replaced internally and it now integrates better with GNOME Shell’s search box. Ah! and it also now provides an AppData file to integrate with GNOME Software Center, which is a nice touch too.

Another interesting thing is that I finally fixed the problem that we have with multiple selections in the main view, which was neither intuitive nor very useful, as Ctrl and Shift modifiers did not work as expected. So, from now on, it is finally possible to work with disjoint multiple selections of pictures, a feature I was missing so much.

Last, I fixed two important problems in the code that caused frogr consume two much memory, specially after uploading pictures. It was a quite severe problem since frogr was not properly freeing the memory used by pictures even after those were uploaded and removed from the UI, causing important issues in cases where people tried to upload a lot of pictures at once. It’s hopefully fixed now.

And that’s all I think. As usual, you can check the website of the project to know how to install frogr on your system if you don’t want to wait for your favourite distribution to ship it, or if you just want to check more information about the project or to contribute to it.

FOSDEM 2014

Ah! By the way… I’m going to FOSDEM again this year, but this time by train. Can’t wait to be there! :)

15 de enero de 2014

Updating CAcert.org X.509 certificates for CentOS

My SSL/TLS certificate has expired so I need to request a new one and I'm summing here all the process.

As my current configuration is more or less a mess, I'm starting from the very begining but I assume you are registered at CAcert.org and you are able to request server certificates for your verified domains. I'll use my tormento.olea.org server as the hostname example.

The better way to me is to use CAcert.org key and CSR creation script (which uses openssl), specially needed when you want to add several domains to the certificate.
# sh csr
Private Key and Certificate Signing Request Generator
This script was designed to suit the request format needed by
the CAcert Certificate Authority. www.CAcert.org

Short Hostname (ie. imap big_srv www2): tormento
FQDN/CommonName (ie. www.example.com) : tormento.olea.org
Type SubjectAltNames for the certificate, one per line. Enter a blank line to finish
SubjectAltName: DNS:olea.org
SubjectAltName: DNS:www.olea.org
SubjectAltName: DNS:olea.es
SubjectAltName: DNS:www.olea.es
SubjectAltName: DNS:ismael.olea.org
SubjectAltName: DNS:
Running OpenSSL...
Generating a 2048 bit RSA private key
.............+++
................................................................................................+++
writing new private key to '/root/tormento_privatekey.pem'
-----
Copy the following Certificate Request and paste into CAcert website to obtain a Certificate.
When you receive your certificate, you 'should' name it something like tormento_server.pem

-----BEGIN CERTIFICATE REQUEST-----
blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblahblahblahblah
-----END CERTIFICATE REQUEST-----

The Certificate request is also available in /root/tormento_csr.pem
The Private Key is stored in /root/tormento_privatekey.pem

Note: I found the genkey tool (from the crypto-utils package) takes a lot of more time to generate a same key lenght. Probably due to some kind design goal. I think you could use genkey to generate the key and the csr script for the multi-dns CSR request.

Then I move files to correct systems places:

mv /root/tormento_csr.pem /etc/pki/tls/certs/tormento.olea.org.0.csr.pem
mv /root/tormento_privatekey.pem /etc/pki/tls/private/tormento.olea.org.key.pem

Then I ask for a certification at CAcert website. CAcert recomends to select a Class 3 root certificate.

Cut and paste the certificate from the browser into the system:

# cat > /etc/pki/tls/certs/tormento.olea.org.crt.pem

You can check the certificate is correct using openssl. And you'll receive an email from CAcert reporting about the new certificate.


Then you can configure your applications to use the new crypto key and certificate.

applications:

These are the applications I've configured for my needs. You have other configuration examples at CAcert website.

postfix

# grep tls /etc/postfix/main.cf

smtpd_tls_key_file = /etc/pki/tls/private/tormento.olea.org.key.pem
smtpd_tls_cert_file = /etc/pki/tls/certs/tormento.olea.org.crt.pem
smtpd_tls_CAfile = /etc/pki/tls/certs/CAcert_chain.pem
smtp_use_tls = yes
smtp_tls_key_file = /etc/pki/tls/private/tormento.olea.org.key.pem
smtp_tls_cert_file = /etc/pki/tls/certs/tormento.olea.org.crt.pem
smtp_tls_CAfile = /etc/pki/tls/certs/CAcert_chain.pem

ejabberd

Create a key + certificate file:
# cat /etc/pki/tls/private/tormento.olea.org.key.pem > /etc/pki/ejabberd/certs/ejabberd.pem
# cat /etc/pki/tls/certs/tormento.olea.org.crt.pem >> /etc/pki/ejabberd/certs/ejabberd.pem
# chown -R ejabberd.ejabberd /etc/pki/ejabberd/
# chmod a-rw,u+r -R /etc/pki/ejabberd/

dovecot

apache

Common things you would need to do with your certificates and keys:

Export public key:

openssl rsa -in /etc/pki/tls/private/tormento.olea.org.key.pem -pubout -out  /etc/pki/tls/public/tormento.olea.org.pub.pem -outform PEM

Print human readable key data:

openssl rsa -noout -text -in /etc/pki/tls/private/tormento.olea.org.key.pem

Print human readable certificate contents:

openssl x509 -noout -text -in /etc/pki/tls/certs/tormento.olea.org.crt.pem

Other info of interest

I've not studied it yet but probably it's worth to read the Fedora developments on managing system crypto keys and signatures:

14 de enero de 2014

Convocatoria: encuentro del taller de hardware abierto

La chavalada, la #GenteQueHaceCosas con hardware en Almería, se ha organizado en un taller permanente de hardware abierto y ha decidido realizar su primer encuentro presencial específicamente dedicado al cacharreo.

Dirigido a

  • Ti, que te mola el cacharreo.
  • Para ti también, que tienes ganas locas de empezar.
  • A ti también, que te dedicas profesionalmente a estos temas pero que ahora quieres jugar.
  • A ti también, aunque sabemos que sólo lo haces para impresionar a las visitas.
  • Tú, que no has pensado todavía qué hacer para el proyecto de fin de carrera, vente un rato y alguna idea se te puede ocurrir entre tanto disparate.
  • Y a ti también, que para las pocas chicas que suelen venir no queremos que faltes. Tráete a tus amigas, por favor.
  • Y si tu eres de los que ha ganado algún campeonato de Lego Mindstorms vente y explícale tu arte a todos estos aprendices.

Programa

  • Charla: electrónica libre. Estado del arte y presentación de dispositivos y proyectos.
  • Debate: ¿Se puede vivir haciendo electrónica libre? ¿Cómo hacerlo? ¿Qué licencias elegir? ¿Hay que patentar?
  • Propuestas para definir un programa de actividades dentro de los próximos encuentros de hardware libre.

Traed vuestras propuestas. Traed a todas vuestras amistades que tengan interés. Y si tenéis vuestros propios trastos, traedlos e impresionad a los parroquianos.

Coordenadas espacio-temporales

staticmap

Los amiguetes de La Oficina Cultural se prestan a darnos cobijo en su local y la cita es:

miércoles 22 de enero
20:30h

Recordad que en La Oficina hay comercio y bebercio a precios populares y que consumiendo todos un poquito les ayudamos a mantener la actividad..

¡Happy hacking!









El día que Personet reemplace a Internet

Lo típico de que Yorokobu te pide un párrafo de prospectiva a 100 años vista y va y te sale una distopía: «el día que Personet reemplace a Internet». Así no hay manera.

Controlando una Nikon D90 con un Android

Gracias a que mi hermano y su mujer me regalaron un filtro para la cámara he retomado un poco la pasión por la fotografía, haciéndo algo que llevába buscando desde hace mucho tiempo: timelapse.
El caso es que se me ocurrió andar buscándo cómo hacerlo en mi Nikon D90, ya que al ser una cámara profesional (o casi) debería tener la función. Error, no la tiene pero me enendió la bombilla para buscar una aplicación para el móvil, quizá hacerme con un intervalómetro, pero tras ver los precios (unos 50 dólares) lo descarté. Tras buscar mucho encontré que, efectivamente, no soy el primero al que se le ocurre.

Lo primero que encontré fueron muchos programas e información para hacerlo por infrarrojos, algo que mis móviles no tienen, así que quedó inmediatamente descartado —además es engorroso—. Lo siguiente fueron módulos WiFi para la cámara pero son caros (unos 60 dólares) y fundirían la batería. Así que seguí buscando y encontré cómo hacerlo con un cable USB. Bendito USB. No obstante leí en un par de foros que había que fabricarse el cable... demasiado engorro. Así que del tirón probé un par de cables que tenía con el teléfono y la cámara y al cabo Intervalómetros varios intentos y aplicaciones resultó que funciona. ¡Eureka!

Encontré la página perfecta de un buen hombre comentando cómo lo había hecho y el precio de cada componente (incluída aplicación de pago). Según sus precios debía salir por unos 10 dólares (zapata, trípode y cable USB) pero eso es en su mundo, en mi checomundo ha salido algo más caro, aunque tengo prácticamente lo mismo que él. 

Aún así decidí probar a tirar unas fotos con mi trípode de alumino que apenas aguanta el peso de la cámara y con el móvil en el bolsillo. El resultado no fue malo, pero de vez en cuando se mueve la cámara y resulta incómodo por dos motivos: porque no te puedes mover mucho —y tienes que estar cerca de la cámara por el cable— y porque el trípode es de 120cm, con lo que me tenía que agachar mucho para ajustar la cámara.

[http://www.youtube.com/watch?v=7qKSEPE3dQE]

El material total que me hacía falta para mejorar la situación, y asemejarme al fulano del blog, se componía de algún elemento más, a saber:

El precio total de los componentes fue:1812+ 25 de transporte, en euros de hoy: 67.

Al final no pude hacer funcionar el N1 con la cámara porque requiere un kernel 3.X y los kernel personalizados no me funcionan, eso si, tengo una flamante CyanogenMod 10 con un kernel 2.6 que no voy a usar mucho.

Las dos aplicaciones que he probado son: 

No tengo nada en contra de aplicaciones de pago, pero no voy a pagar entre 10 y 20 euros por una aplicación que, en principio, no sabía si iba a funcionar con mi trinomio teléfono-cable-cámara. Así de sencillo.

[https://www.youtube.com/watch?v=Y7luDmDDP8] 

Ahora habrá que ver si lo vale o no, pero parte del material me hacía falta de cualquier manera, así que no me preocupo mucho por ello.

Etiquetas: , ,

10 de enero de 2014

Xamarin

After some well deserved relaxing time, I am glad to announce that, since last Tuesday, I am a happy member of the Xamarin crew, where I’ll be working on the awesome cross-platform development tools the company makes.

This is indeed a change from what I have been doing in the last years, as I will be focusing on platforms other than Linux, as has been the case for the last 15 years, but to be honest, and after thinking a lot about it during my “well deserved relaxing time”, this is something that I really needed to boost my career. Not working on other platforms, but moving out of my comfort zone and find something new and exciting to work on. And Xamarin really seems to be the perfect place for this: the company is full of ex-Ximianites (Ximian is, till now, the best company I have ever worked for), lead by great people and focused on making great development tools/APIs, which is something that I have always liked but haven’t had the chance to work on as much as I would have wanted.

Of course, this doesn’t mean I will stop caring/using/developing GNOME. On the contrary, I think, and based on what I have been working on during my vacation, this will help me in making a better contribution to the project, as a lot of things I have been/will be learning, I think, are great for making GNOME better. But will talk about all that in separate blog posts, as things progress.

Many thanks to my girlfriend Yolanda and my friend Ismael Olea, who were the ones to pinpoint what I needed, which was to look for some exciting new stuff, rather than only wanting to stay on my comfort zone, and to Miguel, for the great coding challenge he got me to do, which made me learn exciting stuff and convince me finally that Xamarin was the best place for me.

09 de enero de 2014

Convocatoria: asamblea de gente de Almerí­a que hace cosas con las TIC

Tras el modesto aun cuando satisfactorio éxito del pasado «encuentro e intercambio de experiencias para emprendedores tecnológicos» surgieron montones de ideas y propuestas que abundan en las que, con mayor o menor intensidad, están desarrollando en paralelo otros colectivos de Almerí­a como los encuentros de BetaBeers, los grupos locales de Android o GDG y, en la universidad, la veterana asociación UNIA. Por eso, durante una tormenta de ideas con Víctor Suárez hace unos dí­as pensamos que serí­a una gran idea convocar a la peña para compartir todas las ideas que se están poniendo en marcha y ponernos al dí­a con las novedades, alguna de las cuales es muy jugosa. De ahí esta convocatoria.

A la atención de

En esta ocasión el público convocado es gente con perfiles técnicos TIC muy fuertes: programación, diseño de hardware, administración de sistemas, etc, y con vocación de actividades en comunidad (talleres, conferencias, hackatones, etc) e, idealmente, afinidad por el software libre / opensource.

El acceso es completamente abierto hasta completar aforo y está invitada cualquier persona que tenga ganas de implicarse en la comunidad tecnológica de Almerí­a... si es que no lo está ya. Os rogaos que difundáis esta convocatoria y la hagáis llegar a todas las personas inquietas de vuestros cí­rculos sociales.

Orden del día

Básicamente esperamos hablar al menos de:

  • el calendario aproximado de todas las actividades previstas, como mí­nimo, hasta junio;
  • ajuste y coordinación de las fechas de las mismas, si procede;
  • presentación de las ayudas ofrecidas al Google Developer Group local a la hora de organizar actividades y conferencias
  • exposición de  algunas de las actividades en gestación como:
    • el hackaton presencial de programación
    • el hackaton virtual
    • las actividades durante la próxima Feria de las Ideas (30 de abril de 2014)
  • y lo que surja.

Objetivos

Básicamente acordar un calendario de actividades sincronizado y asignarnos el trabajo de los voluntarios para cada una de ellas.

Coordenadas espacio-temporales

staticmap

Los amiguetes de La Oficina Cultural se han prestado a darnos cobijo en su local y la cita es:

viernes 10 de enero
19:00h

Recordad que en La Oficina hay comercio y bebercio a precios populares y que consumiendo todos un poquito les ayudamos a mantener la actividad.

Finalmente señalar que la reunión va a ser muy práctica pero también muy informal. Traed vuestras mejores ideas y todas las ganas para hacer de Almería un pequeño vórtice de activades TIC cañeras.

Nos vemos este viernes.

29 de diciembre de 2013

Emigrar con cabeza

Con la escalada de paro en España la gente empezó a emigrar, a buscarse un futuro mejor, o un futuro sin más. Uno, que ya está fuera, no deja de ver vídeos de todo tipo de pobrecitos que han emigrado a distintos países y ciudades y han acabado mendigando por Noruega, quejándose de Londres (y con dos carreras) o atrapados en medio de Alemania por una promesa que no llegó a ser. Y le da pena y lo entiende, pero también le sale la vena racional y se da cuenta de los errores que comete mucha gente. Por ello voy a dejar unos comentarios acerca de lo que consideré básico antes de salir de España, a modo de sugerencias, por si puedieran servirle a alguien.

La siguiente serie de puntos, más o menos ordenados, reflejan lo que debería ser un pequeño estudio antes de armarse de valor y emigrar a otro país para evitar, en la medida de lo posible, que se den situaciones como las que comenté anteriormente.

Sigue leyendo...

Etiquetas:

23 de diciembre de 2013

Como el blog ha muerto, escribo esto

Como el blog ha muerto, aprovecho. Abundan análisis asegurando que determinadas tecnologías están muriendo o ya lo habrán hecho. Pero a estos vaticinios, como los de que la TV ha muerto o al PC le quedan dos días, no hacen más que darle largas. Razones hay sobradas y no entraré mucho en ellas.

Pero aprovecho: mi blog está (de hecho, un año más sigue igual) abandonadito. Pero la culpa es mía y solo mía. Mi twitter también está prácticamente paralizado. Y mi facebook casi solo lo uso para subir fotos personales y hacer click en los megusta familares y de confianza (al resto no, porque no distingo muy bien entre las fotos-megusta-para-recopilar-contactos (y luego hacer spam) y las fotos que no caen en la categoría anterior).

Al resto de los blogueros, tuiteros y feisbukers del mundo, os animo a que sigáis ahí, si tenéis tiempo y ganas. Por cierto, que yo seguiré usando el PC (además de juguetitos diversos muy monos pero indudablemente menos usables) y seguiré con el PC como herramienta principal mientras los fabricantes no me obliguen a dejar de usarlo. Porque por ahí es por donde vendría, el final del PC, no creo que de otra forma. Si es que viene…

Y bueno, para demostrar que el blog no ha muerto, aprovecho para felicitaros las fiestas y desearos un año 2014 con mucha tecnología y mucha más humanidad.

Merry Christmas

(como yo siempre me he llevado muy mal con los photoshop, powerpoints y compañía, he buscado uno hecho con licencia libre y aquí os lo dejo con sus créditos, para que no se diga ;-)

Como el blog ha muerto, ¡Feliz Navidad!

13 de diciembre de 2013

WebKitGTK+ Hackfest 2013: The Return of the Thing

The WebKitGTK+ Hackfest 2013As many other WebKitGTK+ hackers (30 in total), I flew last Saturday to A Coruña to attend the 5th edition of the WebKitGTK+ Hackfest, hosted once again by Igalia at their premises and where people from several different affiliations gathered together to try to give our beloved port a boost.

As for me, I flew there to work mainly on accessibility related issues, making the most of the fact that both Joanie (Orca maintainer) and Piñeiro (ATK maintainer) would be there too, so it should be possible to make things happen faster, specially discussion-wise.

And turns out that, even if I feel like I could have achieved more than what I actually did (as usual), I believe we did quite well in the end: we discussed and clarified things that were blocking the mapping of new WAI-ARIA roles in WebKitGTK+, we got rid of a bunch of WebKit1-specific unit tests (Joanie converted them into nice layout tests that will be run by WebKit2GTK+ too), we got a few new roles in ATK to be able to better map things from the web world and and we fixed a couple of issues in the way too.

Of course, not everything has been rainbows and unicorns, as it seems that one of the patches I landed broke the inspector for WebKit2GTK+ (sorry Gustavo!). Fortunately, that one has been rolled out already and I hope I will be able to get back to it soon (next week?) to provide a better patch for that without causing any problem. Fingers crossed.

In the other hand, my mate Brian Holt joined us for three days too and, despite of being his first time in the hackfest, he got integrated pretty quickly with other hackers, teaming up to collaborate in the big boost that the network process & multiple web processes items have went through during the event. And not only that, he also managed to give a boost to his last patch to provide automatic memory leak detection in WebKitGTK+, which I’m sure it will be a great tool once it’s finished and integrated upstream.

Anyway, if you want more details on those topics, or anything else, please check out the blog posts that other hackers have been posting these days, specially Carlos’s blog post, which is quite extensive and detailed.

Samsung LogoOf course, I would like to thank the main sponsors Igalia and the GNOME Foundation for making this thing happen again, and to my employer Samsung  for helping as well by paying our trips and accommodation, as well as the snacks and the coffee that helped us stay alive and get fatter during the hackfest.

Last, I would like to mention (in case anyone reading this wondered) that it has indeed felt a bit strange to go the city where I used to live in and stay in a hotel, not to mention going to the office where I used to work in and hang around it as a visitor. However, both my former city and my former colleagues somehow ensured that I felt as “at home” once again, and so I can’t do anything about it but feeling enormously grateful for that.

Thank you all, and see you next year!

12 de diciembre de 2013

WebKitGTK+ Hackfest 2013: The Network Process

As every year many ideas came up during the WebKitGTK+ hackfest presentation, but this time there was one we all were very excited about, the multiple web processes support. Apple developers already implemented the support for multiple web processes in WebKit, which is mostly cross platform, but it requires the network process support to properly work (we need a common network process where cookies, HTTP cache, etc are shared for all web processes in the same web context). Soup based WebKit ports don’t implement the network process yet, so the goal of the hackfest became to complete the network process implementation previously started by EFL and Nix guys, as a first step to enable the multiple web processes support. Around 10 people were working on this goal during the whole hackfest, meeting from time to time to track the status of the tasks and assigning new ones.

After all this awesome work we managed to have the basic support, with MiniBrowser perfectly rendering pages and allowing navigation using the network process. But as expected, there were some bugs and missing features, so I ran the WebKit2 unit tests and we took failing tests to investigate why they were failing and how to fix them.

So, we are actually far from having a complete and stable network process support, but it’s a huge step forward. The good news is that once we have network process implemented, the multiple web processes support will work automatically just by selecting the multiple web process model.

All this sounds like a lot of work done, but that’s only a small part of what has happened this week in Coruña:

  • Martin and Gustavo made more parts of WebKit actually build with the cmake build.
  • Jon made several improvements in Epiphany UI.
  • Gustavo fixed the default charset encoding used by Epiphany.
  • Iago, Edu made some progress in the wayland support for WebKit2.
  • Dan was working on HTTP2 implementation for libsoup.
  • Zan was finalizing his GSoC work under Martin’s mentorship to bring WebGL support under Wayland
  • Gustavo added support for right-side docking of the web inspector in WebKitGTK+.
  • Javi, Rego and Minhea were focused on a new implementation for the selections in CSS regions.
  • Calvaris began to rewrite the GTK media controls once more, this time in JavaScript.
  • Zan finished the patches to add battery support in WebKitGTK+ using upower.
  • Martin, Gustavo and Zan worked on support for testing WebGL and accelerated compositing layout tests in WebKitGTK+.
  • Brian, Alex and Zan were working on the parsing of the valgrind xml output used when running the tests under valgrind to detect memory leaks.
  • Brendan added a setting to both WebKit1 and WebKit2 APIs to enable media source and fixed a crash in several video layout tests.
  • Claudio went back to his work on the notifications support for WebKitGTK+ and was reviewing patches like crazy.
  • Philippe worked on the WebRTC implementation for the GStreamer WebKit media backend.
  • Mario, Joanie and API were focused on accessibility, also making sure that the multiple web processes doesn’t affect the accessibility support.
  • Brendan also worked on MediaSource, investigating how to handle video resolution changes.
  • I removed all the WebKit1 unused code from Epiphany, and moved the GNOME shell search provider to its own binary.

And I’m sure I’m missing more great stuff done that I could not follow closely. It’s definitely been a very productive hackfest that it would haven’t been possible without the sponsors, Igalia and the GNOME Foundation. Thanks!

Igalia S.L. GNOME Foundation

03 de diciembre de 2013

Old times, new times

The facts narrated here happened on early November, but I’m apparently blog-constipated, hence the extra month…

So, after an overall of 6.5 years working on Lanedo (and former Imendio), I made my last day there on October 31st. After all that time, I consider it a privilege having worked with them, they’re a smart bunch and I’m very sure they’ll be doing fine ;)

After that? Shiny new times, this happened:

20131203_122215-small

On November 1st I joined Red Hat! And so far it’s been an incredible experience. With them, I’ve spent much of my time tinkering, surrounded by tablets, touchscreens and other input devices, and will be doing so in the foreseeable future, so expect bursts of activity around the input area :).

13 de noviembre de 2013

Greppin’ in the past with git

It seems that one can never stop learning new things with git, no matter for how long you’ve been using it (in my case, I’m a proud git user since 2008), because today I added a new trick to my toolbox, that already proved to be quite useful: “grepping” files in a git repository, as you would do it with git grep, but using a commit-id to limit the search to a specific snapshot of your project.

In other words, I found that it’s possible to do things like, say, grep files to search for something in your repository considering how it was, say, some commits ago.

This is the “magical” command:

    git grep <search-params> <tree-id>

This is what I get if I try to search for updateBackingStore() in my local clone of WebKit, as if my current branch was “50 commits older” than what it actually is:

$ git grep updateBackingStore HEAD~50
0ae236137d560da6ca889a826a8f3d023364a669:AccessibilityObject.cpp:void AccessibilityObject::updateBackingStore()
0ae236137d560da6ca889a826a8f3d023364a669:AccessibilityObject.h:    void updateBackingStore();
0ae236137d560da6ca889a826a8f3d023364a669:AccessibilityObject.h:inline void AccessibilityObject::updateBackingStore() { }
0ae236137d560da6ca889a826a8f3d023364a669:atk/WebKitAccessibleUtil.h:        coreObject->updateBackingStore(); \
0ae236137d560da6ca889a826a8f3d023364a669:atk/WebKitAccessibleUtil.h:        coreObject->updateBackingStore(); \
0ae236137d560da6ca889a826a8f3d023364a669:atk/WebKitAccessibleWrapperAtk.cpp:    coreObject->updateBackingStore();
0ae236137d560da6ca889a826a8f3d023364a669:ios/WebAccessibilityObjectWrapperIOS.mm:    m_object->updateBackingStore();
0ae236137d560da6ca889a826a8f3d023364a669:ios/WebAccessibilityObjectWrapperIOS.mm:    m_object->updateBackingStore();
0ae236137d560da6ca889a826a8f3d023364a669:mac/WebAccessibilityObjectWrapperBase.mm:    // Calling updateBackingStore() can invalidate this element so self must be retained.
0ae236137d560da6ca889a826a8f3d023364a669:mac/WebAccessibilityObjectWrapperBase.mm:    m_object->updateBackingStore();

I don’t know about you, but I find this quite useful for me to answer questions such as “Where was this function being used in commit X?”, and things like that.

Anyway, you might have noticed that I mentioned <tree-id> in the recipe instead of <commit-id>, yet I used HEAD~50 in the example, which is actually a commit-id. And still works.

And the short explanation, without trying to explain here all the different kind of data types that git keeps internally for every repository (mainly commitstrees and blobs), is that git is smart enough to find the right tree-id associated to a given commit-id by just considering the current path inside the repository and the tree-id associated to the top directory for a given commit.

But how to know that tree-id myself in case I want to? Easy, just pretty print the full information of the commit object you’re interested in, instead of only seeing the abbreviated version (what you usually see with git show or git log:

$ git cat-file -p HEAD~50
tree 0ae236137d560da6ca889a826a8f3d023364a669
parent bdb7a7949a29988da3fe50a65d6c694d5084d379
author [...]

See that tree thing in the first line? That’s the tree-id that git needs for grepping, which as you can see can be easily extracted from a particular commit. Actually, you could get easily the tree-id for any subdirectory from this point, by using the git ls-tree command:

$ git ls-tree 0ae236137d560da6ca889a826a8f3d023364a669
100644 blob 3fe2340c9614e893f0dfeb720f23773bbf1ea076	.dir-locals.el
100644 blob 741c4d53b5a0338cf36900a283e89408d0f9d457	.gitattributes
100644 blob f45a975762be9a429aa971c18da01b433c559553	.gitignore
100644 blob d571aa28ea86c14c7880533bf3ba68e9ef4b3c81	.qmake.conf
100644 blob 10f85055ae9f3823f0d20808599f644c18af7921	CMakeLists.txt
100644 blob 5eb66e7bcbc7543eb3a4dbf183a9043545776659	ChangeLog
100644 blob 7dbe9d2e0029bab47b8b2b22065a1032ecfe4434	ChangeLog-2012-05-22
040000 tree d42a0b3121ed7993cfd250426d20472769760f87	Examples
100644 blob 78d89e5c70ad56c38b0c25e7705d42fa380c4ee0	GNUmakefile.am
040000 tree 4a9e87fc1f35efa1349a18b1df694530c981c57e	LayoutTests
100644 blob 14e33157011157797dac62c494bac0bf254d7c2f	Makefile
100644 blob ee723d830dea51d1ce9e2d1ad8c985eeca2d4f3f	Makefile.shared
040000 tree 20c763d6a4e8749ad9e041e8372e9f47dc722f45	ManualTests
040000 tree 660d88b926cf618ab9e1612b8e2a3e97b15dbcbe	PerformanceTests
040000 tree fbf9703d3e9a9e4cf2ff10817c99ba3a5de87410	Source
040000 tree 346110c441a674334f5f56ef42b9dd40def89c76	Tools
040000 tree 262cb11d9b491be35daee570f9b825bce5715579	WebKit.xcworkspace
040000 tree b9e48a7a24b4973b253ee14053808b40d67c94aa	WebKitLibraries
040000 tree adce37b690957abdd21d2dd8ff77302c5a5a9071	Websites
100755 blob befd429487fc5ac9bb3494800f4eeaef1e607663	autogen.sh

And of course, “navigating” with more calls to git ls-tree you could also get the tree-id for a specific subdirectory, in case you wanted to constraint the search to that specific path of your repo.

However, considering that git is so good at translating a commit-id into a tree-id, my personal recommendation is that, instead, you first cd into the path you want to focus the search in, and then let git  do its “magic” by just using the git grep <search-params> <tree-id> command.

So that’s it. Hope you find this useful, and please do not hesitate to share any comment or suggestion you might have with regard to this or any other “git trick” you might know.

I honestly love using git so much that sometimes I wonder if coding is not just a poor excuse to use git. Probably not, but the thing is that I can not imagine my life without it anymore. That’s a fact.

08 de noviembre de 2013

Farewell Collabora

Today has been my last day at Collabora, where I’ve spent the last 2 years having a great time and working on some very cool and some not that cool projects, but always with great people as teammates. On the cool projects front, AF_BUS wins. Even though it didn’t gain upstream acceptance, at least it opened the race to bring D-Bus into the kernel, which I think is a great thing (based on real numbers :-D ).

A big hug to all collaborans I’ve met in these 2 years!

Not sure yet what’s coming up next, but first thing I will do, for the first time in aeons, is to get a few weeks of well deserved relax, work on some personal stuff I haven’t had much time to work on lately, and have fun!

30 de octubre de 2013

Anotaciones PDF en Poppler GLib

El fin de pasada estuve con el ánimo de terminar el soporte de anotationes en documentos PDF en Poppler GLib.

Para aquellos que no lo sepan, Poppler es la biblioteca utilizada por Evince (y por extensión Documents [vaya nombre]) para desplegar el contenido de documentos PDF. Cualquier mejora visual o de rendimiento en Poppler se ve automáticamente reflejado en Evince.

Partí por restructurar poppler-glib-demo para que fuera más sencillo agregar y probar múltiples tipos de anotaciones (el código estaba muy ligado a las anotaciones de texto, aquellas que parecen notas amarillas Post-it). Después de revisar el código fuente de anotaciones de Poppler, decidí implementar las anotaciones de líneas (sólo las simples), luego cuadrados y círculos; y, finalmente, marcado de texto (resaltado, subrayado, subrayado ondulado, tachado).

Aquí un video que muestra el progreso hasta el momento.

En el código de la demostración, yo no dibujo directamente en una superficie cairo, sino que añado la anotación a la página, la actualizo según el movimiento del puntero mientras está el botón presionado y le pido a Poppler que despligue el PDF resultante. Lo bueno de este enfoque es que se ve el resultado final del documento PDF mientras es modificado interactivamente. Lo malo es el potencial costo en rendimiento en aquellos documentos donde Poppler es lento de desplegar.

Si ya tienes compilado Evince con lo típico de jhbuild, entonces basta seguir unos simples pasos para probarlo:

$ cd /to/your/jhbuild/checkout
$ git clone https://github.com/gpoo/poppler.git
$ cd poppler
$ git checkout annot-demo-fixes
$ jhbuild make
$ jhbuild shell poppler/glib/demo/poppler-glib-demo <pdf-document>

Los futuros pasos son: mejoras las anotaciones en Evince, editar y mover anotaciones, añadir más tipos de anotaciones y pulir.

Mi motivación para hacerlo es que Evince es una aplicación crítica para mí. Leo muchos documentos PDF y también produzco algunos. Para anotar documentos he estado usando ezPDF Pro (para Android), conveniente pero no es Software Libre y no me sirve en el escritorio, donde paso la mayor parte del tiempo. El visor de Mendeley es lo más cercano a mis necesidades, pero tampoco es Software Libre. Scholiar (un derivado de Xournal) es bueno para anotar en documentos, pero guarda realmente las anotaciones como tales en los documentos PDF, sino que las funde con el resto del contenido (me imagino como formar de suplir las carencias de Poppler GLib). Así que espero tener otro fin de semana similar para terminar lo que falta.

28 de octubre de 2013

Launchpad pull request

So you want to do a pull-request to a LaunchPad project?
Stop right there! The content of this blog post has been migrated to this question in stackoverflow. Move on, nothing to see here.

24 de octubre de 2013

¿Quién lanzó esta ventana?

Problema: una aplicación ha lanzado una ventana en tu escritorio, pero no sabes exactamente qué aplicación es “la culpable”. Solución: desde una terminal, lanzamos el comando $  xwininfo Nos dará un ID de ventana. Por ejemplo, en mi caso, el 0x3e00004. Pedimos ahora las propiedades de ese ID y, más en concreto, el identificador del proceso […]

13 de octubre de 2013

Cómo desactivar el uso de tu nombre y tu foto en la publicidad de Google

No la he tomado con Google. Pero sí, eso de que la gente vea mi nombre y mi foto vinculados a la publicidad no me convence. Aunque solo lo vayan a ver mis contactos. Para variar, localizar el enlace para desactivar esta opción (que está activada de forma predeterminada a todos los usuarios) no es demasiado evidente: para que no os volváis locos buscando y acabéis convencidos de que Google no da opción a desactivar vuestra vinculación a la publicidad, deciros que basta con entrar en vuestra cuenta y seguir este enlace concreto. Al final de la página se encuentra la opción a desactivar. También se llega a esta página a través de una notificación que supongo habrá recibido todo el mundo (ver vídeo) pero sería preferible que estuviera más claro cómo desactivar este tipo de cosas, y tampoco estoy muy seguro de que la gente lea atentamente este tipo de notificaciones. En fin…

27 de septiembre de 2013

WebKitGTK+ 2.2.0: It shines and doesn’t blink

With a bit of delay but we have finally released a new stable version of WebKitGTK+. This is the first stable release after the major 2.0 release. It mainly contains a lot of bug fixes and a few important new futures and API additions.

New Web Inspector

WebKitGTK+ now uses the new Web Inspector recently opensourced and upstreamed by Apple. We took advantage of the migration to improve the way inspector resources are distributed by compiling them in the WebKitGTK+ library as GResources. This means that resources are now always available without having to run make install or set environment variables.

WebKitGTK+ new Web Inspector

Initial Wayland support

WebKitGTK+ 2.2 can be built with Wayland target if it’s available (it requires GTK+ 3.10 compiled with Wayland support). Not everything is fully supported yet, but the WebKit layout tests can be run under the Weston compositor and WebGL content works under Wayland displays too. There’s more detailed information in Žan Doberšek’s blog.

Video accelerated compositing support

When accelerated compositing is enabled, the GStreamer media player can play videos using OpenGL. You can find more details in Víctor’s blog.

Custom JavaScript injection

This was one of the major regressions in WebKit2GTK+ compared to the WebKit1 API. WebKitGTK+ 2.2 now allows to inject custom JavaScript code using the JavaScriptCore C API from a WebKit Web Process Extension. New API has been added to also allow running specific JavaScript code in isolated worlds. You can find examples about how to use this API and how to write Web Process Extensions in general in this post.

Improved accessibility support in WebKit2

Accessibility support in WebKit2 has been reworked to not depend on pango and gail, which resulted in several bugs fixed and a much better accessibility support. Check Mario’s blog for all the details.

New API

21 de septiembre de 2013

Software Freedom Day

15 de septiembre de 2013

LibreOffice Writer: desactivar corrector ortográfico en referencias de Zotero

Como ya presentamos en su día, Zotero es un gestor open source de referencias bibliográficas. Se integra perfectamente en el procesador de textos LibreOffice Writer… Bueno, perfectamente no, tiene un fallo, que es el que quiero comentar (y arreglar). Al añadir las referencias bibliográficas las inserta en el documento Writer sin preocuparse de cambiar el […]

13 de septiembre de 2013

Macro para recorrer y editar entradas de la tabla de contenidos en Writer

Supongamos que quieres recorrer la tabla de contenidos de un documento Writer para modificar automáticamente algunas de las entradas. Por ejemplo, supongamos que quieres cambiar las entradas que empiezan por ” PARTE” (como ” PARTE  1″, ” PARTE 2″…) por el mismo contenido pero en negrita, y añadirle un salto de línea a continuación. Es […]

Goodbye Pango! Goodbye GAIL!

As I mentioned in my previous post before GUADEC, I’ve been putting some effort lately on trying to improve the accessibility layer of WebKitGTK+, as part of my work here at Samsung, and one of the main things I’ve worked on was the removal of the dependency we had on Pango and GAIL to implement the atk_text_get_text_*_offset() family of functions for the different text boundaries.

And finally, I’m really happy to say that such a task is complete once and for all, meaning that now those functions should work as well or as bad on WebKit2GTK+ as they do in WebKitGTK+, so the weird behaviour described in bug 73433 is no longer an issue. You can check I’m not lying by just taking a look to the commit that removed both all trace of Pango and GAIL in the code, as well as and the one that removed the GAIL dependency from the build system. And if you want more detail, just feel free to check the whole dependency tree in WebKit’s bugzilla.

This task has been an interesting challenge for me indeed, and not only because it was one of the biggest accessibility related tasks I’ve worked on in WebKitGTK+ since late 2012 (so I needed to get my brain trained again on it), but also because reimplementing these functions forced me to dive into text editing and accessibility code in WebCore as I never did before. And it’s so cool to see how, despite of having to deal eventually with the frustrating feeling of hitting my head against a wall, at the end of the day it all resulted on a nice set of patches that do the work and help advance the state of the ATK based accessibility layer in WebKitGTK+ forward.

Anyway, even though that is probably the thing that motivated me to write this blog post, that was not the only thing that I did since GUADEC (which has been a blast, by the way):

On the personal side, I’ve spent two lovely weeks in Spain on holidays, which was the biggest period of time I’ve been outside of the UK since I arrived here, and had  an amazing time there just “doing nothing”(tm) but lying around on the beach and seeing the grass grow. And there is not much grass there anywhere, so you can imagine how stressful that life was… it was great.

In the other hand, on the professional side, I’d say that one of the other big things that happened to me lately was that I finally became accepted as a WebKit reviewer, meaning that now I can not only help breaking the Web, but also authorize others to do it so. And while agree that might be fun in some way, it probably would not be very cool, so forgive me if I try instead to do my best to help get exactly the opposite result: make things work better.

And truth to be told, this “upgrade” came just with perfect timing, since these days quite some work is being done in the accessibility layer for both the WebKitGTK+ and the WebKitEFL ports thanks also to my mates Denis NomiyamaAnton ObzhirovBrian Holt and Krzysztof Czech from Samsung, and that work would ideally need to be reviewed by someone familiar with the ATK/AT-SPI based accessibility stack. And while I’m still by far not the most knowledgeable person in the world when it comes to those topics, I believe I might have a fairly well knowledge about it anyway, so I assume (and hope) that my reviews will certainly add value and help with those specific pieces of work.

And as a nice plus, now I can finally “return the favour” to the only accessibility reviewer WebKit had until now (Chris Fleizach) by helping reviewing his patches as well, in a similar fashion to what he has been tirelessly doing for me for the last 3 years and a half. Yay!

To finish , I’d like to get back again to the original topic of this post and say a big “thank you” to everyone who helped me along the way with the removal of Pango and GAIL from the ATK specific code. Special thanks go to those who spend time performing the code reviews, as it’s the case of Martin, Gustavo and Chris. I wouldn’t be writing this post otherwise.

Thanks!

10 de septiembre de 2013

WebKit2GTK+ Web Process Extensions

The multiprocess architecture of WebKit2 brought us a lot of advantages, but it also introduced important challenges, like how to expose some features that now live in the Web Process (DOM, JavaScript, etc.). The UI process API is fully asynchronous to make sure the UI is never blocked, but some APIs like the DOM bindings are synchronous by design. To expose those features that live in the Web Process, WebKit2GTK+ provides a Web Extensions mechanism. A Web Extension is like a plugin for the Web Process, that is loaded at start up, similar to a GTK module or gio extension, but that runs in the Web Process. WebKit2GTK+ exposes a simple low level API that at the moment provides access to three main features:

  • GObject DOM bindings: The exactly same API used in WebKit1 is available in WebKit2.
  • WebKitWebPage::send-request signal: It allows to change any request before it is sent to the server, or even simply prevent it from being sent.
  • Custom JavaScript injection: It provides a signal, equivalent to WebKitWebView::window-object-cleared in WebKit1, to inject custom JavaScript using the JavaScriptCore API. (Since 2.2)

This simple API doesn’t provide any way of communication with the UI Process, so that the user can use any IPC mechanism without interfering with the internal WebKit IPC traffic. Epiphany currently installs a Web Extension to implement some of its features such us pre-filled forms, ads blocker or Do Not Track using D-BUS for the communication between the Web Extension and the UI Process.

How to write a Web Extension?

Web Extensions are shared libraries loaded at run time by the Web Process, so they don’t have a main function, but they have an entry point called by the WebProcess right after the extension is loaded. The initialization function must be called webkit_web_extension_initialize() and it receives a WebKitWebExtension object as parameter. It should also be public, so make sure to use the G_MODULE_EXPORT macro. This is the function to initialize the Web Extension and can be used, for example, to be notified when a web page is created.

static void
web_page_created_callback (WebKitWebExtension *extension,
                           WebKitWebPage      *web_page,
                           gpointer            user_data)
{
    g_print ("Page %d created for %s\n", 
             webkit_web_page_get_id (web_page),
             webkit_web_page_get_uri (web_page));
}

G_MODULE_EXPORT void
webkit_web_extension_initialize (WebKitWebExtension *extension)
{
    g_signal_connect (extension, "page-created", 
                      G_CALLBACK (web_page_created_callback), 
                      NULL);
}

This would be a minimal Web Extension, it does nothing yet, but it can be compiled and loaded so let’s see how to create a Makefile.am file to build the extension.

webextension_LTLIBRARIES = libmyappwebextension.la
webextensiondir = $(libdir)/MyApp/web-extension
libmyappwebextension_la_SOURCES = my-app-web-extension.c
libmyappwebextension_la_CFLAGS = $(WEB_EXTENSION_CFLAGS)
libmyappwebextension_la_LIBADD = $(WEB_EXTENSION_LIBS)
libmyappwebextension_la_LDFLAGS = -module -avoid-version -no-undefined

The extension will be installed in $(libdir)/MyApp/web-extension so we need to tell WebKit where to find web extensions before the Web Process is spawned. Call webkit_web_context_set_web_extensions_directory() as soon as possible in your application, before any other WebKit call to make sure it’s called before a Web Process is launched. You can create a preprocessor macro in the Makefile.am to pass the value of the Web Extensions directory.

myapp_CPPFLAGS = -DMYAPP_WEB_EXTENSIONS_DIR=\""$(libdir)/MyApp/web-extension"\"

And then in the code

webkit_web_context_set_web_extensions_directory (webkit_web_context_get_default (), 
                                                 MYAPP_WEB_EXTENSIONS_DIR);

The Web Extension only needs WebKit2GTK+ to build, so in the configure.ac you can define WEB_EXTENSION_CFLAGS and WEB_EXTENSION_LIBS using pkg-config macros.

PKG_CHECK_MODULES(WEB_EXTENSION, [webkit2gtk-3.0 >= 2.0.0])
AC_SUBST(WEB_EXTENSION_CFLAGS)
AC_SUBST(WEB_EXTENSION_LIBS)

This should be enough. You should be able to build and install the Web Extension with you program and see the printf message every time a page is created. But that’s a useless example, let’s see how to use the Web Extensions API to do something useful.

Accessing the DOM

The GObject DOM bindings API available in WebKit1 is also exposed in WebKit2 from the Web Extensions API. We only need to call webkit_web_page_get_dom_document() to get the WebKitDOMDocument of the given web page.

static void
web_page_created_callback (WebKitWebExtension *extension,
                           WebKitWebPage      *web_page,
                           gpointer            user_data)
{
    WebKitDOMDocument *document;
    gchar             *title;

    document = webkit_web_page_get_dom_document (web_page);
    title = webkit_dom_document_get_title (document);
    g_print ("Page %d created for %s with title %s\n", 
             webkit_web_page_get_id (web_page),
             webkit_web_page_get_uri (web_page),
             title);
    g_free (title);
}

Using WebKitWebPage::send-request signal

Using the Web Extensions API it’s possible to modify the request of any resource before it’s sent to the server, adding HTTP headers or modifying the URI. You can also make WebKit ignore a request, for example to block resources depending on the URI, by simply connecting to the signal and returning TRUE.

static gboolean
web_page_send_request (WebKitWebPage     *web_page,
                       WebKitURIRequest  *request,
                       WebKitURIResponse *redirected_response,
                       gpointer           user_data)
{
    const char *request_uri;
    const char *page_uri;

    request_uri = webkit_uri_request_get_uri (request);
    page_uri = webkit_web_page_get_uri (web_page);

    return uri_is_an_advertisement (request_uri, page_uri);
}

static void
web_page_created_callback (WebKitWebExtension *extension,
                           WebKitWebPage      *web_page,
                           gpointer            user_data)
{
    g_signal_connect_object (web_page, "send-request",
                             G_CALLBACK (web_page_send_request),
                             NULL, 0);
}

Extending JavaScript

Using the JavaScriptCore API it’s possible to inject custom JavaScript code by connecting to the window-object-cleared signal of the default WebKitScriptWorld. You can get the global JavaScript execution context by calling webkit_frame_get_javascript_context_for_script_world() for the WebKitFrame passed as parameter of the window-object-cleared signal.

static void 
window_object_cleared_callback (WebKitScriptWorld *world, 
                                WebKitWebPage     *web_page, 
                                WebKitFrame       *frame, 
                                gpointer           user_data)
{
    JSGlobalContextRef jsContext;
    JSObjectRef        globalObject;

    jsContext = webkit_frame_get_javascript_context_for_script_world (frame, world);
    globalObject = JSContextGetGlobalObject (jsContext);

    /* Use JSC API to add the JavaScript code you want */
}

G_MODULE_EXPORT void
webkit_web_extension_initialize (WebKitWebExtension *extension)
{
    g_signal_connect (webkit_script_world_get_default (), 
                      "window-object-cleared", 
                      G_CALLBACK (window_object_cleared_callback), 
                      NULL);
}

06 de septiembre de 2013

Instalar Ubuntu 13.04 en iMac 27″

Un apunte rápido, porque ha sido coser y cantar, a diferencia del martirio por el que tuvimos que pasar en 2010 y que dejamos documentado. Realmente lo único que he necesitado ha sido la versión AMD64 de Ubuntu 13.04 (la vez anterior tuve que descargar explícitamente la versión “alternate”, esta vez ha bastado con la versión […]

04 de septiembre de 2013

Control de líneas huérfanas y viudas en LibreOffice Writer

La Wikipedia define perfectamente las líneas viudas y huérfanas: son líneas que, por quedar en una página distinta que el resto del párrafo al que pertenecen, aparecen aisladas de su contexto. En la imagen de la izquierda tenemos un ejemplo de línea viuda (aquella que, siendo la última de un párrafo, aparece al principio de […]

02 de septiembre de 2013

Referencias y bookmarks en LibreOffice

Redactando un documento te das cuenta de que quieres crear un enlace a sección del texto. Por ejemplo, estás redactando una receta y quieres crear un enlace a la zona de ingredientes. Lo mismo que cuando redactando un documento HTML quieres crear un enlace interno, de una parte del documento a otra. ¿Cómo hacerlo en […]

01 de septiembre de 2013

HackIt! 2013. Level 8. RPN (y II)

Warning: si no has intentando entender el intérprete RPN antes, ni te molestes en leer este post, porque te sonará a chino. Lo dejo explicado aquí para aquellos que se hayan pegado con este reto y no hayan obtenido la solución o estén totalmente atascados. Al resto de los mortales les puede explotar la cabeza […]

29 de agosto de 2013

El spam en los calendarios de Gmail

Últimamente se ha puesto de moda enviar spam en forma de invitación al calendario. Toda una nueva forma de molestar, sobre todo porque los filtros antispam de Gmail aun no están bien entrenados y además tienen un fallo importante: si tienes activas las notificaciones SMS para invitaciones a eventos, éstas te llegan aunque la invitación al evento haya sido clasificado como spam por Gmail. Es decir, en los sistemas de Google parece primero se procesa el correo como invitación a evento y luego se le pasa los filtros antispam, por lo que te llega el SMS aunque luego encuentres la invitación en la carpeta de Spam. Mientras Google corrige (o no, como suele pasar X-D ) este problema, no hay más remedio que desactivar los SMS para invitaciones a calendarios si no queremos recibir un SMS a horas intempestivas… nos tenemos que ir a la Configuración -> Calendarios -> Configuración de Notificaciones y desactivar SMS aquí:

evitar SMS de spam

Este truco ha sido fácil (más que el de mi entrada anterior, porque no tiene nada que ver con Google+ :-D), pero como siempre es una opción un poco escondida.

27 de agosto de 2013

Los calendarios de gmail y Google+

Poco a poco, Google+ va entrando doblada en nuestras vidas. En esta ocasión, me he encontrado que el spam de las invitaciones a eventos se me cuelan en el calendario de Gmail sin yo quererlo. Me ha costado ver cómo desactivarlo, pero finalmente lo encontré. Eso sí, probablemente tenga algún efecto secundario (como el hecho de no ver invitaciones a eventos que no lleguen mediante Google+). En cualquier caso, este tipo de invitaciones sí deberíamos recibirlas por otros medios (e-mail).

Por si a alguien le interesa, la forma de desactivar la integración entre eventos spam de Google+ y el calendario (sin renunciar a la cuenta de Google+, que también es, hasta que Google lo prohíba, otra solución), consiste en poner un No bien grande en un par de opciones de la configuración de Google Calendar:

Calendarios sin GooglePlus