| 331 | |
| 332 | |
| 333 | class GNUTranslations(NullTranslations): |
| 334 | # Magic number of .mo files |
| 335 | LE_MAGIC = 0x950412de |
| 336 | BE_MAGIC = 0xde120495 |
| 337 | |
| 338 | # The encoding of a msgctxt and a msgid in a .mo file is |
| 339 | # msgctxt + "\x04" + msgid (gettext version >= 0.15) |
| 340 | CONTEXT = "%s\x04%s" |
| 341 | |
| 342 | # Acceptable .mo versions |
| 343 | VERSIONS = (0, 1) |
| 344 | |
| 345 | def _get_versions(self, version): |
| 346 | """Returns a tuple of major version, minor version""" |
| 347 | return (version >> 16, version & 0xffff) |
| 348 | |
| 349 | def _parse(self, fp): |
| 350 | """Override this method to support alternative .mo formats.""" |
| 351 | # Delay struct import for speeding up gettext import when .mo files |
| 352 | # are not used. |
| 353 | from struct import unpack |
| 354 | filename = getattr(fp, 'name', '') |
| 355 | # Parse the .mo file header, which consists of 5 little endian 32 |
| 356 | # bit words. |
| 357 | self._catalog = catalog = {} |
| 358 | self.plural = lambda n: int(n != 1) # germanic plural by default |
| 359 | buf = fp.read() |
| 360 | buflen = len(buf) |
| 361 | # Are we big endian or little endian? |
| 362 | magic = unpack('<I', buf[:4])[0] |
| 363 | if magic == self.LE_MAGIC: |
| 364 | version, msgcount, masteridx, transidx = unpack('<4I', buf[4:20]) |
| 365 | ii = '<II' |
| 366 | elif magic == self.BE_MAGIC: |
| 367 | version, msgcount, masteridx, transidx = unpack('>4I', buf[4:20]) |
| 368 | ii = '>II' |
| 369 | else: |
| 370 | raise OSError(0, 'Bad magic number', filename) |
| 371 | |
| 372 | major_version, minor_version = self._get_versions(version) |
| 373 | |
| 374 | if major_version not in self.VERSIONS: |
| 375 | raise OSError(0, 'Bad version number ' + str(major_version), filename) |
| 376 | |
| 377 | # Now put all messages from the .mo file buffer into the catalog |
| 378 | # dictionary. |
| 379 | for i in range(0, msgcount): |
| 380 | mlen, moff = unpack(ii, buf[masteridx:masteridx+8]) |
| 381 | mend = moff + mlen |
| 382 | tlen, toff = unpack(ii, buf[transidx:transidx+8]) |
| 383 | tend = toff + tlen |
| 384 | if mend < buflen and tend < buflen: |
| 385 | msg = buf[moff:mend] |
| 386 | tmsg = buf[toff:tend] |
| 387 | else: |
| 388 | raise OSError(0, 'File is corrupt', filename) |
| 389 | # See if we're looking at GNU .mo conventions for metadata |
| 390 | if mlen == 0: |
no outgoing calls