/var/www/html_nl/wp-content/plugins/loco-translate/src/ajax/DownloadController.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<?php
/**
 * Ajax "download" route, for outputting raw gettext file contents.
 */
class Loco_ajax_DownloadController extends Loco_ajax_common_BundleController {


    
/**
     * @return string
     */
    
private function renderArchive$path ){

        
$zipfile = new Loco_fs_File($path);
        
$pofile = new Loco_fs_DummyFile'/fake/'.$zipfile->filename().'.po');

        
// Resolving script refs requires configured project
        
$bundle $this->getBundle();
        
$project $this->getProject($bundle);
        
        
// Create a temporary file for zip, which must work on disk, not in memory
        
$path wp_tempnam();
        if( ! 
$path || ! file_exists($path) ){
            throw new 
Loco_error_Exception('Failed to create temporary file for zip archive');
        }
        
register_shutdown_function('unlink',$path);
        
        
// initialize zip
        // TODO PHP 8.4 Using empty file as ZipArchive is deprecated
        
loco_check_extension('zip');
        
$z = new ZipArchive;
        
$z->open$pathZipArchive::CREATE);
        
$z->setArchiveComment$bundle->getName() );
        
        
$post Loco_mvc_PostParams::get();
        
$data Loco_gettext_Data::fromSource($post->source);
        
$compiler = new Loco_gettext_Compiler($pofile);
        
        
/* @var Loco_fs_DummyFile $file */
        
foreach( $compiler->writeAll($data,$project) as $file ){
            
$z->addFromString$file->basename(), $file->getContents() );
        }
        
$z->close();
        
        return 
file_get_contents($path);
    }


    
/**
     * {@inheritdoc}
     */
    
public function render(){
        
$post $this->validate();
        
$path $this->get('path');

        
// The UI now replaces .mo with .zip, but requires the ZipArchive extension is installed.
        
if( '.zip' === substr($path,-4) ){
            return 
$this->renderArchive($path);
        }

        
// Below is for direct .po/pot downloads, plus legacy .mo/l10n.php
        // mo is only used when zip is not available. php works but not hooked into UI.
        
$file = new Loco_fs_File($path);
        
$file->normalizeloco_constant('WP_CONTENT_DIR') );
        
$ext Loco_gettext_Data::ext($file);

        
// posted source must be clean and must parse as whatever the file extension claims to be
        
$raw $post->source;
        if( 
is_string($raw) && '' !== $raw ){
            
// compile source if target is MO
            
if( 'mo' === $ext ) {
                
$raw Loco_gettext_Data::fromSource($raw)->msgfmt();
            }
            
// supporting .l10n.php for WordPress >= 6.5
            
else if( 'php' === $ext && class_exists('WP_Translation_File_PHP',false) ){
                
$raw Loco_gettext_PhpCache::renderLoco_gettext_Data::fromSource($raw) );
            }
        }
        
// else file can be output directly if it exists.
        // note that files on disk will not be parsed or manipulated. they will download strictly as-is
        
else if( $file->exists() ){
            
$raw $file->getContents();
        }
        
// else we can't do anything except bail
        
else {
            throw new 
Loco_error_Exception('File not found and no source posted');
        }

        
// Observe UTF-8 BOM setting for PO and POT only
        
if( 'po' === $ext || 'pot' === $ext ){
            
$has_bom "\xEF\xBB\xBF" === substr($raw,0,3);
            
$use_bom = (bool) Loco_data_Settings::get()->po_utf8_bom;
            
// only alter file if valid UTF-8. Deferring detection overhead until required 
            
if( $has_bom !== $use_bom && preg_match('//u',$raw) ){
                if( 
$use_bom ){
                    
$raw "\xEF\xBB\xBF".$raw// prepend
                
}
                else {
                    
$raw substr($raw,3); // strip bom
                
}
            }
        }

        return 
$raw;
    }

}