T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/lavocat.quebec/private_html/scripts/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.quebec/private_html/scripts/find-hardcoded-language-links.js
#!/usr/bin/env node

const fs = require('fs');
const path = require('path');
const glob = require('glob');

// Patterns to search for hard-coded language navigation
const patterns = [
  // Hard-coded language switcher links
  {
    pattern: /<Link[^>]*href=["']\/en["'][^>]*>.*?EN.*?<\/Link>/gs,
    description: 'Hard-coded EN link to /en'
  },
  {
    pattern: /<Link[^>]*href=["']\/["'][^>]*>.*?FR.*?<\/Link>/gs,
    description: 'Hard-coded FR link to /'
  },
  {
    pattern: /<Link[^>]*href=["']\/en\/[^"']*["'][^>]*>.*?<\/Link>/gs,
    description: 'Hard-coded English page links'
  },
  {
    pattern: /<Link[^>]*href=["']\/(?!en\/)[^"']*["'][^>]*>.*?<\/Link>/gs,
    description: 'Hard-coded French page links (excluding /en/ paths)'
  },
  // Language switcher patterns
  {
    pattern: /onClick.*?router\.push.*?\/en/gs,
    description: 'Router push to /en in onClick handlers'
  },
  {
    pattern: /onClick.*?router\.push.*?\/fr/gs,
    description: 'Router push to /fr in onClick handlers'
  },
  // State-based patterns (these are good, we want to find pages that DON'T have these)
  {
    pattern: /const \[language, setLanguage\] = useState/gs,
    description: 'Language state management (GOOD)',
    isGood: true
  },
  {
    pattern: /handleLanguageToggle.*?setLanguage/gs,
    description: 'Language toggle handler (GOOD)',
    isGood: true
  }
];

// Files to scan
const scanPaths = [
  'src/pages/**/*.tsx',
  'src/pages/**/*.jsx',
  'src/components/**/*.tsx',
  'src/components/**/*.jsx'
];

// Files to exclude
const excludePatterns = [
  '**/node_modules/**',
  '**/.next/**',
  '**/deployment/**',
  '**/*.d.ts',
  '**/test-results/**'
];

function scanFile(filePath) {
  try {
    const content = fs.readFileSync(filePath, 'utf8');
    const issues = [];
    const hasGoodPatterns = [];

    patterns.forEach(({ pattern, description, isGood }) => {
      const matches = content.match(pattern);
      if (matches) {
        if (isGood) {
          hasGoodPatterns.push(description);
        } else {
          issues.push({
            description,
            matches: matches.length,
            examples: matches.slice(0, 2) // Show first 2 examples
          });
        }
      }
    });

    return {
      filePath,
      issues,
      hasGoodPatterns,
      needsConversion: issues.length > 0 && hasGoodPatterns.length === 0
    };
  } catch (error) {
    return {
      filePath,
      error: error.message
    };
  }
}

function main() {
  console.log('šŸ” Scanning for hard-coded language navigation links...\n');

  const allFiles = [];
  scanPaths.forEach(pattern => {
    const files = glob.sync(pattern, { ignore: excludePatterns });
    allFiles.push(...files);
  });

  console.log(`šŸ“ Found ${allFiles.length} files to scan\n`);

  const results = allFiles.map(scanFile);
  
  // Filter results
  const filesWithIssues = results.filter(r => r.issues && r.issues.length > 0);
  const filesNeedingConversion = results.filter(r => r.needsConversion);
  const filesWithGoodPatterns = results.filter(r => r.hasGoodPatterns && r.hasGoodPatterns.length > 0);

  // Display results
  console.log('šŸ“Š SCAN RESULTS:\n');

  console.log(`āœ… Files with good state-based patterns: ${filesWithGoodPatterns.length}`);
  filesWithGoodPatterns.forEach(file => {
    console.log(`   - ${file.filePath}`);
    file.hasGoodPatterns.forEach(pattern => {
      console.log(`     āœ“ ${pattern}`);
    });
  });

  console.log(`\nāš ļø  Files with hard-coded language issues: ${filesWithIssues.length}`);
  filesWithIssues.forEach(file => {
    console.log(`\nšŸ“„ ${file.filePath}`);
    file.issues.forEach(issue => {
      console.log(`   āŒ ${issue.description} (${issue.matches} instances)`);
      if (issue.examples) {
        issue.examples.forEach((example, i) => {
          const truncated = example.length > 100 ? example.substring(0, 100) + '...' : example;
          console.log(`      Example ${i + 1}: ${truncated.replace(/\s+/g, ' ')}`);
        });
      }
    });
  });

  console.log(`\n🚨 Files needing conversion to state-based switching: ${filesNeedingConversion.length}`);
  filesNeedingConversion.forEach(file => {
    console.log(`   šŸ”§ ${file.filePath}`);
  });

  // Summary
  console.log('\nšŸ“‹ SUMMARY:');
  console.log(`   - Total files scanned: ${allFiles.length}`);
  console.log(`   - Files with good patterns: ${filesWithGoodPatterns.length}`);
  console.log(`   - Files with issues: ${filesWithIssues.length}`);
  console.log(`   - Files needing conversion: ${filesNeedingConversion.length}`);

  if (filesNeedingConversion.length > 0) {
    console.log('\nšŸŽÆ RECOMMENDATIONS:');
    console.log('   1. Convert hard-coded <Link> components to state-based buttons');
    console.log('   2. Add language state management (useState)');
    console.log('   3. Add handleLanguageToggle function');
    console.log('   4. Make content dynamic using language state');
    console.log('\nšŸ’” Example conversion:');
    console.log('   āŒ <Link href="/en">EN</Link>');
    console.log('   āœ… <button onClick={handleLanguageToggle}>{language === "fr" ? "EN" : "FR"}</button>');
  }

  // Save detailed report
  const report = {
    timestamp: new Date().toISOString(),
    summary: {
      totalFiles: allFiles.length,
      filesWithGoodPatterns: filesWithGoodPatterns.length,
      filesWithIssues: filesWithIssues.length,
      filesNeedingConversion: filesNeedingConversion.length
    },
    filesNeedingConversion: filesNeedingConversion.map(f => f.filePath),
    filesWithIssues: filesWithIssues.map(f => ({
      filePath: f.filePath,
      issues: f.issues
    }))
  };

  fs.writeFileSync('language-scan-report.json', JSON.stringify(report, null, 2));
  console.log('\nšŸ“„ Detailed report saved to: language-scan-report.json');
}

if (require.main === module) {
  main();
}

module.exports = { scanFile, patterns }; 

CasperSecurity Mini