LV Engine Blog
News and notes from the LV Engine team

Search this blog


More LV Engine

LV Engine DevZone
LV Engine Help
LV Engine Company
LV Engine is the name of a portuguese company, specialized on web solutions but also the name of our flagship product – a complete web application suite on-demand. In fact, this blog is powered entirely by LV Engine.
Posted last year, by Hugo Costa | about php

This one I just learned the hard way. Both str_replace and the case-insensitive brother str_ireplace, work by replacing each occurrence one by one.

Lets take this example:

$phrase = "my name is john";

echo str_replace(array("name", "john"), array("lastname", "doe"), $phrase);
will echo: my lastname is doe
if we replace by the same matching occurrence:
$phrase = "my name is john";

echo str_replace(array("name", "john"), array("john", "doe"), $phrase);
will echo: my doe is doe
meaning, name is replaced by john but john then is replaced by doe
 
If we want one replacing operation, we should use strtr :
$phrase = "my name is john";

echo strtr($phrase, array("name"=>"john", "john"=>"doe"));
will echo: my john is doe
(Notice the different syntax writing the function parameters, that in my opinion is much cleaner)
Posted last year, by Luís

Yesterday I was playing with a WDS configuration, and I needed to flash my old WRT54GS to a new tomato build. In 2 clicks I've bricked (again) my WNR3500L router because I selected the wrong browser window to flash the router... (so I flashed a MIPS1 firmware on a MIPS2 hardware).

Luckily the Netgear has a quick (although dangerous) recovery method. I've found this method buried in some thread on www.myopenrouter.com but I can't remember exactly where.

  1. Download the special firmware for "initial flashing" from dd-wrt here . (you can also use the default firmware from netgear)
  2. Download a tftp client, for windows you could use tftp32 , for mac you already have the tftp command line client, for linux you should be able to install tftp utils from your distro of choice
  3. Setup your network interface computer to 192.168.1.2 / 255.255.255.0
  4. Open the router
    1. Remove the bottom screw
    2. Drag the plastic cover down (it will kind of slide), maybe with the help of a screwdriver to release one of the sides
    3. Just find a video somewhere if you can't figure it out
  5. Now do a reset to the router, just to be sure that this works correctly. You can try the 30-30-30 method, but I don't know if this has any effect in the WNR. Just press the reset button, turn the router on, wait 30 seconds, turn it off while always pressing the button.
  6. Now you need to prepare the tftp client to upload the file downloaded from dd-wrt
    1. windows: open the tftp32, select tftp client, input the ip address 192.168.1.1 and browse for the file to be uploaded. Don't hit "send" just yet
    2. mac: open a terminal window and do the following commands:
      # cd Downloads (or whatever the file you downloaded is)
      # tftp 192.168.1.1
         binary
         put WNR3500L.chk
         (this is the filename that you downloaded, you can rename it to whatever you want, but don't hit ENTER just yet on this last command!)
  7. Connect a network cable to the router and turn it on, wait for all the lights to flash and when they turn off you have to short the 2 pins showned in the picture
     
  8. After you have shorted the pins, hit ENTER or "send" in the tftp client. You power led should be flashing green and the network port should have activity briefly. The tftp client should send the file in 2 seconds, but the router will take 2-3 minutes to flash it.
  9. Now the router should have a working firmware, you can reset to defaults, flash another firmware and do whatever you want again.

If the tftp client times out, just try again. Last night this only worked after I reseted the router. Also, you can start wireshark and see what the router is doing, in my case it was trying to fetch via tftp a vmlinuz file from 192.168.1.2 (normally the kernel file), but after the reset it accepted the tftp file and the router was debricked.

Posted long time ago, by Luís

Just a quick post, i've found my problem with the igmp packets. Turns out we need to have rp_filter set to off in order for multicast to work! 

The scripts are now fixed, and tomato now works 100% for Meo. DD-WRT also works 100% for Meo IPTV, you just need to have the right router.

I haven't given up on the D-Link Dir-825 yet...

Posted long time ago, by Hugo Costa

Google was first named BackRub, later they changed the name. They did well. :)

