This is a specific issue for multilingual websites. If you have just upgraded and do not have a multilingual site please see #1442080: "permission restrictions" in reports -> run re-analyze only task once after upgrade

In a multilingual site using i18n module the db_rewrite_sql() function causes language negotiation to be added to the query. This means a large percentage of broken links cannot be fixed (or are difficult to fix) because they are obscured by the "Permission restrictions deny you access to this broken link" text which makes it impossible to see where the link is, why permission is denied, or which language it is in. Since you do not need to speak the language to fix a URL I don't think this is desired functionality. linkchecker v2.4 showed all broken links in all languages so for me this is a feature regression.

I tracked this down to linkchecker.module -> _linkchecker_link_node_ids() -> two db_rewrite_sql() calls.

My temp fix is to trick i18n into thinking the sql already has language negotiation by adding "i18n" text to the sql that does not interfere with the query.

<?php
function _linkchecker_link_node_ids($link, $node_author_account = NULL) {
  static
$fields_with_node_links = array();
 
// If the user cannot access content, there is no need to check further.
 
if (!user_access('access content')) {
    return array();
  }
 
// Trick i18n module so that it does not add language negotiation sql
 
$dummy = '';
  if (
module_exists('i18n')) {
   
$dummy = 'n.nid <> "i18n" AND ';
  }
 
// Get a list of nodes containing the link, using db_rewrite_sql() to allow
  // node access modules to exclude nodes that the current user does not have
  // access to view.
 
if (!empty($node_author_account)) {
   
$nodes = db_query(db_rewrite_sql('SELECT n.nid
      FROM {node} n
      INNER JOIN {linkchecker_nodes} ln ON ln.nid = n.nid
      INNER JOIN {node_revisions} r ON r.vid = n.vid
      WHERE '
. $dummy . 'ln.lid = %d AND (n.uid = %d OR r.uid = %d)'), $link->lid, $node_author_account->uid, $node_author_account->uid);
  }
  else {
   
$nodes = db_query(db_rewrite_sql('SELECT n.nid
      FROM {node} n
      INNER JOIN {linkchecker_nodes} ln ON ln.nid = n.nid
      WHERE '
. $dummy . 'ln.lid = %d'), $link->lid);
  }
// ...
?>

Alternatively passing array('view' => NULL) as the $arg for db_rewrite_sql() will also stop i18n but I don't know the full ramification of using that.

<?php
$nodes
= db_query(db_rewrite_sql('SELECT n.nid
      FROM {node} n
      INNER JOIN {linkchecker_nodes} ln ON ln.nid = n.nid
      WHERE '
. $dummy . 'ln.lid = %d', 'n', 'nid', array('view' => NULL)), $link->lid);
?>

If one of these is acceptable I would gladly roll a patch. In my case this is a critical issue since the site has 5 languages. The rest of the "Permission restrictions" problems seem to be caused by unpublished content which probably should not be link checked?

Files: 
CommentFileSizeAuthor
#23 1488572-23-linkchecker-i18n-d6.patch928 bytescaktux
PASSED: [[SimpleTest]]: [MySQL] 105 pass(es).
[ View ]
#17 1488572_linkchecker_i18n_D6b.patch1.08 KBhass
PASSED: [[SimpleTest]]: [MySQL] 97 pass(es).
[ View ]
#14 1488572_linkchecker_i18n_D6.patch1.14 KBhass
FAILED: [[SimpleTest]]: [MySQL] Invalid patch format in 1488572_linkchecker_i18n_D6_0.patch.
[ View ]
#10 1488572_linkchecker_i18n_D6.patch1.14 KBhass
FAILED: [[SimpleTest]]: [MySQL] Invalid patch format in 1488572_linkchecker_i18n_D6.patch.
[ View ]

Comments

Please make sure you run a Re-analyze after upgrading to 2.5. Does this solve the problem?

Is there no better way from stopping i18n modue from extending the query?

Re-analyze is not the solution. Did that multiple times on two sites to no avail. I debugged the problem and its the sql. i18n injects language = english criteria where as the nodes that have the links are in other languages. Language is not a valid criteria here. There are a number of checks in i18n_db_rewrite_sql to stop language injection but I think I chose the most suitable. The checks are:

<?php
// i18n.module
function i18n_db_rewrite_sql($query, $primary_table, $primary_key, $args = array()) {
 
// If mode is 'off' = no rewrite, we cannot return any empty 'where' string so check here.
 
$mode = i18n_selection_mode();
  if (
$mode == 'off') return;
 
// Disable language conditions for views.
 
if (array_key_exists('view', $args)) return;
  switch (
$primary_table) {
    case
'n':
    case
'node':
     
// No rewrite for queries with subselect ? (views count queries).
      // @ TO DO Actually these queries look un-rewrittable, check with other developers.
     
if (preg_match("/FROM \(SELECT/", $query)) return;
     
// No rewrite for translation module queries.
     
if (preg_match("/.*FROM {node} $primary_table WHERE.*$primary_table\.tnid/", $query)) return;
     
// When loading specific nodes, language conditions shouldn't apply.
     
if (preg_match("/WHERE.*\s$primary_table.nid\s*=\s*(\d|%d)/", $query)) return;
     
// If language conditions already there, get out.
     
if (preg_match("/i18n/", $query)) return;
?>

My first method will not interfer with queries because NID will never equal "i18n" so I think it is the safest. The second method is cleaner PHP and SQL as there is no SQL addition but I could not find usage of $args array ('view' =>) in any modules outside of i18n so I don't know how it could interfere. Everything else involves larger changes to SQL.

I have only tested on MySQL.

Priority:Major» Critical
Status:Needs review» Needs work

You should never compare a string value with an integer. This adds serious database load as it tries to convert the i18n to integer what could theroretically end with 18... And match on node 18, but i'm not sure about sql... This will at least happen in php. The arg views solution sounds ok, if this is clean - or we add "i18n == i18n" to be clean with datatypes. Like views do it for debugging...

CNW as there is no clean patch.

Title:"Permission restrictions deny" all broken links in other languagesI18n: "Permission restrictions deny" all broken links in other languages

Title:I18n: "Permission restrictions deny" all broken links in other languagesi18n: "Permission restrictions deny" all broken links in other languages

I am getting the same "permission restrictions deny" error and I don't have i18 installed. Using Linkchechecker 6.x-2.5.

Status:Needs work» Needs review
StatusFileSize
new1.14 KB
FAILED: [[SimpleTest]]: [MySQL] Invalid patch format in 1488572_linkchecker_i18n_D6.patch.
[ View ]

Here is a proper patch for D6. I'm myself not really sure if we need to set it to 'off' or one of the many other possible values. Please test this patch.

off = No language conditions inserted.
simple = Only current language and no language.
mixed = Only current and default languages.
strict = Only current language.
default = Only default language.
user = User defined, in the module's settings page.
params = Gets the stored params.
reset = Returns to previous.
custom = add custom where clause, like "%alias.language = 'en'".

What type of language detection are you using? Path based or domain based or any other? Aside, what about comments, blocks?

The last submitted patch, 1488572_linkchecker_i18n_D6.patch, failed testing.

Status:Needs work» Needs review

#10: 1488572_linkchecker_i18n_D6.patch queued for re-testing.

Status:Needs review» Needs work

The last submitted patch, 1488572_linkchecker_i18n_D6.patch, failed testing.

Status:Needs review» Needs work
StatusFileSize
new1.14 KB
FAILED: [[SimpleTest]]: [MySQL] Invalid patch format in 1488572_linkchecker_i18n_D6_0.patch.
[ View ]

Patch has no unix lf's. suxxx testbot.

Status:Needs work» Needs review

Status:Needs review» Needs work

The last submitted patch, 1488572_linkchecker_i18n_D6.patch, failed testing.

Status:Needs review» Needs work
StatusFileSize
new1.08 KB
PASSED: [[SimpleTest]]: [MySQL] 97 pass(es).
[ View ]

suxxx, same patch again

Status:Needs work» Needs review

Status:Needs work» Needs review

@tinker: have you been able to test this patch?

Status:Needs review» Fixed

Status:Fixed» Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

Version:6.x-2.5» 6.x-2.x-dev
Priority:Critical» Major
Status:Closed (fixed)» Needs review
StatusFileSize
new928 bytes
PASSED: [[SimpleTest]]: [MySQL] 105 pass(es).
[ View ]

tinker's solution was right and the patch in #17 didn't work for me but might also be necessary, didn't check without it since it's already committed. I went with the array('view' => NULL) trick since it felt cleaner, although I'm also unsure of what it's actually doing. We're only changing the query in our module so it shouldn't affect anything else.

Just realized I applied his solution to _linkchecker_link_comment_ids instead of _linkchecker_link_node_ids, but that was actually the problem. Sweet.

Issue summary:View changes

Add link to other issue that will help most people.