1607 | | Download [http://www.opensubtitles.org/addons/download/oshash-example.zip example]. Key is using Javascript LONG library. Thanks to [http://divhide.com/ Oscar Brito] for fixing the code. Check also https://github.com/ka2er/node-opensubtitles-api/blob/master/lib/opensubtitles.js#L36 |
1608 | | |
1609 | | {{{ |
1610 | | //be sure Long.min.js is already included |
1611 | | /* |
1612 | | * Calculate OpenSubtitles hash |
1613 | | * (Oscar Brito - aetheon@gmail.com) |
1614 | | * |
1615 | | * @param {File} file - a File obj contained on a DataTransfer |
1616 | | * @param {Function} onComplete - the result callback |
1617 | | */ |
1618 | | var OpenSubtitlesHash = function(file, onComplete){ |
1619 | | |
1620 | | var HASH_CHUNK_SIZE = 64 * 1024; |
1621 | | if(file.size<HASH_CHUNK_SIZE) |
1622 | | HASH_CHUNK_SIZE = file.size; |
1623 | | |
1624 | | |
1625 | | // sum chunk long values |
1626 | | var sumChunk = function(arrayBuffer){ |
1627 | | |
1628 | | var view = new DataView(arrayBuffer); |
1629 | | var hNumber = new dcodeIO.Long(); |
1630 | | |
1631 | | for(var i=0; i<arrayBuffer.byteLength; i+=8){ |
1632 | | |
1633 | | var low = view.getUint32(i, true); |
1634 | | var high = view.getUint32(i+4, true); |
1635 | | |
1636 | | var n = new dcodeIO.Long(low, high); |
1637 | | hNumber = hNumber.add(n); |
| 1607 | There is some WRONG implementations floating around, please always check correct hash codes with test files at start of this document. This implementation works fine, credits go to Rasmus - THANKS! |
| 1608 | |
| 1609 | {{{ |
| 1610 | function(file, callback) { |
| 1611 | var HASH_CHUNK_SIZE = 65536, //64 * 1024 |
| 1612 | longs = [], |
| 1613 | temp = file.size; |
| 1614 | |
| 1615 | function read(start, end, callback) { |
| 1616 | var reader = new FileReader(); |
| 1617 | reader.onload = function(e) { |
| 1618 | callback.call(reader, process(e.target.result)); |
| 1619 | }; |
| 1620 | |
| 1621 | if (end === undefined) { |
| 1622 | reader.readAsBinaryString(file.slice(start)); |
| 1623 | } else { |
| 1624 | reader.readAsBinaryString(file.slice(start, end)); |
1639 | | |
1640 | | return hNumber; |
1641 | | |
1642 | | }; |
1643 | | |
1644 | | |
1645 | | // read chunk |
1646 | | var readChunk = function(start, end, callback){ |
1647 | | |
1648 | | var reader = new FileReader(); |
1649 | | reader.onload = function(e){ |
1650 | | |
1651 | | // sum all long values on the chunk |
1652 | | var number = sumChunk(e.currentTarget.result); |
1653 | | |
1654 | | if(callback) |
1655 | | callback(number); |
1656 | | |
| 1626 | } |
| 1627 | |
| 1628 | function process(chunk) { |
| 1629 | for (var i = 0; i < chunk.length; i++) { |
| 1630 | longs[(i + 8) % 8] += chunk.charCodeAt(i); |
1658 | | |
1659 | | var blob = file.slice(start, end); |
1660 | | reader.readAsArrayBuffer(blob); |
1661 | | }; |
1662 | | |
1663 | | |
1664 | | // read the first chunk |
1665 | | readChunk(0, HASH_CHUNK_SIZE, function(head){ |
1666 | | |
1667 | | // read the tail chunk |
1668 | | var start = file.size-HASH_CHUNK_SIZE; |
1669 | | if(start < 0) |
1670 | | start = 0; |
1671 | | |
1672 | | readChunk(start, file.size, function(tail){ |
1673 | | |
1674 | | // sum all values |
1675 | | var sum = head.add(tail).add(new dcodeIO.Long(file.size)); |
1676 | | // convert to hex |
1677 | | var sumHex = sum.toString(16); |
1678 | | |
1679 | | if(onComplete) |
1680 | | onComplete(sumHex); |
1681 | | |
| 1632 | } |
| 1633 | |
| 1634 | function binl2hex(a) { |
| 1635 | var b = 255, |
| 1636 | d = '0123456789abcdef', |
| 1637 | e = '', |
| 1638 | c = 7; |
| 1639 | |
| 1640 | a[1] += a[0] >> 8; |
| 1641 | a[0] = a[0] & b; |
| 1642 | a[2] += a[1] >> 8; |
| 1643 | a[1] = a[1] & b; |
| 1644 | a[3] += a[2] >> 8; |
| 1645 | a[2] = a[2] & b; |
| 1646 | a[4] += a[3] >> 8; |
| 1647 | a[3] = a[3] & b; |
| 1648 | a[5] += a[4] >> 8; |
| 1649 | a[4] = a[4] & b; |
| 1650 | a[6] += a[5] >> 8; |
| 1651 | a[5] = a[5] & b; |
| 1652 | a[7] += a[6] >> 8; |
| 1653 | a[6] = a[6] & b; |
| 1654 | a[7] = a[7] & b; |
| 1655 | for (d, e, c; c > -1; c--) { |
| 1656 | e += d.charAt(a[c] >> 4 & 15) + d.charAt(a[c] & 15); |
| 1657 | } |
| 1658 | return e; |
| 1659 | } |
| 1660 | |
| 1661 | |
| 1662 | for (var i = 0; i < 8; i++) { |
| 1663 | longs[i] = temp & 255; |
| 1664 | temp = temp >> 8; |
| 1665 | } |
| 1666 | |
| 1667 | read(0, HASH_CHUNK_SIZE, function() { |
| 1668 | read(file.size - HASH_CHUNK_SIZE, undefined, function() { |
| 1669 | callback.call(null, file, binl2hex(longs)); |