http://www.google.com/corporate/milestones.html

I find it also interesting the initial quick rise: in 1999 they went from eight (February) to forty employees (November). 

Posted long time ago, by Hugo Costa | about postgresql

Yesterday I was looking at how to do a correct order by in PostgreSQL, that is, taking into account special characters in our language - for instance Á should go with A not placed in the bottom.

After a quick googling the best I found was this tread follow-up:  http://archives.postgresql.org/pgsql-novice/2004-05/msg00044.php from Marc Bastin, were he writes about using translate() to replace the special chars in the column, and then do a order by with that. Better yet, since the translate string would become very large, to create a function, in other words, instead of:

SELECT name FROM clients ORDER BY name

Do something like this:

SELECT name, normalizar(name) as clean_name FROM clients ORDER BY clean_name

Well, i've build myself a little function to do just that:

CREATE OR REPLACE FUNCTION normalizar(palavra text)
  RETURNS text AS
$BODY$
DECLARE passed TEXT;
BEGIN
    passed := UPPER(palavra);

    passed := translate(passed, 'àáâäãÀÁÂÄÃa', 'AAAAAAAAA');
    passed := translate(passed, 'èéêëÈÉÊËe', 'EEEEEEEEE');
    passed := translate(passed, 'ìíïÌÍÏi', 'IIIIII');
    passed := translate(passed, 'òóôöÒÓÔÖo', 'OOOOOOOOO');
    passed := translate(passed, 'üu', 'UU');
    passed := translate(passed, 'çÇ', 'CC');

    RETURN passed;
END;
$BODY$
  LANGUAGE plpgsql IMMUTABLE;
ALTER FUNCTION normalizar(text) OWNER TO hpc;

this is my first try and obviously, calling for translate that many times just for sake of readability is wrong.

quick benchmark

using table "clients" with 6492 records:

  • standard order by: 32 ms
  • with the translate function: 360 - 380 ms

 

After a little optimization:

CREATE OR REPLACE FUNCTION normalizar(palavra text)
  RETURNS text AS
$BODY$
DECLARE
    passed TEXT;
    texto TEXT;
    rules TEXT;
BEGIN
    passed := UPPER(palavra);

    texto := 'àáâäãÀÁÂÄÃa' || 'èéêëÈÉÊËe' || 'ìíïÌÍÏi' || 'òóôöÒÓÔÖo' || 'üu' || 'çÇ';
    rules := 'AAAAAAAAA' || 'EEEEEEEEE' || 'IIIIII' || 'OOOOOOOOO' || 'UU' || 'CC';

    RETURN translate(passed, texto, rules);
END;
$BODY$
  LANGUAGE plpgsql IMMUTABLE;
ALTER FUNCTION normalizar(text) OWNER TO hpc;

about 280 - 300 ms

(taking out the string concat doesn't improve performace)

 

Now eliminating the need of variables, my final version:

CREATE OR REPLACE FUNCTION normalizar(palavra text)
  RETURNS text AS
$BODY$
BEGIN
    RETURN translate(UPPER(palavra), 'àáâäãÀÁÂÄÃaèéêëÈÉÊËeìíïÌÍÏiòóôöÒÓÔÖoüuçÇ', 'AAAAAAAAAEEEEEEEEEIIIIIIOOOOOOOOOUUCC');
END;
$BODY$
  LANGUAGE plpgsql IMMUTABLE;
ALTER FUNCTION normalizar(text) OWNER TO hpc;

about 250 ms

It is still a bit of a hog using this function, specially in bigger recordsets, but there are cases where doing a correct "human" order by, is imperative. Also, maybe with the use of indexes it could perform better. 

I've also read somewhere (in the same post?) that PostgreSQL should do a correct order by if the defined language set is correct, but that isn't working yet in unicode. Maybe in the future.