Changeset 12174
- Timestamp:
- 11/12/2009 04:05:43 PM (15 years ago)
- Location:
- trunk/wp-includes/pomo
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/wp-includes/pomo/mo.php
r12079 r12174 3 3 * Class for working with MO files 4 4 * 5 * @version $Id: mo.php 2 21 2009-09-07 21:08:21Z nbachiyski $5 * @version $Id: mo.php 293 2009-11-12 15:43:50Z nbachiyski $ 6 6 * @package pomo 7 7 * @subpackage mo … … 22 22 */ 23 23 function import_from_file($filename) { 24 $reader = new POMO_CachedIntFileReader($filename); 25 if (isset($reader->error)) { 26 return false; 27 } 24 $reader = new POMO_FileReader($filename); 25 if (!$reader->is_resource()) 26 return false; 28 27 return $this->import_from_reader($reader); 29 28 } … … 114 113 115 114 function import_from_reader($reader) { 116 $reader->setEndian('little'); 117 $endian = MO::get_byteorder($reader->readint32()); 118 if (false === $endian) { 119 return false; 120 } 121 $reader->setEndian($endian); 122 123 $revision = $reader->readint32(); 124 $total = $reader->readint32(); 125 // get addresses of array of lenghts and offsets for original string and translations 126 $originals_lenghts_addr = $reader->readint32(); 127 $translations_lenghts_addr = $reader->readint32(); 128 115 $endian_string = MO::get_byteorder($reader->readint32()); 116 if (false === $endian_string) { 117 return false; 118 } 119 $reader->setEndian($endian_string); 120 121 $endian = ('big' == $endian_string)? 'N' : 'V'; 122 123 $header = $reader->read(24); 124 if ($reader->strlen($header) != 24) 125 return false; 126 127 // parse header 128 $header = unpack("{$endian}revision/{$endian}total/{$endian}originals_lenghts_addr/{$endian}translations_lenghts_addr/{$endian}hash_length/{$endian}hash_addr", $header); 129 if (!is_array($header)) 130 return false; 131 132 extract( $header ); 133 134 // support revision 0 of MO format specs, only 135 if ($revision != 0) 136 return false; 137 138 // seek to data blocks 129 139 $reader->seekto($originals_lenghts_addr); 130 $originals_lenghts = $reader->readint32array($total * 2); // each of 131 $reader->seekto($translations_lenghts_addr); 132 $translations_lenghts = $reader->readint32array($total * 2); 133 134 $length = create_function('$i', 'return $i * 2 + 1;'); 135 $offset = create_function('$i', 'return $i * 2 + 2;'); 136 137 for ($i = 0; $i < $total; ++$i) { 138 $reader->seekto($originals_lenghts[$offset($i)]); 139 $original = $reader->read($originals_lenghts[$length($i)]); 140 $reader->seekto($translations_lenghts[$offset($i)]); 141 $translation = $reader->read($translations_lenghts[$length($i)]); 142 if ('' == $original) { 140 141 // read originals' indices 142 $originals_lengths_length = $translations_lenghts_addr - $originals_lenghts_addr; 143 if ( $originals_lengths_length != $total * 8 ) 144 return false; 145 146 $originals = $reader->read($originals_lengths_length); 147 if ( $reader->strlen( $originals ) != $originals_lengths_length ) 148 return false; 149 150 // read translations' indices 151 $translations_lenghts_length = $hash_addr - $translations_lenghts_addr; 152 if ( $translations_lenghts_length != $total * 8 ) 153 return false; 154 155 $translations = $reader->read($translations_lenghts_length); 156 if ( $reader->strlen( $translations ) != $translations_lenghts_length ) 157 return false; 158 159 // transform raw data into set of indices 160 $originals = $reader->str_split( $originals, 8 ); 161 $translations = $reader->str_split( $translations, 8 ); 162 163 // skip hash table 164 $strings_addr = $hash_addr + $hash_length * 4; 165 166 $reader->seekto($strings_addr); 167 168 $strings = $reader->read_all(); 169 $reader->close(); 170 171 for ( $i = 0; $i < $total; $i++ ) { 172 $o = unpack( "{$endian}length/{$endian}pos", $originals[$i] ); 173 $t = unpack( "{$endian}length/{$endian}pos", $translations[$i] ); 174 if ( !$o || !$t ) return false; 175 176 // adjust offset due to reading strings to separate space before 177 $o['pos'] -= $strings_addr; 178 $t['pos'] -= $strings_addr; 179 180 $original = $reader->substr( $strings, $o['pos'], $o['length'] ); 181 $translation = $reader->substr( $strings, $t['pos'], $t['length'] ); 182 183 if ('' === $original) { 143 184 $this->set_headers($this->make_headers($translation)); 144 185 } else { 145 $this->add_entry($this->make_entry($original, $translation)); 186 $entry = &$this->make_entry($original, $translation); 187 $this->entries[$entry->key()] = &$entry; 146 188 } 147 189 } … … 150 192 151 193 /** 194 * Build a Translation_Entry from original string and translation strings, 195 * found in a MO file 196 * 152 197 * @static 198 * @param string $original original string to translate from MO file. Might contain 199 * 0x04 as context separator or 0x00 as singular/plural separator 200 * @param string $translation translation string from MO file. Might contain 201 * 0x00 as a plural translations separator 153 202 */ 154 203 function &make_entry($original, $translation) { 155 $ args = array();204 $entry = & new Translation_Entry(); 156 205 // look for context 157 206 $parts = explode(chr(4), $original); 158 207 if (isset($parts[1])) { 159 208 $original = $parts[1]; 160 $ args['context']= $parts[0];209 $entry->context = $parts[0]; 161 210 } 162 211 // look for plural original 163 212 $parts = explode(chr(0), $original); 164 $ args['singular']= $parts[0];213 $entry->singular = $parts[0]; 165 214 if (isset($parts[1])) { 166 $args['plural'] = $parts[1]; 215 $entry->is_plural = true; 216 $entry->plural = $parts[1]; 167 217 } 168 218 // plural translations are also separated by \0 169 $args['translations'] = explode(chr(0), $translation); 170 $entry = & new Translation_Entry($args); 219 $entry->translations = explode(chr(0), $translation); 171 220 return $entry; 172 221 } … … 179 228 return $this->_nplurals; 180 229 } 181 182 183 230 } 184 231 endif; -
trunk/wp-includes/pomo/streams.php
r12079 r12174 4 4 * Based on the classes from Danilo Segan <danilo@kvota.net> 5 5 * 6 * @version $Id: streams.php 2 23 2009-09-07 21:20:13Z nbachiyski $6 * @version $Id: streams.php 293 2009-11-12 15:43:50Z nbachiyski $ 7 7 * @package pomo 8 8 * @subpackage streams 9 9 */ 10 10 11 12 if ( !class_exists( 'POMO_StringReader' ) ): 13 /** 14 * Provides file-like methods for manipulating a string instead 15 * of a physical file. 16 */ 17 class POMO_StringReader { 18 var $_pos; 19 var $_str; 20 21 function POMO_StringReader($str = '') { 22 $this->_str = $str; 11 if ( !class_exists( 'POMO_Reader' ) ): 12 class POMO_Reader { 13 14 var $endian = 'little'; 15 var $_post = ''; 16 17 function POMO_Reader() { 18 $this->is_overloaded = ((ini_get("mbstring.func_overload") & 2) != 0) && function_exists('mb_substr'); 23 19 $this->_pos = 0; 24 $this->is_overloaded = ((ini_get("mbstring.func_overload") & 2) != 0) && function_exists('mb_substr'); 25 } 26 27 function _substr($string, $start, $length) { 28 if ($this->is_overloaded) { 29 return mb_substr($string,$start,$length,'ascii'); 30 } else { 31 return substr($string,$start,$length); 32 } 33 } 34 35 function _strlen($string) { 36 if ($this->is_overloaded) { 37 return mb_strlen($string,'ascii'); 38 } else { 39 return strlen($string); 40 } 41 } 42 43 function read($bytes) { 44 $data = $this->_substr($this->_str, $this->_pos, $bytes); 45 $this->_pos += $bytes; 46 if ($this->_strlen($this->_str) < $this->_pos) $this->_pos = $this->_strlen($this->_str); 47 return $data; 48 } 49 50 function seekto($pos) { 51 $this->_pos = $pos; 52 if ($this->_strlen($this->_str) < $this->_pos) $this->_pos = $this->_strlen($this->_str); 53 return $this->_pos; 54 } 55 56 function pos() { 57 return $this->_pos; 58 } 59 60 function length() { 61 return $this->_strlen($this->_str); 62 } 63 64 } 65 endif; 66 67 if ( !class_exists( 'POMO_CachedFileReader' ) ): 68 /** 69 * Reads the contents of the file in the beginning. 70 */ 71 class POMO_CachedFileReader extends POMO_StringReader { 72 function POMO_CachedFileReader($filename) { 73 parent::POMO_StringReader(); 74 $this->_str = file_get_contents($filename); 75 if (false === $this->_str) 76 return false; 77 $this->_pos = 0; 78 } 79 } 80 endif; 81 82 if ( !class_exists( 'POMO_CachedIntFileReader' ) ): 83 /** 84 * Allows reading integers from a file. 85 */ 86 class POMO_CachedIntFileReader extends POMO_CachedFileReader { 87 88 var $endian = 'little'; 89 90 /** 91 * Opens a file and caches it. 92 * 93 * @param $filename string name of the file to be opened 94 * @param $endian string endianness of the words in the file, allowed 95 * values are 'little' or 'big'. Default value is 'little' 96 */ 97 function POMO_CachedIntFileReader($filename, $endian = 'little') { 98 $this->endian = $endian; 99 parent::POMO_CachedFileReader($filename); 100 } 101 20 } 21 102 22 /** 103 23 * Sets the endianness of the file. … … 117 37 function readint32() { 118 38 $bytes = $this->read(4); 119 if (4 != $this-> _strlen($bytes))39 if (4 != $this->strlen($bytes)) 120 40 return false; 121 41 $endian_letter = ('big' == $this->endian)? 'N' : 'V'; … … 133 53 function readint32array($count) { 134 54 $bytes = $this->read(4 * $count); 135 if (4*$count != $this-> _strlen($bytes))55 if (4*$count != $this->strlen($bytes)) 136 56 return false; 137 57 $endian_letter = ('big' == $this->endian)? 'N' : 'V'; 138 58 return unpack($endian_letter.$count, $bytes); 139 59 } 140 } 141 endif; 60 61 62 function substr($string, $start, $length) { 63 if ($this->is_overloaded) { 64 return mb_substr($string, $start, $length, 'ascii'); 65 } else { 66 return substr($string, $start, $length); 67 } 68 } 69 70 function strlen($string) { 71 if ($this->is_overloaded) { 72 return mb_strlen($string, 'ascii'); 73 } else { 74 return strlen($string); 75 } 76 } 77 78 function str_split($string, $chunk_size) { 79 if (!function_exists('str_split')) { 80 $length = $this->strlen($string); 81 $out = array(); 82 for ($i = 0; $i < $length; $i += $chunk_size) 83 $out[] = $this->substr($string, $i, $chunk_size); 84 return $out; 85 } else { 86 return str_split( $string, $chunk_size ); 87 } 88 } 89 90 91 function pos() { 92 return $this->_pos; 93 } 94 95 function is_resource() { 96 return true; 97 } 98 99 function close() { 100 return true; 101 } 102 } 103 endif; 104 105 if ( !class_exists( 'POMO_FileReader' ) ): 106 class POMO_FileReader extends POMO_Reader { 107 function POMO_FileReader($filename) { 108 parent::POMO_Reader(); 109 $this->_f = fopen($filename, 'r'); 110 } 111 112 function read($bytes) { 113 return fread($this->_f, $bytes); 114 } 115 116 function seekto($pos) { 117 if ( -1 == fseek($this->_f, $pos, SEEK_SET)) { 118 return false; 119 } 120 $this->_pos = $pos; 121 return true; 122 } 123 124 function is_resource() { 125 return is_resource($this->_f); 126 } 127 128 function feof() { 129 return feof($this->_f); 130 } 131 132 function close() { 133 return fclose($this->_f); 134 } 135 136 function read_all() { 137 $all = ''; 138 while ( !$this->feof() ) 139 $all .= $this->read(4096); 140 return $all; 141 } 142 } 143 endif; 144 145 if ( !class_exists( 'POMO_StringReader' ) ): 146 /** 147 * Provides file-like methods for manipulating a string instead 148 * of a physical file. 149 */ 150 class POMO_StringReader extends POMO_Reader { 151 152 var $_str = ''; 153 154 function POMO_StringReader($str = '') { 155 parent::POMO_Reader(); 156 $this->_str = $str; 157 $this->_pos = 0; 158 } 159 160 161 function read($bytes) { 162 $data = $this->substr($this->_str, $this->_pos, $bytes); 163 $this->_pos += $bytes; 164 if ($this->strlen($this->_str) < $this->_pos) $this->_pos = $this->strlen($this->_str); 165 return $data; 166 } 167 168 function seekto($pos) { 169 $this->_pos = $pos; 170 if ($this->strlen($this->_str) < $this->_pos) $this->_pos = $this->strlen($this->_str); 171 return $this->_pos; 172 } 173 174 function length() { 175 return $this->strlen($this->_str); 176 } 177 178 function read_all() { 179 return $this->substr($this->_str, $this->_pos, $this->strlen($this->_str)); 180 } 181 182 } 183 endif; 184 185 if ( !class_exists( 'POMO_CachedFileReader' ) ): 186 /** 187 * Reads the contents of the file in the beginning. 188 */ 189 class POMO_CachedFileReader extends POMO_StringReader { 190 function POMO_CachedFileReader($filename) { 191 parent::POMO_StringReader(); 192 $this->_str = file_get_contents($filename); 193 if (false === $this->_str) 194 return false; 195 $this->_pos = 0; 196 } 197 } 198 endif; 199 200 if ( !class_exists( 'POMO_CachedIntFileReader' ) ): 201 /** 202 * Reads the contents of the file in the beginning. 203 */ 204 class POMO_CachedIntFileReader extends POMO_CachedFileReader { 205 function POMO_CachedIntFileReader($filename) { 206 parent::POMO_CachedFileReader($filename); 207 } 208 } 209 endif;
Note: See TracChangeset
for help on using the changeset viewer.