0

I'm developing a application using PHP 5.4, CakePHP 2.2.3. The problem is, in my local server (XAMPP) this error does not happen (PHP 5.4).

But in my server online, it does (PHP 5.3).

The error is that little weird character in the link:

enter image description here

Here: sgc/noticias/�avascript:void(0)

Most of the weird characters are data that are fetched through the database.

This does only happen when I use the link method of the HtmlHelper. Lets say, if I echo this:

echo $this->Html->link('Click me', '/pages/home', array('class' => 'button', 'target' => '_blank'));

I get this:

enter image description here

As you can see in the image: /sgc/index/�pages/home

If I echo this:

<a href="/sgc/index/pages/home" >Click me</a>

I get this: /sgc/index/pages/home

If I echo this:

echo $this->Html->link('Click me',array('controller'=>'pages', 'action' => 'view'), array('class' => 'button', 'target' => '_blank'));

I get this: /sgc/pages/view

I read something that this problem may be something like encoding problem, but I'm almost 100% sure all my files are encoding in UTF8 (without BOM).

Looks like this is the character: %EF%BB%BF.

Also, looking at the error log shows up this:

2012-11-21 15:37:05 Error: [MissingActionException] Action IndexController::�index() could not be found.

I don't think this problem could be related to the CakePHP version or some file in CakePHP lib, because I just uploaded a new CakePHP application without modifying anything (just a simple CakePHP app) and everything works fine in my online server.

The error must be in some of my files and not CakePHP.

Update

I followed this answer and have used the Total Commander to search for UTF BOM files in my project. But the results are, only images return in the search for "EF BB BF".

Community
  • 1
  • 1
Fuhrmann
  • 557
  • 13
  • 35

3 Answers3

2

"\xEF\xBB\xBF" is a UTF-8 byte-order mark, no question about it.

Since it's always at the beginning of the link argument, here are some possibilities off the top of my head:

  1. Whereever you have configured the base paths (e.g. /sgc/index, /sgc/noticias), you have a stray trailing BOM.
  2. The link() helper itself is encoding the supplied input to utf-8 (e.g., '/pages/home') and mistakenly including a BOM.

I would go straight to the HTML::link() code and trace through it, looking for calls to iconv or mb_* functions. Most likely those libraries are being used under the hood and are somehow incorrectly configured to emit a BOM as you would when writing a file.

Francis Avila
  • 31,233
  • 6
  • 58
  • 96
1

It does seem to be a problem with conflicting encodings. Check that in app/config/core.php you have the following, it should be there since it's the default:

Configure::write('App.encoding', 'UTF-8');

Then in your views specify the charset in the <head> like this:

<head>
    <?php echo $html->charset(); ?>
</head>

EDIT

The link() method does some processing on the URL it receives before generating the link:

$url = $this->url($url); // Line 335

The url() method then uses the Router::url() static method and the global h() function:

return h(Router::url($url, $full));

The Router::url() method doesn't seem to be doing anything related with encoding and the h() function just uses PHP's htmlspecialchars():

return htmlspecialchars($text, ENT_QUOTES, ($charset) ? $charset : $defaultCharset, $double);

I'm at a loss here, but maybe these trailing might help someone track down the cause for the character.

juan.facorro
  • 9,791
  • 2
  • 33
  • 41
  • Yes, in my `core.php` I have the App.enconding config and in my `default.ctp` layout also have the Html->charset(); ?>. It's very strange, because this is not a problem in PHP 5.4. – Fuhrmann Nov 21 '12 at 18:04
  • 1
    See if `mbstring.func_overload` php setting is enabled. Perhaps the `substr()` function invocation in `Router::url()` (which removes the leading `/` from your argument) is silently using `mb_substr()` – Francis Avila Nov 21 '12 at 18:54
  • 1
    @Fuhrmann What if you don't include the leading `/` in the URL supplied to the `link()` method? – juan.facorro Nov 21 '12 at 19:21
  • @juan.facorro Good idea, but I did this right now, and the BOM character just changed the position: /sgc/index/�ages/home – Fuhrmann Nov 21 '12 at 19:24
  • 1
    @Fuhrmann Could it be possible that the uploading to the server is changing the encoding of files? Have you tried downloading the file from the server and comparing it with the original (using a text editor that lets you view file in HEX)? – juan.facorro Nov 21 '12 at 19:51
  • @juan.facorro I just found what was the problem. I'll post the answer in a few minutes. Big thanks to you and the other guys. – Fuhrmann Nov 21 '12 at 20:03
0

I just found the problem! A really big thanks to you guys that helped me out thinking.

To go to the point, the code that was giving me those weird character is this:

public function url($url = null, $full = false) {

    if(!isset($url['plugin'])) {
        $url['plugin'] = null;
    }

    return parent::url($url, $full);
}

It was inside the class AppHelper. But why?

My application is divided into modules, which means that a module = plugin. I have many plugins inside my application. Sometimes when I was inside a plugin page (like News, or Blog), and I want to link to a controller that is part of the application and not part of the plugin, I always have to set plugin => "" so CakePHP would know that I want a controller that was is not part of the plugin;

Example: when I use the HtmlHelper::link or even the HtmlHelper::url:

echo $this->Html->link('All users', array('plugin' => '', 'controller' => 'users', 'action' => 'index'));

This would echo the right link, that will point to the Users controller and index action.

But, if I use this (without setting plugin => ""):

echo $this->Html->link('All users', array('controller' => 'users', 'action' => 'index'));

It was pointing me to a Users controller inside my plugin.

I did not wanted to declare it every time (plugin => "") so inside the AppHelper::url I simple put this routine: If there is no plugin => "" in the $url set plugin to null.

But this was causing me this weird characters in all URLS that was constructed using HtmlHelper::url or HtmlHelper::link.

I've changed this function to this now:

public function url($url = null, $full = false) {

    if (is_array($url)) {
        if(!isset($url['plugin'])) {
            $url['plugin'] = "";
        }    
    }
    return parent::url($url, $full);
}

And all working fine.

Fuhrmann
  • 557
  • 13
  • 35